From c81dd85c3db228b3e83a8ecde25d551be7116372 Mon Sep 17 00:00:00 2001
From: jcarpent <jcarpent@laas.fr>
Date: Tue, 17 Oct 2017 21:42:52 +0200
Subject: [PATCH] [CMake] Make EigenPy a full Python library

---
 CMakeLists.txt             | 70 ++++++++++++++++++++----------
 python/CMakeLists.txt      | 88 ++++++++++++++++++++++++++++++++++++++
 python/main.cpp            | 30 +++++++++++++
 python/scripts/__init__.py | 18 ++++++++
 4 files changed, 183 insertions(+), 23 deletions(-)
 create mode 100644 python/CMakeLists.txt
 create mode 100644 python/main.cpp
 create mode 100644 python/scripts/__init__.py

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8acb0ef3..627d0dcc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,6 +45,12 @@ IF(APPLE)
   ENDIF("${isSystemDir}" STREQUAL "-1")
 ENDIF(APPLE)
 
+IF(WIN32)
+  SET(LINK copy_if_different)
+ELSE(WIN32)
+  SET(LINK create_symlink)
+ENDIF(WIN32)
+
 # ----------------------------------------------------
 # --- OPTIONS  ---------------------------------------
 # ----------------------------------------------------
@@ -74,34 +80,47 @@ INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIRS})
 # --- INCLUDE ----------------------------------------
 # ----------------------------------------------------
 SET(HEADERS
-  src/eigenpy.hpp
-  src/exception.hpp
-  src/details.hpp
-  src/fwd.hpp
-  src/map.hpp
-  src/geometry.hpp
-  src/memory.hpp
-  src/registration.hpp
-  src/angle-axis.hpp
-  src/quaternion.hpp
+  eigenpy.hpp
+  exception.hpp
+  details.hpp
+  fwd.hpp
+  map.hpp
+  geometry.hpp
+  memory.hpp
+  registration.hpp
+  angle-axis.hpp
+  quaternion.hpp
 )
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/eigenpy")
 INCLUDE_DIRECTORIES(${${PROJECT_NAME}_BINARY_DIR}/include/eigenpy)
 
+#FOREACH(header ${HEADERS})
+#  GET_FILENAME_COMPONENT(headerName ${header} NAME)
+#  IF(WIN32)
+#    execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
+#                    ${${PROJECT_NAME}_SOURCE_DIR}/${header}
+#                    ${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/)
+#  ELSE(WIN32)
+#    execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
+#                    ${${PROJECT_NAME}_SOURCE_DIR}/${header}
+#                    ${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/${headerName})
+#  ENDIF(WIN32)
+#  INSTALL(FILES ${${PROJECT_NAME}_SOURCE_DIR}/${header}
+#	  DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}
+#          PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
+#ENDFOREACH(header)
+
+SET(${PROJECT_NAME}_HEADERS)
 FOREACH(header ${HEADERS})
   GET_FILENAME_COMPONENT(headerName ${header} NAME)
-  IF(WIN32)
-    execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
-                    ${${PROJECT_NAME}_SOURCE_DIR}/${header}
-                    ${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/)
-  ELSE(WIN32)
-    execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
-                    ${${PROJECT_NAME}_SOURCE_DIR}/${header}
-                    ${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/${headerName})
-  ENDIF(WIN32)
-  INSTALL(FILES ${${PROJECT_NAME}_SOURCE_DIR}/${header}
-	  DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}
-          PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
+  GET_FILENAME_COMPONENT(headerPath ${header} PATH)
+  EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E ${LINK}
+    ${${PROJECT_NAME}_SOURCE_DIR}/src/${header}
+    ${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/${header})
+  INSTALL(FILES ${${PROJECT_NAME}_SOURCE_DIR}/src/${header}
+    DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/${headerPath}
+          PERMISSIONS OWNER_READ GROUP_READ WORLD_READ OWNER_WRITE)
+  LIST(APPEND ${PROJECT_NAME}_HEADERS src/${header})
 ENDFOREACH(header)
 
 # ----------------------------------------------------
@@ -114,7 +133,7 @@ SET(${PROJECT_NAME}_SOURCES
   src/quaternion.cpp
 )
 
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES} ${HEADERS})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES} ${${PROJECT_NAME}_HEADERS})
 
 TARGET_LINK_BOOST_PYTHON(${PROJECT_NAME})
 PKG_CONFIG_USE_DEPENDENCY(${PROJECT_NAME} eigen3)
@@ -129,6 +148,11 @@ ADD_SUBDIRECTORY(unittest)
 # --- EXECUTABLES ------------------------------------
 # ----------------------------------------------------
 
+# ----------------------------------------------------
+# --- PYTHON BINDINGS --------------------------------
+# ----------------------------------------------------
+ADD_SUBDIRECTORY(python)
+
 IF(EIGEN_NUMPY_ALIGNED)
   PKG_CONFIG_APPEND_CFLAGS("-DEIGENPY_ALIGNED")
 ENDIF(EIGEN_NUMPY_ALIGNED)
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
new file mode 100644
index 00000000..9faeefcd
--- /dev/null
+++ b/python/CMakeLists.txt
@@ -0,0 +1,88 @@
+# 
+# Copyright (c) 2017 CNRS
+# 
+# This file is part of eigenpy
+# eigenpy is free software: you can redistribute it
+# and/or modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation, either version
+# 3 of the License, or (at your option) any later version.
+# eigenpy is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Lesser Public License for more details. You should have
+# received a copy of the GNU Lesser General Public License along with
+# eigenpy If not, see
+# <http://www.gnu.org/licenses/>.
+
+MACRO(SYMLINK_AND_INSTALL_HEADERS HEADERS SUBPATH)
+  FOREACH(header ${HEADERS})
+    GET_FILENAME_COMPONENT(headerName ${header} NAME)
+    GET_FILENAME_COMPONENT(headerPath ${header} PATH)
+    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E ${LINK}
+      ${CMAKE_CURRENT_SOURCE_DIR}/${header}
+      ${${PROJECT_NAME}_BINARY_DIR}/include/${PROJECT_NAME}/${SUBPATH}/${header})
+
+    INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${header}
+      DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/${SUBPATH}/${headerPath}
+            PERMISSIONS OWNER_READ GROUP_READ WORLD_READ OWNER_WRITE)
+  ENDFOREACH(header)
+ENDMACRO(SYMLINK_AND_INSTALL_HEADERS HEADERS SUBPATH)
+
+# --- LIBRARY --- #
+SET(PYWRAP ${PROJECT_NAME}_pywrap) 
+MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}")
+
+ADD_LIBRARY(${PYWRAP} SHARED main.cpp)
+TARGET_LINK_LIBRARIES(${PYWRAP} ${PROJECT_NAME}) 
+TARGET_LINK_BOOST_PYTHON(${PYWRAP})
+#IF(BUILD_WITH_COMMIT_VERSION)
+#  TAG_LIBRARY_VERSION(${PYWRAP})
+#ENDIF(BUILD_WITH_COMMIT_VERSION)
+SET(${PYWRAP}_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}/${PROJECT_NAME})
+
+SET_PROPERTY(TARGET ${PYWRAP} PROPERTY LINKER_LANGUAGE CXX)
+IF(APPLE)
+  # We need to change the extension for python bindings
+  SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES SUFFIX ".so")
+ENDIF(APPLE)
+
+SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES
+  LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/${PROJECT_NAME}")
+
+SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES PREFIX "")
+SET_TARGET_PROPERTIES(${PYWRAP} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}")
+
+INSTALL(TARGETS ${PYWRAP} DESTINATION ${${PYWRAP}_INSTALL_DIR})
+
+# --- INSTALL SCRIPTS 
+SET(PYTHON_FILES
+  __init__.py
+  )
+
+FOREACH(python ${PYTHON_FILES})
+  GET_FILENAME_COMPONENT(pythonFile ${python} NAME)
+  EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E ${LINK}
+    ${${PROJECT_NAME}_SOURCE_DIR}/python/scripts/${python}
+    ${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile})
+    
+  # Generate pyc file
+  EXECUTE_PROCESS(COMMAND
+    ${PYTHON_EXECUTABLE} -m py_compile
+    ${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile})
+  # Tag pyc file as generated.
+  SET_SOURCE_FILES_PROPERTIES(
+    "${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile}c"
+    PROPERTIES GENERATED TRUE)
+    
+  # Clean generated files.
+  SET_PROPERTY(
+    DIRECTORY APPEND PROPERTY
+    ADDITIONAL_MAKE_CLEAN_FILES
+    "${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile}c")
+    
+  INSTALL(FILES
+    "${${PROJECT_NAME}_SOURCE_DIR}/python/scripts/${python}"
+    "${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}/${pythonFile}c"
+    DESTINATION ${${PYWRAP}_INSTALL_DIR})
+ENDFOREACH(python)
+
diff --git a/python/main.cpp b/python/main.cpp
new file mode 100644
index 00000000..95ec5c44
--- /dev/null
+++ b/python/main.cpp
@@ -0,0 +1,30 @@
+//
+// Copyright (c) 2017, Justin Carpentier, CNRS
+//
+// This file is part of eigenpy
+// eigenpy is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// eigenpy is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// eigenpy If not, see
+// <http://www.gnu.org/licenses/>.
+
+#include "eigenpy/eigenpy.hpp"
+#include "eigenpy/geometry.hpp"
+
+#include <iostream>
+
+
+BOOST_PYTHON_MODULE(eigenpy)
+{
+  eigenpy::enableEigenPy();
+  eigenpy::exposeAngleAxis();
+  eigenpy::exposeQuaternion();
+  
+}
diff --git a/python/scripts/__init__.py b/python/scripts/__init__.py
new file mode 100644
index 00000000..3f79365c
--- /dev/null
+++ b/python/scripts/__init__.py
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2017 CNRS
+#
+# This file is part of eigenpy
+# eigenpy is free software: you can redistribute it
+# and/or modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation, either version
+# 3 of the License, or (at your option) any later version.
+# Pinocchio is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Lesser Public License for more details. You should have
+# received a copy of the GNU Lesser General Public License along with
+# eigenpy If not, see
+# <http://www.gnu.org/licenses/>.
+
+import numpy as np
+from eigenpy import *
-- 
GitLab