diff --git a/CMakeLists.txt b/CMakeLists.txt
index 87286141c0aaaefae48b4dec00a6cfa57d116b7e..f1f83fdb99f2713f0f8895660a9cf60f7c84f0ca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,15 +1,14 @@
 #
-# Copyright (c) 2014-2019 CNRS
+# Copyright (c) 2014-2020 CNRS
 # Copyright (c) 2018-2020 INRIA
 #
 
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
 
 SET(PROJECT_NAME eigenpy)
 SET(PROJECT_DESCRIPTION "Bindings between Numpy and Eigen using Boost.Python")
 SET(PROJECT_URL "http://github.com/stack-of-tasks/eigenpy")
 SET(PROJECT_USE_CMAKE_EXPORT TRUE)
-SET(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE)
 SET(PROJECT_CUSTOM_HEADER_EXTENSION "hpp")
 
 # Check if the submodule cmake have been initialized
@@ -35,16 +34,9 @@ STRING(REPLACE "-pedantic" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
 # If needed, fix CMake policy for APPLE systems
 APPLY_DEFAULT_APPLE_CONFIGURATION()
 
-IF(WIN32)
-  SET(LINK copy_if_different)
-ELSE(WIN32)
-  SET(LINK create_symlink)
-ENDIF(WIN32)
-
 # ----------------------------------------------------
 # --- OPTIONS  ---------------------------------------
 # ----------------------------------------------------
-OPTION(INSTALL_DOCUMENTATION "Generate and install the documentation" FALSE)
 OPTION(SUFFIX_SO_VERSION "Suffix library name with its version" OFF)
 
 IF(DEFINED BUILD_UNIT_TESTS)
@@ -54,19 +46,35 @@ IF(DEFINED BUILD_UNIT_TESTS)
   SET(BUILD_TESTING ${BUILD_UNIT_TESTS})
 ENDIF(DEFINED BUILD_UNIT_TESTS)
 
-FINDPYTHON()
-FIND_NUMPY()
-
 IF(WIN32)
   LINK_DIRECTORIES(${PYTHON_LIBRARY_DIRS})
 ENDIF(WIN32)
 
+SET(PYWRAP "${PROJECT_NAME}_pywrap")
+
 # ----------------------------------------------------
 # --- DEPENDENCIES -----------------------------------
 # ----------------------------------------------------
-ADD_PROJECT_DEPENDENCY(Eigen3 REQUIRED PKG_CONFIG_REQUIRES "eigen3 >= 3.0.5")
+ADD_PROJECT_DEPENDENCY(Eigen3 REQUIRED)
+
+IF(BUILD_PYTHON_INTERFACE)
+  FINDPYTHON()
+  FIND_NUMPY()
+  SEARCH_FOR_BOOST_PYTHON(REQUIRED)
+ENDIF(BUILD_PYTHON_INTERFACE)
+
+# ----------------------------------------------------
+# --- INTERFACE --------------------------------------
+# ----------------------------------------------------
+ADD_LIBRARY(${PROJECT_NAME} INTERFACE)
+TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME}
+  SYSTEM INTERFACE
+  ${Boost_INCLUDE_DIRS}
+  ${EIGEN3_INCLUDE_DIR}
+  INTERFACE
+  $<INSTALL_INTERFACE:include>)
 
-SEARCH_FOR_BOOST_PYTHON()
+INSTALL(TARGETS ${PROJECT_NAME} EXPORT ${TARGETS_EXPORT_NAME} DESTINATION lib)
 
 # ----------------------------------------------------
 # --- INCLUDE ----------------------------------------
@@ -143,7 +151,7 @@ SET(${PROJECT_NAME}_SOLVERS_SOURCES
 SET(${PROJECT_NAME}_DECOMPOSITIONS_SOURCES
   src/decompositions/decompositions.cpp
   )
-  
+
 SET(${PROJECT_NAME}_SOURCES
   ${${PROJECT_NAME}_SOLVERS_SOURCES}
   ${${PROJECT_NAME}_DECOMPOSITIONS_SOURCES}
@@ -166,52 +174,50 @@ SET(${PROJECT_NAME}_SOURCES
   src/version.cpp
 )
 
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES} ${${PROJECT_NAME}_HEADERS})
-TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} 
-  SYSTEM PUBLIC 
-  ${Boost_INCLUDE_DIRS} 
-  ${EIGEN3_INCLUDE_DIR}
-  ${PYTHON_INCLUDE_DIRS} 
-  ${NUMPY_INCLUDE_DIRS}
-  $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
-  $<INSTALL_INTERFACE:include>)
-
-IF(SUFFIX_SO_VERSION)
-  SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
-ENDIF(SUFFIX_SO_VERSION)
-
-IF(NOT WIN32)
-  TARGET_COMPILE_OPTIONS(${PROJECT_NAME} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:-bigobj> "-Wno-conversion")
-ELSE()
-  TARGET_COMPILE_OPTIONS(${PROJECT_NAME} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:-bigobj>)
-ENDIF()
-
-TARGET_LINK_BOOST_PYTHON(${PROJECT_NAME} PUBLIC)
-INSTALL(TARGETS ${PROJECT_NAME}
-  EXPORT ${TARGETS_EXPORT_NAME}
-  PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}
-  INCLUDES DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}
-  LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
-  ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
-  RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
-
 ADD_HEADER_GROUP(${PROJECT_NAME}_HEADERS)
 ADD_SOURCE_GROUP(${PROJECT_NAME}_SOURCES)
 
-# Install package for ROS
-install(FILES package.xml DESTINATION share/eigenpy)
-
-# ----------------------------------------------------
-# --- PYTHON LIBRARY ---------------------------------
-# ----------------------------------------------------
-ADD_SUBDIRECTORY(python)
-
-# ----------------------------------------------------
-# --- UNIT TEST --------------------------------------
-# ----------------------------------------------------
-ADD_SUBDIRECTORY(unittest)
+IF(BUILD_PYTHON_INTERFACE)
+  ADD_LIBRARY(${PY_PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES} ${${PROJECT_NAME}_HEADERS})
+  TARGET_LINK_LIBRARIES(${PY_PROJECT_NAME} PUBLIC ${PROJECT_NAME})
+  TARGET_INCLUDE_DIRECTORIES(${PY_PROJECT_NAME}
+    SYSTEM PUBLIC
+    ${PYTHON_INCLUDE_DIR}
+    ${NUMPY_INCLUDE_DIRS})
+
+  IF(SUFFIX_SO_VERSION)
+    SET_TARGET_PROPERTIES(${PY_PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
+  ENDIF(SUFFIX_SO_VERSION)
+
+  IF(NOT WIN32)
+    TARGET_COMPILE_OPTIONS(${PY_PROJECT_NAME} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:-bigobj> "-Wno-conversion")
+  ELSE()
+    TARGET_COMPILE_OPTIONS(${PY_PROJECT_NAME} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:-bigobj>)
+  ENDIF()
+
+  TARGET_LINK_BOOST_PYTHON(${PY_PROJECT_NAME} PRIVATE)
+  INSTALL(TARGETS ${PY_PROJECT_NAME}
+    EXPORT ${TARGETS_EXPORT_PY_NAME}
+    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}
+    INCLUDES DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
+    RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
+
+  PROJECT_INSTALL_COMPONENT(${PY_PROJECT_NAME})
+
+  # ----------------------------------------------------
+  # --- PYTHON LIBRARY ---------------------------------
+  # ----------------------------------------------------
+  ADD_SUBDIRECTORY(python)
+
+  # ----------------------------------------------------
+  # --- UNIT TEST --------------------------------------
+  # ----------------------------------------------------
+  ADD_SUBDIRECTORY(unittest)
+ENDIF()
 
-PKG_CONFIG_APPEND_LIBS(${PROJECT_NAME})
-PKG_CONFIG_APPEND_CFLAGS("-I${PYTHON_INCLUDE_DIRS}")
-PKG_CONFIG_APPEND_CFLAGS("-I${NUMPY_INCLUDE_DIRS}")
-PKG_CONFIG_APPEND_BOOST_LIBS(${BOOST_COMPONENTS})
+IF(NOT INSTALL_PYTHON_INTERFACE_ONLY)
+  # Install package for ROS
+  install(FILES package.xml DESTINATION "share/${PROJECT_NAME}")
+ENDIF()
diff --git a/cmake b/cmake
index f4fca276f9feaaea1ef9b866df32f8a263a35501..d5fd2cc10afc094e9cb1d4db3051cb5e4d437ac2 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit f4fca276f9feaaea1ef9b866df32f8a263a35501
+Subproject commit d5fd2cc10afc094e9cb1d4db3051cb5e4d437ac2
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 12430ef309300669aca08eb21f2c35143ebffe80..2d381fcd806989e5b980edf73f15c20623cf12ef 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -3,17 +3,12 @@
 #
 
 # --- LIBRARY --- #
-SET(PYWRAP ${PROJECT_NAME}_pywrap) 
-SET(PYWRAP ${PYWRAP} PARENT_SCOPE)
-
-MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}")
-
 ADD_CUSTOM_TARGET(python)
 SET_TARGET_PROPERTIES(python PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD True)
 
 ADD_LIBRARY(${PYWRAP} SHARED main.cpp)
 ADD_DEPENDENCIES(python ${PYWRAP})
-TARGET_LINK_LIBRARIES(${PYWRAP} PUBLIC ${PROJECT_NAME}) 
+TARGET_LINK_LIBRARIES(${PYWRAP} PUBLIC ${PY_PROJECT_NAME})
 # BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS spews conversion warnings from int to long unsigned int.
 # Unfortunately, using literals does not work in a macro. As such, this turns them off for the entire wrapper:
 IF(NOT WIN32)
@@ -26,7 +21,7 @@ ELSE()
 ENDIF()
 
 SET_TARGET_PROPERTIES(${PYWRAP}
-  PROPERTIES 
+  PROPERTIES
   PREFIX ""
   SUFFIX ${PYTHON_EXT_SUFFIX}
   OUTPUT_NAME "${PROJECT_NAME}"
@@ -35,14 +30,11 @@ SET_TARGET_PROPERTIES(${PYWRAP}
 
 INSTALL(TARGETS ${PYWRAP} DESTINATION ${${PYWRAP}_INSTALL_DIR})
 
-# --- INSTALL SCRIPTS 
+# --- INSTALL SCRIPTS
 SET(PYTHON_FILES
   __init__.py
   )
 
 FOREACH(python ${PYTHON_FILES})
-  INSTALL(FILES
-    "${CMAKE_CURRENT_SOURCE_DIR}/eigenpy/${python}"
-    DESTINATION ${${PYWRAP}_INSTALL_DIR})
+  PYTHON_INSTALL_ON_SITE("${PROJECT_NAME}" "${python}")
 ENDFOREACH(python)
-
diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt
index 4fd09e3239cee8d9234d0a41097ffb9699f20e4c..0fad240845803119871b01f89111fdc4efcda582 100644
--- a/unittest/CMakeLists.txt
+++ b/unittest/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014-2019 CNRS
+# Copyright (c) 2014-2020 CNRS
 # Copyright (c) 2018-2020 INRIA
 #
 
@@ -12,7 +12,7 @@ MACRO(ADD_LIB_UNIT_TEST test)
     ADD_LIBRARY(${test} SHARED EXCLUDE_FROM_ALL ${test})
   ENDIF(BUILD_TESTING)
 
-  TARGET_LINK_LIBRARIES(${test} PUBLIC ${PROJECT_NAME})
+  TARGET_LINK_LIBRARIES(${test} PUBLIC ${PY_PROJECT_NAME})
   SET_TARGET_PROPERTIES(${test} PROPERTIES PREFIX "")
 
   SET_TARGET_PROPERTIES(${test} PROPERTIES SUFFIX ${PYTHON_EXT_SUFFIX})
@@ -41,23 +41,23 @@ ADD_PYTHON_UNIT_TEST("py-return-by-ref" "unittest/python/test_return_by_ref.py"
 ADD_PYTHON_UNIT_TEST("py-eigen-ref" "unittest/python/test_eigen_ref.py" "unittest")
 ADD_PYTHON_UNIT_TEST("py-user-type" "unittest/python/test_user_type.py" "unittest")
 
-ADD_PYTHON_UNIT_TEST("py-switch" "unittest/python/test_switch.py" "python/eigenpy;unittest")
+ADD_PYTHON_UNIT_TEST("py-switch" "unittest/python/test_switch.py" "python;unittest")
 SET_TESTS_PROPERTIES("py-switch" PROPERTIES DEPENDS ${PYWRAP})
 
-ADD_PYTHON_UNIT_TEST("py-dimensions" "unittest/python/test_dimensions.py" "python/eigenpy;unittest")
+ADD_PYTHON_UNIT_TEST("py-dimensions" "unittest/python/test_dimensions.py" "python;unittest")
 SET_TESTS_PROPERTIES("py-dimensions" PROPERTIES DEPENDS ${PYWRAP})
 
-ADD_PYTHON_UNIT_TEST("py-version" "unittest/python/test_version.py" "python/eigenpy;unittest")
+ADD_PYTHON_UNIT_TEST("py-version" "unittest/python/test_version.py" "python;unittest")
 SET_TESTS_PROPERTIES("py-version" PROPERTIES DEPENDS ${PYWRAP})
 
-ADD_PYTHON_UNIT_TEST("py-eigen-solver" "unittest/python/test_eigen_solver.py" "python/eigenpy;unittest")
+ADD_PYTHON_UNIT_TEST("py-eigen-solver" "unittest/python/test_eigen_solver.py" "python;unittest")
 SET_TESTS_PROPERTIES("py-eigen-solver" PROPERTIES DEPENDS ${PYWRAP})
 
-ADD_PYTHON_UNIT_TEST("py-self-adjoint-eigen-solver" "unittest/python/test_self_adjoint_eigen_solver.py" "python/eigenpy;unittest")
+ADD_PYTHON_UNIT_TEST("py-self-adjoint-eigen-solver" "unittest/python/test_self_adjoint_eigen_solver.py" "python;unittest")
 SET_TESTS_PROPERTIES("py-self-adjoint-eigen-solver" PROPERTIES DEPENDS ${PYWRAP})
 
-ADD_PYTHON_UNIT_TEST("py-LLT" "unittest/python/test_LLT.py" "python/eigenpy;unittest")
+ADD_PYTHON_UNIT_TEST("py-LLT" "unittest/python/test_LLT.py" "python;unittest")
 SET_TESTS_PROPERTIES("py-LLT" PROPERTIES DEPENDS ${PYWRAP})
 
-ADD_PYTHON_UNIT_TEST("py-LDLT" "unittest/python/test_LDLT.py" "python/eigenpy;unittest")
+ADD_PYTHON_UNIT_TEST("py-LDLT" "unittest/python/test_LDLT.py" "python;unittest")
 SET_TESTS_PROPERTIES("py-LDLT" PROPERTIES DEPENDS ${PYWRAP})