diff --git a/CMakeLists.txt b/CMakeLists.txt index c5e8c46de5..5ffb66ad02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,30 +26,15 @@ install(FILES cmake/gtwrapConfig.cmake cmake/PybindWrap.cmake cmake/GtwrapUtils.cmake DESTINATION "${SCRIPT_INSTALL_DIR}/gtwrap") +include(GNUInstallDirs) +# Install the gtwrap python package as a directory so it can be found for +# wrapping. +install(DIRECTORY gtwrap DESTINATION "${CMAKE_INSTALL_DATADIR}/gtwrap") + # Install wrapping scripts as binaries to `CMAKE_INSTALL_PREFIX/bin` so they can # be invoked for wrapping. install(PROGRAMS scripts/pybind_wrap.py scripts/matlab_wrap.py TYPE BIN) # Install pybind11 directory to `CMAKE_INSTALL_PREFIX/lib/pybind11` This will # allow the gtwrapConfig.cmake file to load it later. -install(DIRECTORY pybind11 TYPE LIB) - -# ############################################################################## -# Install the Python package -find_package( - Python ${WRAP_PYTHON_VERSION} - COMPONENTS Interpreter - EXACT) - -# Detect virtualenv and set Pip args accordingly -# https://www.scivision.dev/cmake-install-python-package/ -if(DEFINED ENV{VIRTUAL_ENV} OR DEFINED ENV{CONDA_PREFIX}) - set(_pip_args) -else() - set(_pip_args "--user") -endif() -#TODO add correct flags for virtualenv - -# Finally install the gtwrap python package. -execute_process(COMMAND ${Python_EXECUTABLE} -m pip install . ${_pip_args} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +install(DIRECTORY pybind11 DESTINATION "${CMAKE_INSTALL_LIBDIR}/gtwrap") diff --git a/README.md b/README.md index 347cca601f..5b5cbb902f 100644 --- a/README.md +++ b/README.md @@ -23,18 +23,18 @@ cmake .. make install # use sudo if needed ``` -Using `wrap` in your project is straightforward from here. In you `CMakeLists.txt` file, you just need to add the following: +Using `wrap` in your project is straightforward from here. In your `CMakeLists.txt` file, you just need to add the following: ```cmake -include(PybindWrap) +find_package(gtwrap) pybind_wrap(${PROJECT_NAME}_py # target ${PROJECT_SOURCE_DIR}/cpp/${PROJECT_NAME}.h # interface header file "${PROJECT_NAME}.cpp" # the generated cpp "${PROJECT_NAME}" # module_name - "gtsam" # top namespace in the cpp file + "${PROJECT_MODULE_NAME}" # top namespace in the cpp file e.g. gtsam "${ignore}" # ignore classes - ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.tpl + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.tpl # the wrapping template file ${PROJECT_NAME} # libs "${PROJECT_NAME}" # dependencies ON # use boost diff --git a/cmake/PybindWrap.cmake b/cmake/PybindWrap.cmake index a94dbc5cce..c7c47a662e 100644 --- a/cmake/PybindWrap.cmake +++ b/cmake/PybindWrap.cmake @@ -1,5 +1,12 @@ set(PYBIND11_PYTHON_VERSION ${WRAP_PYTHON_VERSION}) +if(GTWRAP_PYTHON_PACKAGE_DIR) + # packaged + set(GTWRAP_PACKAGE_DIR "${GTWRAP_PYTHON_PACKAGE_DIR}") +else() + set(GTWRAP_PACKAGE_DIR ${CMAKE_CURRENT_LIST_DIR}/..) +endif() + # User-friendly Pybind11 wrapping and installing function. # Builds a Pybind11 module from the provided interface_header. # For example, for the interface header gtsam.h, this will @@ -35,9 +42,16 @@ function(pybind_wrap else(USE_BOOST) set(_WRAP_BOOST_ARG "") endif(USE_BOOST) - + + if (UNIX) + set(GTWRAP_PATH_SEPARATOR ":") + else() + set(GTWRAP_PATH_SEPARATOR ";") + endif() + add_custom_command(OUTPUT ${generated_cpp} - COMMAND ${PYTHON_EXECUTABLE} + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${GTWRAP_PACKAGE_DIR}${GTWRAP_PATH_SEPARATOR}$ENV{PYTHONPATH}" + ${PYTHON_EXECUTABLE} ${PYBIND_WRAP_SCRIPT} --src ${interface_header} @@ -119,7 +133,7 @@ function(install_python_scripts else() set(build_type_tag "") endif() - # Split up filename to strip trailing '/' in WRAP_CYTHON_INSTALL_PATH if + # Split up filename to strip trailing '/' in GTSAM_PY_INSTALL_PATH if # there is one get_filename_component(location "${dest_directory}" PATH) get_filename_component(name "${dest_directory}" NAME) diff --git a/cmake/gtwrapConfig.cmake b/cmake/gtwrapConfig.cmake index 48bd4772df..15c5ea9211 100644 --- a/cmake/gtwrapConfig.cmake +++ b/cmake/gtwrapConfig.cmake @@ -5,9 +5,13 @@ set(GTWRAP_DIR "${CMAKE_CURRENT_LIST_DIR}") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") if(WIN32 AND NOT CYGWIN) - set(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/CMake") + set(GTWRAP_CMAKE_DIR "${GTWRAP_DIR}") + set(GTWRAP_SCRIPT_DIR ${GTWRAP_CMAKE_DIR}/../../../bin) + set(GTWRAP_PYTHON_PACKAGE_DIR ${GTWRAP_CMAKE_DIR}/../../../share/gtwrap) else() - set(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/cmake") + set(GTWRAP_CMAKE_DIR "${GTWRAP_DIR}") + set(GTWRAP_SCRIPT_DIR ${GTWRAP_CMAKE_DIR}/../../../bin) + set(GTWRAP_PYTHON_PACKAGE_DIR ${GTWRAP_CMAKE_DIR}/../../../share/gtwrap) endif() # Standard includes @@ -16,12 +20,12 @@ include(CMakePackageConfigHelpers) include(CMakeDependentOption) # Load all the CMake scripts from the standard location -include(${SCRIPT_INSTALL_DIR}/gtwrap/PybindWrap.cmake) -include(${SCRIPT_INSTALL_DIR}/gtwrap/GtwrapUtils.cmake) +include(${GTWRAP_CMAKE_DIR}/PybindWrap.cmake) +include(${GTWRAP_CMAKE_DIR}/GtwrapUtils.cmake) # Set the variables for the wrapping scripts to be used in the build. -set(PYBIND_WRAP_SCRIPT "${CMAKE_INSTALL_FULL_BINDIR}/pybind_wrap.py") -set(MATLAB_WRAP_SCRIPT "${CMAKE_INSTALL_FULL_BINDIR}/matlab_wrap.py") +set(PYBIND_WRAP_SCRIPT "${GTWRAP_SCRIPT_DIR}/pybind_wrap.py") +set(MATLAB_WRAP_SCRIPT "${GTWRAP_SCRIPT_DIR}/matlab_wrap.py") # Load the pybind11 code from the library installation path -add_subdirectory(${CMAKE_INSTALL_FULL_LIBDIR}/pybind11 pybind11) +add_subdirectory(${GTWRAP_CMAKE_DIR}/../../gtwrap/pybind11 pybind11) diff --git a/gtwrap/matlab_wrapper.py b/gtwrap/matlab_wrapper.py index 355913ba7e..669bf474f0 100755 --- a/gtwrap/matlab_wrapper.py +++ b/gtwrap/matlab_wrapper.py @@ -1010,7 +1010,8 @@ def wrap_instantiated_class(self, instantiated_class, namespace_name=''): file_name = self._clean_class_name(instantiated_class) namespace_file_name = namespace_name + file_name - if instantiated_class.cpp_class() in self.ignore_classes: + uninstantiated_name = "::".join(instantiated_class.namespaces()[1:]) + "::" + instantiated_class.name + if uninstantiated_name in self.ignore_classes: return None # Class comment @@ -1518,7 +1519,11 @@ def generate_wrapper(self, namespace): ptr_ctor_frag = '' for cls in self.classes: - if cls.cpp_class().strip() in self.ignore_classes: + uninstantiated_name = "::".join(cls.namespaces()[1:]) + "::" + cls.name + self._debug("Cls: {} -> {}".format(cls.name, uninstantiated_name)) + + if uninstantiated_name in self.ignore_classes: + self._debug("Ignoring: {} -> {}".format(cls.name, uninstantiated_name)) continue def _has_serialization(cls):