diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000000000000000000000000000000000000..f5f8f6082698f3167fa36b14058fcdb958f9eb2c
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,2 @@
+# pre-commit run -a (Guilhem Saurel, 2022-07-27)
+db4d991c9d727b8454695ce8d88948b948c6b36f
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 55356e3acca4a58d92d2780999646f340290fbad..5ea131e08633893bc4c55ed1869b426f1b0d2e4e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -33,3 +33,7 @@ repos:
     rev: 5.0.4
     hooks:
     -   id: flake8
+-   repo: https://github.com/cheshirekow/cmake-format-precommit
+    rev: v0.6.13
+    hooks:
+    - id: cmake-format
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6e97429fbfd37f49281bfa339950cf6caddb1872..ddb3d851e5756ea8f91df282aded397f41bcb20a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,87 +1,85 @@
-# Copyright 2010-2020, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem Saurel, JRL, CNRS/AIST, LAAS-CNRS
+# Copyright 2010-2020, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem
+# Saurel, JRL, CNRS/AIST, LAAS-CNRS
 
-CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1)
 
 # Project properties
-SET(PROJECT_ORG stack-of-tasks)
-SET(PROJECT_NAME dynamic-graph-python)
-SET(PROJECT_DESCRIPTION "Dynamic graph library Python bindings")
-SET(PROJECT_URL "https://github.com/${PROJECT_ORG}/${PROJECT_NAME}")
+set(PROJECT_ORG stack-of-tasks)
+set(PROJECT_NAME dynamic-graph-python)
+set(PROJECT_DESCRIPTION "Dynamic graph library Python bindings")
+set(PROJECT_URL "https://github.com/${PROJECT_ORG}/${PROJECT_NAME}")
 
 # Project options
-OPTION(SUFFIX_SO_VERSION "Suffix library name with its version" ON)
+option(SUFFIX_SO_VERSION "Suffix library name with its version" ON)
 
 # Project configuration
-SET(PROJECT_USE_CMAKE_EXPORT TRUE)
-SET(CUSTOM_HEADER_DIR "dynamic-graph/python")
-SET(CXX_DISABLE_WERROR TRUE)
-SET(DOXYGEN_USE_MATHJAX YES)
+set(PROJECT_USE_CMAKE_EXPORT TRUE)
+set(CUSTOM_HEADER_DIR "dynamic-graph/python")
+set(CXX_DISABLE_WERROR TRUE)
+set(DOXYGEN_USE_MATHJAX YES)
 
 # JRL-cmakemodule setup
-INCLUDE(cmake/base.cmake)
-INCLUDE(cmake/boost.cmake)
-INCLUDE(cmake/python.cmake)
+include(cmake/base.cmake)
+include(cmake/boost.cmake)
 
 # Project definition
-COMPUTE_PROJECT_ARGS(PROJECT_ARGS LANGUAGES CXX)
-PROJECT(${PROJECT_NAME} ${PROJECT_ARGS})
-CHECK_MINIMAL_CXX_STANDARD(14 ENFORCE)
+compute_project_args(PROJECT_ARGS LANGUAGES CXX)
+project(${PROJECT_NAME} ${PROJECT_ARGS})
+check_minimal_cxx_standard(14 ENFORCE)
 
 # Project dependencies
-FINDPYTHON()
-
-ADD_PROJECT_DEPENDENCY(dynamic-graph 4.4.0 REQUIRED)
-ADD_PROJECT_DEPENDENCY(eigenpy REQUIRED)
-SEARCH_FOR_BOOST_PYTHON(REQUIRED)
-IF(BUILD_TESTING)
-  FIND_PACKAGE(Boost REQUIRED COMPONENTS unit_test_framework)
-ENDIF(BUILD_TESTING)
-
-IF(Boost_VERSION GREATER 107299 OR Boost_VERSION_MACRO GREATER 107299)
+add_project_dependency(dynamic-graph 4.4.0 REQUIRED)
+add_project_dependency(eigenpy 2.7.10 REQUIRED)
+include(cmake/python.cmake) # TODO: overwriting eigenpy/python.cmake
+if(BUILD_TESTING)
+  find_package(Boost REQUIRED COMPONENTS unit_test_framework)
+endif(BUILD_TESTING)
+
+if(Boost_VERSION GREATER 107299 OR Boost_VERSION_MACRO GREATER 107299)
   # Silence a warning about a deprecated use of boost bind by boost >= 1.73
   # without dropping support for boost < 1.73
-  ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)
-ENDIF()
+  add_definitions(-DBOOST_BIND_GLOBAL_PLACEHOLDERS)
+endif()
 
 # Main Library
-SET(${PROJECT_NAME}_HEADERS
-  include/${CUSTOM_HEADER_DIR}/api.hh
-  include/${CUSTOM_HEADER_DIR}/convert-dg-to-py.hh
-  include/${CUSTOM_HEADER_DIR}/dynamic-graph-py.hh
-  include/${CUSTOM_HEADER_DIR}/fwd.hh
-  include/${CUSTOM_HEADER_DIR}/interpreter.hh
-  include/${CUSTOM_HEADER_DIR}/module.hh
-  include/${CUSTOM_HEADER_DIR}/python-compat.hh
-  include/${CUSTOM_HEADER_DIR}/signal.hh
-  include/${CUSTOM_HEADER_DIR}/signal-wrapper.hh
-  )
-
-SET(${PROJECT_NAME}_SOURCES
-  src/interpreter.cc
-  src/dynamic_graph/python-compat.cc
-  src/dynamic_graph/entity-py.cc
-  src/dynamic_graph/convert-dg-to-py.cc
-  )
-
-ADD_LIBRARY(${PROJECT_NAME} SHARED
-  ${${PROJECT_NAME}_SOURCES} ${${PROJECT_NAME}_HEADERS})
-TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} SYSTEM PUBLIC ${PYTHON_INCLUDE_DIR})
-TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} PUBLIC $<INSTALL_INTERFACE:include>)
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} PUBLIC ${PYTHON_LIBRARY}
-  dynamic-graph::dynamic-graph)
-TARGET_LINK_BOOST_PYTHON(${PROJECT_NAME} PRIVATE)
-
-IF(SUFFIX_SO_VERSION)
-  SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
-ENDIF(SUFFIX_SO_VERSION)
-
-TARGET_COMPILE_DEFINITIONS(${PROJECT_NAME} PRIVATE PYTHON_LIBRARY="${PYTHON_LIBRARY}")
-
-INSTALL(TARGETS ${PROJECT_NAME} EXPORT ${TARGETS_EXPORT_NAME} DESTINATION lib)
-
-ADD_SUBDIRECTORY(src)
-IF(BUILD_TESTING)
-  ADD_SUBDIRECTORY(tests)
-ENDIF(BUILD_TESTING)
-
-INSTALL(FILES package.xml DESTINATION share/${PROJECT_NAME})
+set(${PROJECT_NAME}_HEADERS
+    include/${CUSTOM_HEADER_DIR}/api.hh
+    include/${CUSTOM_HEADER_DIR}/convert-dg-to-py.hh
+    include/${CUSTOM_HEADER_DIR}/dynamic-graph-py.hh
+    include/${CUSTOM_HEADER_DIR}/fwd.hh
+    include/${CUSTOM_HEADER_DIR}/interpreter.hh
+    include/${CUSTOM_HEADER_DIR}/module.hh
+    include/${CUSTOM_HEADER_DIR}/python-compat.hh
+    include/${CUSTOM_HEADER_DIR}/signal.hh
+    include/${CUSTOM_HEADER_DIR}/signal-wrapper.hh)
+
+set(${PROJECT_NAME}_SOURCES
+    src/interpreter.cc src/dynamic_graph/python-compat.cc
+    src/dynamic_graph/entity-py.cc src/dynamic_graph/convert-dg-to-py.cc)
+
+add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES}
+                                   ${${PROJECT_NAME}_HEADERS})
+target_include_directories(${PROJECT_NAME} PUBLIC $<INSTALL_INTERFACE:include>)
+target_link_libraries(
+  ${PROJECT_NAME} PUBLIC dynamic-graph::dynamic-graph
+                         Python${PYTHON_VERSION_MAJOR}::Python)
+target_link_boost_python(${PROJECT_NAME} PRIVATE)
+
+if(SUFFIX_SO_VERSION)
+  set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
+endif(SUFFIX_SO_VERSION)
+
+target_compile_definitions(${PROJECT_NAME}
+                           PRIVATE PYTHON_LIBRARY="${PYTHON_LIBRARY}")
+
+install(
+  TARGETS ${PROJECT_NAME}
+  EXPORT ${TARGETS_EXPORT_NAME}
+  DESTINATION lib)
+
+add_subdirectory(src)
+if(BUILD_TESTING)
+  add_subdirectory(tests)
+endif(BUILD_TESTING)
+
+install(FILES package.xml DESTINATION share/${PROJECT_NAME})
diff --git a/cmake b/cmake
index 332976cc4d5305256c79a479e55ad7ab2ecc42f1..a7567987b03fcad59e68aa9c4bf4580af7551144 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit 332976cc4d5305256c79a479e55ad7ab2ecc42f1
+Subproject commit a7567987b03fcad59e68aa9c4bf4580af7551144
diff --git a/doc/package.dox.cmake b/doc/package.dox.in
similarity index 100%
rename from doc/package.dox.cmake
rename to doc/package.dox.in
diff --git a/package.xml b/package.xml
index 38982608e83b466fc1bb84310398a92134f34b84..c73d7253c268c0269f26a7f1fdff914defacb862 100644
--- a/package.xml
+++ b/package.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <package format="3">
   <name>dynamic-graph-python</name>
-  <version>4.0.5</version>
+  <version>4.0.6</version>
   <description>
     Dynamic graph library Python bindings
   </description>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 98a95a689d37565dd64eba19566ac635219576fb..965b1d3cd2c3a61825f1ee4d3f86cac3609b0fe5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,23 +1,20 @@
-#  Python bindings
+# Python bindings
 
-ADD_SUBDIRECTORY(dynamic_graph)
+add_subdirectory(dynamic_graph)
 
-SET(PYTHON_SOURCES
-  __init__.py
-  attrpath.py
-  entity.py
-  signal_base.py
-  script_shortcuts.py
-  tools.py
-  )
+set(PYTHON_SOURCES __init__.py attrpath.py entity.py signal_base.py
+                   script_shortcuts.py tools.py)
 
-FOREACH(source ${PYTHON_SOURCES})
-  PYTHON_INSTALL_ON_SITE(dynamic_graph ${source})
-ENDFOREACH(source)
+foreach(source ${PYTHON_SOURCES})
+  python_install_on_site(dynamic_graph ${source})
+endforeach(source)
 
 # --- ADD the wrap on the dg modules
-LINK_DIRECTORIES(${DYNAMIC_GRAPH_PLUGINDIR})
-DYNAMIC_GRAPH_PYTHON_MODULE("tracer" dynamic-graph::tracer tracer-wrap
-  SOURCE_PYTHON_MODULE ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_graph/tracer/wrap.cc)
-DYNAMIC_GRAPH_PYTHON_MODULE("tracer_real_time" dynamic-graph::tracer-real-time tracer_real_time-wrap
-  SOURCE_PYTHON_MODULE ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_graph/tracer_real_time/wrap.cc)
+link_directories(${DYNAMIC_GRAPH_PLUGINDIR})
+dynamic_graph_python_module(
+  "tracer" dynamic-graph::tracer tracer-wrap SOURCE_PYTHON_MODULE
+  ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_graph/tracer/wrap.cc)
+dynamic_graph_python_module(
+  "tracer_real_time" dynamic-graph::tracer-real-time tracer_real_time-wrap
+  SOURCE_PYTHON_MODULE
+  ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_graph/tracer_real_time/wrap.cc)
diff --git a/src/dynamic_graph/CMakeLists.txt b/src/dynamic_graph/CMakeLists.txt
index 139b31566cf4c8bdd66cf25719d174462eaf020f..00c91d1288ca0ac0a5224177ff964667cc12530a 100644
--- a/src/dynamic_graph/CMakeLists.txt
+++ b/src/dynamic_graph/CMakeLists.txt
@@ -1,26 +1,24 @@
-# Copyright 2010-2021, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem Saurel, JRL, CNRS/AIST, LAAS-CNRS
+# Copyright 2010-2021, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem
+# Saurel, JRL, CNRS/AIST, LAAS-CNRS
 
-SET(PYTHON_MODULE wrap)
+set(PYTHON_MODULE wrap)
 
-ADD_LIBRARY(${PYTHON_MODULE} MODULE
-  debug-py.cc
-  dynamic-graph-py.cc
-  factory-py.cc
-  pool-py.cc
-  signal-base-py.cc
-  signal-wrapper.cc
-  )
+add_library(
+  ${PYTHON_MODULE} MODULE debug-py.cc dynamic-graph-py.cc factory-py.cc
+                          pool-py.cc signal-base-py.cc signal-wrapper.cc)
 
-TARGET_LINK_LIBRARIES(${PYTHON_MODULE} PUBLIC ${PROJECT_NAME} eigenpy::eigenpy)
-TARGET_LINK_BOOST_PYTHON(${PYTHON_MODULE} PRIVATE)
+target_link_libraries(${PYTHON_MODULE} PUBLIC ${PROJECT_NAME} eigenpy::eigenpy)
+target_link_boost_python(${PYTHON_MODULE} PRIVATE)
 
 # Remove prefix lib
-SET_TARGET_PROPERTIES(${PYTHON_MODULE} PROPERTIES PREFIX "")
+set_target_properties(${PYTHON_MODULE} PROPERTIES PREFIX "")
 
-IF(UNIX AND NOT APPLE)
-  SET_TARGET_PROPERTIES(${PYTHON_MODULE} PROPERTIES INSTALL_RPATH "\$ORIGIN/../../..")
-ENDIF()
+if(UNIX AND NOT APPLE)
+  set_target_properties(${PYTHON_MODULE} PROPERTIES INSTALL_RPATH
+                                                    "\$ORIGIN/../../..")
+endif()
 
-INSTALL(TARGETS ${PYTHON_MODULE}
+install(
+  TARGETS ${PYTHON_MODULE}
   EXPORT ${TARGETS_EXPORT_NAME}
   DESTINATION ${PYTHON_SITELIB}/dynamic_graph)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5ca0cb2b78a2d80bd3ccde5c081f48ff00a8f90e..91146c6eae21de31e7e65e5b063efd918410f780 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,58 +1,56 @@
-# Copyright 2010-2020, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem Saurel, JRL, CNRS/AIST, LAAS-CNRS
+# Copyright 2010-2020, Florent Lamiraux, Thomas Moulard, Olivier Stasse, Guilhem
+# Saurel, JRL, CNRS/AIST, LAAS-CNRS
 
 # Test the interpreter
-ADD_UNIT_TEST(interpreter-test interpreter-test.cc)
-TARGET_LINK_LIBRARIES(interpreter-test PRIVATE ${PROJECT_NAME})
+add_unit_test(interpreter-test interpreter-test.cc)
+target_link_libraries(interpreter-test PRIVATE ${PROJECT_NAME})
 
 # Test runfile
-ADD_UNIT_TEST(interpreter-test-runfile interpreter-test-runfile.cc)
-TARGET_LINK_LIBRARIES(interpreter-test-runfile PRIVATE ${PROJECT_NAME})
-TARGET_INCLUDE_DIRECTORIES(interpreter-test-runfile PRIVATE Boost::unit_test_framework)
-TARGET_COMPILE_DEFINITIONS(interpreter-test-runfile PRIVATE PATH="${CMAKE_CURRENT_LIST_DIR}/")
+add_unit_test(interpreter-test-runfile interpreter-test-runfile.cc)
+target_link_libraries(interpreter-test-runfile PRIVATE ${PROJECT_NAME})
+target_include_directories(interpreter-test-runfile
+                           PRIVATE Boost::unit_test_framework)
+target_compile_definitions(interpreter-test-runfile
+                           PRIVATE PATH="${CMAKE_CURRENT_LIST_DIR}/")
 
-# Test the module generation
-## Create an entity
+# Test the module generation Create an entity
 
-SET(LIBRARY_NAME "custom_entity")
-ADD_LIBRARY(${LIBRARY_NAME} SHARED "${LIBRARY_NAME}.cpp")
-IF(SUFFIX_SO_VERSION)
-  SET_TARGET_PROPERTIES(${LIBRARY_NAME}
-    PROPERTIES SOVERSION ${PROJECT_VERSION})
-ENDIF(SUFFIX_SO_VERSION)
+set(LIBRARY_NAME "custom_entity")
+add_library(${LIBRARY_NAME} SHARED "${LIBRARY_NAME}.cpp")
+if(SUFFIX_SO_VERSION)
+  set_target_properties(${LIBRARY_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION})
+endif(SUFFIX_SO_VERSION)
 
 target_link_libraries(${LIBRARY_NAME} PRIVATE dynamic-graph::dynamic-graph)
 
-## Create its bindings
-## This mimics DYNAMIC_GRAPH_PYTHON_MODULE(${LIBRARY_NAME} ${LIBRARY_NAME} "${LIBRARY_NAME}-wrap")
+# Create its bindings This mimics DYNAMIC_GRAPH_PYTHON_MODULE(${LIBRARY_NAME}
+# ${LIBRARY_NAME} "${LIBRARY_NAME}-wrap")
 
-CONFIGURE_FILE(
-  ${PROJECT_SOURCE_DIR}/cmake/dynamic_graph/submodule/__init__.py.cmake
-  ${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}/__init__.py
-  )
-SET(PYTHON_MODULE "${LIBRARY_NAME}-wrap")
-set(DYNAMICGRAPH_MODULE_HEADER "${CMAKE_SOURCE_DIR}/tests/custom_entity_module.h")
 configure_file(
-  ${PROJECT_SOURCE_DIR}/cmake/dynamic_graph/python-module-py.cc.in
-  ${CMAKE_CURRENT_BINARY_DIR}/python-module-py.cc
-  @ONLY
-  )
-ADD_LIBRARY(${PYTHON_MODULE} MODULE ${CMAKE_CURRENT_BINARY_DIR}/python-module-py.cc)
-SET_TARGET_PROPERTIES(${PYTHON_MODULE} PROPERTIES
-  PREFIX ""
-  OUTPUT_NAME ${LIBRARY_NAME}/wrap)
-
-IF(UNIX AND NOT APPLE)
-  TARGET_LINK_LIBRARIES(${PYTHON_MODULE} PRIVATE "-Wl,--no-as-needed")
-ENDIF(UNIX AND NOT APPLE)
-
-TARGET_LINK_LIBRARIES(${PYTHON_MODULE} PRIVATE
-  ${LIBRARY_NAME} dynamic-graph-python
-  ${PYTHON_LIBRARY})
-TARGET_LINK_BOOST_PYTHON(${PYTHON_MODULE} PRIVATE)
-TARGET_INCLUDE_DIRECTORIES(${PYTHON_MODULE} SYSTEM PRIVATE ${PYTHON_INCLUDE_DIRS})
-
-## Test it
-ADD_PYTHON_UNIT_TEST("test-custom-entity" "tests/test_custom_entity.py" src tests)
+  ${PROJECT_SOURCE_DIR}/cmake/dynamic_graph/submodule/__init__.py.cmake
+  ${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}/__init__.py)
+set(PYTHON_MODULE "${LIBRARY_NAME}-wrap")
+set(DYNAMICGRAPH_MODULE_HEADER
+    "${CMAKE_SOURCE_DIR}/tests/custom_entity_module.h")
+configure_file(${PROJECT_SOURCE_DIR}/cmake/dynamic_graph/python-module-py.cc.in
+               ${CMAKE_CURRENT_BINARY_DIR}/python-module-py.cc @ONLY)
+add_library(${PYTHON_MODULE} MODULE
+            ${CMAKE_CURRENT_BINARY_DIR}/python-module-py.cc)
+set_target_properties(${PYTHON_MODULE}
+                      PROPERTIES PREFIX "" OUTPUT_NAME ${LIBRARY_NAME}/wrap)
+
+if(UNIX AND NOT APPLE)
+  target_link_libraries(${PYTHON_MODULE} PRIVATE "-Wl,--no-as-needed")
+endif(UNIX AND NOT APPLE)
+
+target_link_libraries(${PYTHON_MODULE} PRIVATE ${LIBRARY_NAME} ${PROJECT_NAME})
+target_link_boost_python(${PYTHON_MODULE} PRIVATE)
+target_include_directories(${PYTHON_MODULE} SYSTEM
+                           PRIVATE ${PYTHON_INCLUDE_DIRS})
+
+# Test it
+add_python_unit_test("test-custom-entity" "tests/test_custom_entity.py" src
+                     tests)
 
 # also test other bindings, using this custom entity
-ADD_PYTHON_UNIT_TEST("test-bindings" "tests/test_bindings.py" src tests)
+add_python_unit_test("test-bindings" "tests/test_bindings.py" src tests)