Squashed 'wrap/' changes from b28b3570d..b0eb968f2
b0eb968f2 Completely handle Matlab wrapping (#34) 4ad71812a Merge pull request #33 from borglab/fix/script-destination 0c832eed7 reverted from TYPE to DESTINATION for wrapper scripts 10e1efd6f Merge pull request #32 from ayushbaid/feature/pickle 55d5d7fbe ignoring pickle in matlab wrap 8d70c7fe2 adding newlines dee8aaee3 adding markers for pickling 46fc45d82 separating out the marker for pickle d37b8a972 Merge pull request #31 from ayushbaid/feature/pickle efd4a0fb4 removing tab 42fd231f3 adding newline for test compare 0aa316150 removing extra brackets 7fe1d7d0f adding pickle code to expected file 9c3ab7a8b fixing string format for new classname 2f89284e8 moving pickle support with the serialization code 5a8abc916 adding pickle support for select classes using serialization git-subtree-dir: wrap git-subtree-split: b0eb968f29a2261700361599cab2823221dd0f9drelease/4.3a0
parent
8d49d7dc40
commit
f52b09660e
|
@ -21,20 +21,27 @@ else()
|
|||
set(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/cmake")
|
||||
endif()
|
||||
|
||||
# Install scripts to the standard CMake script directory.
|
||||
install(FILES cmake/gtwrapConfig.cmake cmake/PybindWrap.cmake
|
||||
cmake/GtwrapUtils.cmake
|
||||
# Install CMake scripts to the standard CMake script directory.
|
||||
install(FILES cmake/gtwrapConfig.cmake cmake/MatlabWrap.cmake
|
||||
cmake/PybindWrap.cmake cmake/GtwrapUtils.cmake
|
||||
DESTINATION "${SCRIPT_INSTALL_DIR}/gtwrap")
|
||||
|
||||
# Needed for the CMAKE_INSTALL_X variables used below.
|
||||
include(GNUInstallDirs)
|
||||
# Install the gtwrap python package as a directory so it can be found for
|
||||
# wrapping.
|
||||
|
||||
# Install the gtwrap python package as a directory so it can be found by CMake
|
||||
# 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)
|
||||
# be invoked for wrapping. We use DESTINATION (instead of TYPE) so we can
|
||||
# support older CMake versions.
|
||||
install(PROGRAMS scripts/pybind_wrap.py scripts/matlab_wrap.py
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
# Install pybind11 directory to `CMAKE_INSTALL_PREFIX/lib/pybind11` This will
|
||||
# allow the gtwrapConfig.cmake file to load it later.
|
||||
# Install pybind11 directory to `CMAKE_INSTALL_PREFIX/lib/gtwrap/pybind11` This
|
||||
# will allow the gtwrapConfig.cmake file to load it later.
|
||||
install(DIRECTORY pybind11 DESTINATION "${CMAKE_INSTALL_LIBDIR}/gtwrap")
|
||||
|
||||
# Install the matlab.h file to `CMAKE_INSTALL_PREFIX/lib/gtwrap/matlab.h`.
|
||||
install(FILES matlab.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gtwrap")
|
||||
|
|
79
README.md
79
README.md
|
@ -1,4 +1,3 @@
|
|||
|
||||
# WRAP
|
||||
|
||||
The wrap library wraps the GTSAM library into a Python library or MATLAB toolbox.
|
||||
|
@ -43,36 +42,64 @@ pybind_wrap(${PROJECT_NAME}_py # target
|
|||
|
||||
For more information, please follow our [tutorial](https://github.com/borglab/gtsam-project-python).
|
||||
|
||||
## GTSAM Python wrapper
|
||||
## Python Wrapper
|
||||
|
||||
**WARNING: On macOS, you have to statically build GTSAM to use the wrapper.**
|
||||
|
||||
1. Set `GTSAM_BUILD_PYTHON=ON` while configuring the build with `cmake`.
|
||||
1. What you can do in the `build` folder:
|
||||
1. Just run python then import GTSAM and play around:
|
||||
```
|
||||
|
||||
import gtsam
|
||||
gtsam.__dir__()
|
||||
```
|
||||
1. Just run python then import GTSAM and play around:
|
||||
|
||||
```
|
||||
import gtsam
|
||||
gtsam.__dir__()
|
||||
```
|
||||
|
||||
1. Run the unittests:
|
||||
```
|
||||
python -m unittest discover
|
||||
```
|
||||
1. Edit the unittests in `python/gtsam/*.py` and simply rerun the test.
|
||||
They were symlinked to `<build_folder>/gtsam/*.py` to facilitate fast development.
|
||||
`python -m unittest gtsam/tests/test_Pose3.py` - NOTE: You might need to re-run `cmake ..` if files are deleted or added.
|
||||
|
||||
1. Run the unittests:
|
||||
```
|
||||
python -m unittest discover
|
||||
```
|
||||
1. Edit the unittests in `python/gtsam/*.py` and simply rerun the test.
|
||||
They were symlinked to `<build_folder>/gtsam/*.py` to facilitate fast development.
|
||||
```
|
||||
python -m unittest gtsam/tests/test_Pose3.py
|
||||
```
|
||||
- NOTE: You might need to re-run `cmake ..` if files are deleted or added.
|
||||
1. Do `make install` and `cd <gtsam_install_folder>/python`. Here, you can:
|
||||
1. Run the unittests:
|
||||
```
|
||||
python setup.py test
|
||||
```
|
||||
2. Install `gtsam` to your current Python environment.
|
||||
```
|
||||
python setup.py install
|
||||
```
|
||||
- NOTE: It's a good idea to create a virtual environment otherwise it will be installed in your system Python's site-packages.
|
||||
1. Run the unittests:
|
||||
```
|
||||
python setup.py test
|
||||
```
|
||||
2. Install `gtsam` to your current Python environment.
|
||||
```
|
||||
python setup.py install
|
||||
```
|
||||
- NOTE: It's a good idea to create a virtual environment otherwise it will be installed in your system Python's site-packages.
|
||||
|
||||
## Matlab Wrapper
|
||||
|
||||
In the CMake, simply include the `MatlabWrap.cmake` file.
|
||||
|
||||
```cmake
|
||||
include(MatlabWrap)
|
||||
```
|
||||
|
||||
This cmake file defines functions for generating MATLAB wrappers.
|
||||
|
||||
- `wrap_and_install_library(interfaceHeader linkLibraries extraIncludeDirs extraMexFlags)` Generates wrap code and compiles the wrapper.
|
||||
|
||||
Usage example:
|
||||
|
||||
`wrap_and_install_library("lba.h" "" "" "")`
|
||||
|
||||
Arguments:
|
||||
|
||||
- `interfaceHeader`: The relative or absolute path to the wrapper interface definition file.
|
||||
- `linkLibraries`: Any _additional_ libraries to link. Your project library
|
||||
(e.g. `lba`), libraries it depends on, and any necessary
|
||||
MATLAB libraries will be linked automatically. So normally,
|
||||
leave this empty.
|
||||
- `extraIncludeDirs`: Any _additional_ include paths required by dependent
|
||||
libraries that have not already been added by
|
||||
include_directories. Again, normally, leave this empty.
|
||||
- `extraMexFlags`: Any _additional_ flags to pass to the compiler when building
|
||||
the wrap code. Normally, leave this empty.
|
||||
|
|
|
@ -0,0 +1,477 @@
|
|||
find_package(
|
||||
Matlab
|
||||
COMPONENTS MEX_COMPILER
|
||||
REQUIRED)
|
||||
|
||||
if(NOT Matlab_MEX_COMPILER)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Cannot find MEX compiler binary. Please check your Matlab installation and ensure MEX in installed as well."
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WRAP_BUILD_TYPE_POSTFIXES)
|
||||
set(CURRENT_POSTFIX ${CMAKE_${CMAKE_BUILD_TYPE_UPPER}_POSTFIX})
|
||||
endif()
|
||||
|
||||
# WRAP_MEX_BUILD_STATIC_MODULE is not for Windows - on Windows any static
|
||||
# are already compiled into the library by the linker
|
||||
if(WRAP_MEX_BUILD_STATIC_MODULE AND WIN32)
|
||||
message(FATAL_ERROR "WRAP_MEX_BUILD_STATIC_MODULE should not be set on Windows - the linker already automatically compiles in any dependent static libraries. To create a standalone toolbox pacakge, simply ensure that CMake finds the static versions of all dependent libraries (Boost, etc).")
|
||||
endif()
|
||||
|
||||
set(MEX_COMMAND ${Matlab_MEX_COMPILER} CACHE PATH "Path to MATLAB MEX compiler")
|
||||
set(MATLAB_ROOT ${Matlab_ROOT_DIR} CACHE PATH "Path to MATLAB installation root (e.g. /usr/local/MATLAB/R2012a)")
|
||||
|
||||
# Try to automatically configure mex path from provided custom `bin` path.
|
||||
if(WRAP_CUSTOM_MATLAB_PATH)
|
||||
set(matlab_bin_directory ${WRAP_CUSTOM_MATLAB_PATH})
|
||||
|
||||
if(WIN32)
|
||||
set(mex_program_name "mex.bat")
|
||||
else()
|
||||
set(mex_program_name "mex")
|
||||
endif()
|
||||
|
||||
# Run find_program explicitly putting $PATH after our predefined program
|
||||
# directories using 'ENV PATH' and 'NO_SYSTEM_ENVIRONMENT_PATH' - this prevents
|
||||
# finding the LaTeX mex program (totally unrelated to MATLAB Mex) when LaTeX is
|
||||
# on the system path.
|
||||
find_program(MEX_COMMAND ${mex_program_name}
|
||||
PATHS ${matlab_bin_directory} ENV PATH
|
||||
NO_DEFAULT_PATH)
|
||||
mark_as_advanced(FORCE MEX_COMMAND)
|
||||
# Now that we have mex, trace back to find the Matlab installation root
|
||||
get_filename_component(MEX_COMMAND "${MEX_COMMAND}" REALPATH)
|
||||
get_filename_component(mex_path "${MEX_COMMAND}" PATH)
|
||||
if(mex_path MATCHES ".*/win64$")
|
||||
get_filename_component(MATLAB_ROOT "${mex_path}/../.." ABSOLUTE)
|
||||
else()
|
||||
get_filename_component(MATLAB_ROOT "${mex_path}/.." ABSOLUTE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Consistent and user-friendly wrap function
|
||||
function(matlab_wrap interfaceHeader linkLibraries
|
||||
extraIncludeDirs extraMexFlags ignore_classes)
|
||||
wrap_and_install_library("${interfaceHeader}" "${linkLibraries}"
|
||||
"${extraIncludeDirs}" "${extraMexFlags}"
|
||||
"${ignore_classes}")
|
||||
endfunction()
|
||||
|
||||
# Wrapping function. Builds a mex module from the provided
|
||||
# interfaceHeader. For example, for the interface header gtsam.h, this will
|
||||
# build the wrap module 'gtsam'.
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# interfaceHeader: The relative path to the wrapper interface definition file.
|
||||
# linkLibraries: Any *additional* libraries to link. Your project library
|
||||
# (e.g. `lba`), libraries it depends on, and any necessary MATLAB libraries will
|
||||
# be linked automatically. So normally, leave this empty.
|
||||
# extraIncludeDirs: Any *additional* include paths required by dependent libraries that have not
|
||||
# already been added by include_directories. Again, normally, leave this empty.
|
||||
# extraMexFlags: Any *additional* flags to pass to the compiler when building
|
||||
# the wrap code. Normally, leave this empty.
|
||||
# ignore_classes: List of classes to ignore in the wrapping.
|
||||
function(wrap_and_install_library interfaceHeader linkLibraries
|
||||
extraIncludeDirs extraMexFlags ignore_classes)
|
||||
wrap_library_internal("${interfaceHeader}" "${linkLibraries}"
|
||||
"${extraIncludeDirs}" "${mexFlags}")
|
||||
install_wrapped_library_internal("${interfaceHeader}")
|
||||
endfunction()
|
||||
|
||||
# Internal function that wraps a library and compiles the wrapper
|
||||
function(wrap_library_internal interfaceHeader linkLibraries extraIncludeDirs
|
||||
extraMexFlags)
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(mexModuleExt mexa64)
|
||||
else()
|
||||
set(mexModuleExt mexglx)
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
set(mexModuleExt mexmaci64)
|
||||
elseif(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(mexModuleExt mexw64)
|
||||
else()
|
||||
set(mexModuleExt mexw32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Wrap codegen interface usage: wrap interfacePath moduleName toolboxPath
|
||||
# headerPath interfacePath : *absolute* path to directory of module interface
|
||||
# file moduleName : the name of the module, interface file must be called
|
||||
# moduleName.h toolboxPath : the directory in which to generate the wrappers
|
||||
# headerPath : path to matlab.h
|
||||
|
||||
# Extract module name from interface header file name
|
||||
get_filename_component(interfaceHeader "${interfaceHeader}" ABSOLUTE)
|
||||
get_filename_component(modulePath "${interfaceHeader}" PATH)
|
||||
get_filename_component(moduleName "${interfaceHeader}" NAME_WE)
|
||||
|
||||
# Paths for generated files
|
||||
set(generated_files_path "${PROJECT_BINARY_DIR}/wrap/${moduleName}")
|
||||
set(generated_cpp_file "${generated_files_path}/${moduleName}_wrapper.cpp")
|
||||
set(compiled_mex_modules_root "${PROJECT_BINARY_DIR}/wrap/${moduleName}_mex")
|
||||
|
||||
message(STATUS "Building wrap module ${moduleName}")
|
||||
|
||||
# Set matlab.h in project
|
||||
set(matlab_h_path "${CMAKE_SOURCE_DIR}")
|
||||
|
||||
# If building a static mex module, add all cmake-linked libraries to the
|
||||
# explicit link libraries list so that the next block of code can unpack any
|
||||
# static libraries
|
||||
set(automaticDependencies "")
|
||||
foreach(lib ${moduleName} ${linkLibraries})
|
||||
# message("MODULE NAME: ${moduleName}")
|
||||
if(TARGET "${lib}")
|
||||
get_target_property(dependentLibraries ${lib} INTERFACE_LINK_LIBRARIES)
|
||||
# message("DEPENDENT LIBRARIES: ${dependentLibraries}")
|
||||
if(dependentLibraries)
|
||||
list(APPEND automaticDependencies ${dependentLibraries})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# CHRIS: Temporary fix. On my system the get_target_property above returned
|
||||
# Not-found for gtsam module This needs to be fixed!!
|
||||
if(UNIX AND NOT APPLE)
|
||||
list(
|
||||
APPEND
|
||||
automaticDependencies
|
||||
${Boost_SERIALIZATION_LIBRARY_RELEASE}
|
||||
${Boost_FILESYSTEM_LIBRARY_RELEASE}
|
||||
${Boost_SYSTEM_LIBRARY_RELEASE}
|
||||
${Boost_THREAD_LIBRARY_RELEASE}
|
||||
${Boost_DATE_TIME_LIBRARY_RELEASE})
|
||||
# Only present in Boost >= 1.48.0
|
||||
if(Boost_TIMER_LIBRARY_RELEASE)
|
||||
list(APPEND automaticDependencies ${Boost_TIMER_LIBRARY_RELEASE}
|
||||
${Boost_CHRONO_LIBRARY_RELEASE})
|
||||
if(WRAP_MEX_BUILD_STATIC_MODULE)
|
||||
# list(APPEND automaticDependencies -Wl,--no-as-needed -lrt)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# message("AUTOMATIC DEPENDENCIES: ${automaticDependencies}") CHRIS: End
|
||||
# temporary fix
|
||||
|
||||
# Separate dependencies
|
||||
set(correctedOtherLibraries "")
|
||||
set(otherLibraryTargets "")
|
||||
set(otherLibraryNontargets "")
|
||||
set(otherSourcesAndObjects "")
|
||||
foreach(lib ${moduleName} ${linkLibraries} ${automaticDependencies})
|
||||
if(TARGET "${lib}")
|
||||
if(WRAP_MEX_BUILD_STATIC_MODULE)
|
||||
get_target_property(target_sources ${lib} SOURCES)
|
||||
list(APPEND otherSourcesAndObjects ${target_sources})
|
||||
else()
|
||||
list(APPEND correctedOtherLibraries ${lib})
|
||||
list(APPEND otherLibraryTargets ${lib})
|
||||
endif()
|
||||
else()
|
||||
get_filename_component(file_extension "${lib}" EXT)
|
||||
get_filename_component(lib_name "${lib}" NAME_WE)
|
||||
if(file_extension STREQUAL ".a" AND WRAP_MEX_BUILD_STATIC_MODULE)
|
||||
# For building a static MEX module, unpack the static library and
|
||||
# compile its object files into our module
|
||||
file(MAKE_DIRECTORY "${generated_files_path}/${lib_name}_objects")
|
||||
execute_process(
|
||||
COMMAND ar -x "${lib}"
|
||||
WORKING_DIRECTORY "${generated_files_path}/${lib_name}_objects"
|
||||
RESULT_VARIABLE ar_result)
|
||||
if(NOT ar_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed extracting ${lib}")
|
||||
endif()
|
||||
|
||||
# Get list of object files
|
||||
execute_process(
|
||||
COMMAND ar -t "${lib}"
|
||||
OUTPUT_VARIABLE object_files
|
||||
RESULT_VARIABLE ar_result)
|
||||
if(NOT ar_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed listing ${lib}")
|
||||
endif()
|
||||
|
||||
# Add directory to object files
|
||||
string(REPLACE "\n" ";" object_files_list "${object_files}")
|
||||
foreach(object_file ${object_files_list})
|
||||
get_filename_component(file_extension "${object_file}" EXT)
|
||||
if(file_extension STREQUAL ".o")
|
||||
list(APPEND otherSourcesAndObjects
|
||||
"${generated_files_path}/${lib_name}_objects/${object_file}")
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
list(APPEND correctedOtherLibraries ${lib})
|
||||
list(APPEND otherLibraryNontargets ${lib})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Check libraries for conflicting versions built-in to MATLAB
|
||||
set(dependentLibraries "")
|
||||
if(NOT "${otherLibraryTargets}" STREQUAL "")
|
||||
foreach(target ${otherLibraryTargets})
|
||||
get_target_property(dependentLibrariesOne ${target}
|
||||
INTERFACE_LINK_LIBRARIES)
|
||||
list(APPEND dependentLibraries ${dependentLibrariesOne})
|
||||
endforeach()
|
||||
endif()
|
||||
list(APPEND dependentLibraries ${otherLibraryNontargets})
|
||||
check_conflicting_libraries_internal("${dependentLibraries}")
|
||||
|
||||
# Set up generation of module source file
|
||||
file(MAKE_DIRECTORY "${generated_files_path}")
|
||||
|
||||
find_package(PythonInterp ${WRAP_PYTHON_VERSION} EXACT)
|
||||
find_package(PythonLibs ${WRAP_PYTHON_VERSION} EXACT)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${generated_cpp_file}
|
||||
DEPENDS ${interfaceHeader} ${module_library_target} ${otherLibraryTargets}
|
||||
${otherSourcesAndObjects}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E env
|
||||
"PYTHONPATH=${GTWRAP_PACKAGE_DIR}${GTWRAP_PATH_SEPARATOR}$ENV{PYTHONPATH}"
|
||||
${PYTHON_EXECUTABLE} ${MATLAB_WRAP_SCRIPT} --src ${interfaceHeader}
|
||||
--module_name ${moduleName} --out ${generated_files_path}
|
||||
--top_module_namespaces ${moduleName} --ignore ${ignore_classes}
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${generated_files_path})
|
||||
|
||||
# Set up building of mex module
|
||||
string(REPLACE ";" " " extraMexFlagsSpaced "${extraMexFlags}")
|
||||
string(REPLACE ";" " " mexFlagsSpaced "${WRAP_BUILD_MEX_BINARY_FLAGS}")
|
||||
add_library(
|
||||
${moduleName}_matlab_wrapper MODULE
|
||||
${generated_cpp_file} ${interfaceHeader} ${otherSourcesAndObjects})
|
||||
target_link_libraries(${moduleName}_matlab_wrapper ${correctedOtherLibraries})
|
||||
target_link_libraries(${moduleName}_matlab_wrapper ${moduleName})
|
||||
set_target_properties(
|
||||
${moduleName}_matlab_wrapper
|
||||
PROPERTIES OUTPUT_NAME "${moduleName}_wrapper"
|
||||
PREFIX ""
|
||||
SUFFIX ".${mexModuleExt}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${compiled_mex_modules_root}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${compiled_mex_modules_root}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${compiled_mex_modules_root}"
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
set_property(
|
||||
TARGET ${moduleName}_matlab_wrapper
|
||||
APPEND_STRING
|
||||
PROPERTY
|
||||
COMPILE_FLAGS
|
||||
" ${extraMexFlagsSpaced} ${mexFlagsSpaced} \"-I${MATLAB_ROOT}/extern/include\" -DMATLAB_MEX_FILE -DMX_COMPAT_32"
|
||||
)
|
||||
set_property(
|
||||
TARGET ${moduleName}_matlab_wrapper
|
||||
APPEND
|
||||
PROPERTY INCLUDE_DIRECTORIES ${extraIncludeDirs})
|
||||
# Disable build type postfixes for the mex module - we install in different
|
||||
# directories for each build type instead
|
||||
foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER "${build_type}" build_type_upper)
|
||||
set_target_properties(${moduleName}_matlab_wrapper
|
||||
PROPERTIES ${build_type_upper}_POSTFIX "")
|
||||
endforeach()
|
||||
# Set up platform-specific flags
|
||||
if(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(mxLibPath "${MATLAB_ROOT}/extern/lib/win64/microsoft")
|
||||
else()
|
||||
set(mxLibPath "${MATLAB_ROOT}/extern/lib/win32/microsoft")
|
||||
endif()
|
||||
target_link_libraries(
|
||||
${moduleName}_matlab_wrapper "${mxLibPath}/libmex.lib"
|
||||
"${mxLibPath}/libmx.lib" "${mxLibPath}/libmat.lib")
|
||||
set_target_properties(${moduleName}_matlab_wrapper
|
||||
PROPERTIES LINK_FLAGS "/export:mexFunction")
|
||||
set_property(
|
||||
SOURCE "${generated_cpp_file}"
|
||||
APPEND
|
||||
PROPERTY COMPILE_FLAGS "/bigobj")
|
||||
elseif(APPLE)
|
||||
set(mxLibPath "${MATLAB_ROOT}/bin/maci64")
|
||||
target_link_libraries(
|
||||
${moduleName}_matlab_wrapper "${mxLibPath}/libmex.dylib"
|
||||
"${mxLibPath}/libmx.dylib" "${mxLibPath}/libmat.dylib")
|
||||
endif()
|
||||
|
||||
# Hacking around output issue with custom command Deletes generated build
|
||||
# folder
|
||||
add_custom_target(
|
||||
wrap_${moduleName}_matlab_distclean
|
||||
COMMAND cmake -E remove_directory ${generated_files_path}
|
||||
COMMAND cmake -E remove_directory ${compiled_mex_modules_root})
|
||||
endfunction()
|
||||
|
||||
# Internal function that installs a wrap toolbox
|
||||
function(install_wrapped_library_internal interfaceHeader)
|
||||
get_filename_component(moduleName "${interfaceHeader}" NAME_WE)
|
||||
set(generated_files_path "${PROJECT_BINARY_DIR}/wrap/${moduleName}")
|
||||
|
||||
# NOTE: only installs .m and mex binary files (not .cpp) - the trailing slash
|
||||
# on the directory name here prevents creating the top-level module name
|
||||
# directory in the destination.
|
||||
message(STATUS "Installing Matlab Toolbox to ${WRAP_TOOLBOX_INSTALL_PATH}")
|
||||
if(WRAP_BUILD_TYPE_POSTFIXES)
|
||||
foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER "${build_type}" build_type_upper)
|
||||
if(${build_type_upper} STREQUAL "RELEASE")
|
||||
set(build_type_tag "") # Don't create release mode tag on installed
|
||||
# directory
|
||||
else()
|
||||
set(build_type_tag "${build_type}")
|
||||
endif()
|
||||
# Split up filename to strip trailing '/' in WRAP_TOOLBOX_INSTALL_PATH if
|
||||
# there is one
|
||||
get_filename_component(location "${WRAP_TOOLBOX_INSTALL_PATH}" PATH)
|
||||
get_filename_component(name "${WRAP_TOOLBOX_INSTALL_PATH}" NAME)
|
||||
install(
|
||||
DIRECTORY "${generated_files_path}/"
|
||||
DESTINATION "${location}/${name}${build_type_tag}"
|
||||
CONFIGURATIONS "${build_type}"
|
||||
FILES_MATCHING
|
||||
PATTERN "*.m")
|
||||
install(
|
||||
TARGETS ${moduleName}_matlab_wrapper
|
||||
LIBRARY DESTINATION "${location}/${name}${build_type_tag}"
|
||||
CONFIGURATIONS "${build_type}"
|
||||
RUNTIME DESTINATION "${location}/${name}${build_type_tag}"
|
||||
CONFIGURATIONS "${build_type}")
|
||||
endforeach()
|
||||
else()
|
||||
install(
|
||||
DIRECTORY "${generated_files_path}/"
|
||||
DESTINATION ${WRAP_TOOLBOX_INSTALL_PATH}
|
||||
FILES_MATCHING
|
||||
PATTERN "*.m")
|
||||
install(
|
||||
TARGETS ${moduleName}_matlab_wrapper
|
||||
LIBRARY DESTINATION ${WRAP_TOOLBOX_INSTALL_PATH}
|
||||
RUNTIME DESTINATION ${WRAP_TOOLBOX_INSTALL_PATH})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Internal function to check for libraries installed with MATLAB that may
|
||||
# conflict and prints a warning to move them if problems occur.
|
||||
function(check_conflicting_libraries_internal libraries)
|
||||
if(UNIX)
|
||||
# Set path for matlab's built-in libraries
|
||||
if(APPLE)
|
||||
set(mxLibPath "${MATLAB_ROOT}/bin/maci64")
|
||||
else()
|
||||
if(CMAKE_CL_64)
|
||||
set(mxLibPath "${MATLAB_ROOT}/bin/glnxa64")
|
||||
else()
|
||||
set(mxLibPath "${MATLAB_ROOT}/bin/glnx86")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# List matlab's built-in libraries
|
||||
file(
|
||||
GLOB matlabLibs
|
||||
RELATIVE "${mxLibPath}"
|
||||
"${mxLibPath}/lib*")
|
||||
|
||||
# Convert to base names
|
||||
set(matlabLibNames "")
|
||||
foreach(lib ${matlabLibs})
|
||||
get_filename_component(libName "${lib}" NAME_WE)
|
||||
list(APPEND matlabLibNames "${libName}")
|
||||
endforeach()
|
||||
|
||||
# Get names of link libraries
|
||||
set(linkLibNames "")
|
||||
foreach(lib ${libraries})
|
||||
string(FIND "${lib}" "/" slashPos)
|
||||
if(NOT slashPos EQUAL -1)
|
||||
# If the name is a path, just get the library name
|
||||
get_filename_component(libName "${lib}" NAME_WE)
|
||||
list(APPEND linkLibNames "${libName}")
|
||||
else()
|
||||
# It's not a path, so see if it looks like a filename
|
||||
get_filename_component(ext "${lib}" EXT)
|
||||
if(NOT "${ext}" STREQUAL "")
|
||||
# It's a filename, so get the base name
|
||||
get_filename_component(libName "${lib}" NAME_WE)
|
||||
list(APPEND linkLibNames "${libName}")
|
||||
else()
|
||||
# It's not a filename so it must be a short name, add the "lib" prefix
|
||||
list(APPEND linkLibNames "lib${lib}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Remove duplicates
|
||||
list(REMOVE_DUPLICATES linkLibNames)
|
||||
|
||||
set(conflictingLibs "")
|
||||
foreach(lib ${linkLibNames})
|
||||
list(FIND matlabLibNames "${lib}" libPos)
|
||||
if(NOT libPos EQUAL -1)
|
||||
if(NOT conflictingLibs STREQUAL "")
|
||||
set(conflictingLibs "${conflictingLibs}, ")
|
||||
endif()
|
||||
set(conflictingLibs "${conflictingLibs}${lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT "${conflictingLibs}" STREQUAL "")
|
||||
message(
|
||||
WARNING
|
||||
"The project links to the libraries [ ${conflictingLibs} ] on your system, but "
|
||||
"MATLAB is distributed with its own versions of these libraries which may conflict. "
|
||||
"If you get strange errors or crashes with the MATLAB wrapper, move these "
|
||||
"libraries out of MATLAB's built-in library directory, which is ${mxLibPath} on "
|
||||
"your system. MATLAB will usually still work with these libraries moved away, but "
|
||||
"if not, you'll have to compile the static MATLAB wrapper module."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Helper function to install MATLAB scripts and handle multiple build types
|
||||
# where the scripts should be installed to all build type toolboxes
|
||||
function(install_matlab_scripts source_directory patterns)
|
||||
set(patterns_args "")
|
||||
set(exclude_patterns "")
|
||||
|
||||
foreach(pattern ${patterns})
|
||||
list(APPEND patterns_args PATTERN "${pattern}")
|
||||
endforeach()
|
||||
if(WRAP_BUILD_TYPE_POSTFIXES)
|
||||
foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER "${build_type}" build_type_upper)
|
||||
if(${build_type_upper} STREQUAL "RELEASE")
|
||||
set(build_type_tag "") # Don't create release mode tag on installed
|
||||
# directory
|
||||
else()
|
||||
set(build_type_tag "${build_type}")
|
||||
endif()
|
||||
# Split up filename to strip trailing '/' in WRAP_TOOLBOX_INSTALL_PATH if
|
||||
# there is one
|
||||
get_filename_component(location "${WRAP_TOOLBOX_INSTALL_PATH}" PATH)
|
||||
get_filename_component(name "${WRAP_TOOLBOX_INSTALL_PATH}" NAME)
|
||||
install(
|
||||
DIRECTORY "${source_directory}"
|
||||
DESTINATION "${location}/${name}${build_type_tag}"
|
||||
CONFIGURATIONS "${build_type}"
|
||||
FILES_MATCHING ${patterns_args}
|
||||
PATTERN "${exclude_patterns}" EXCLUDE)
|
||||
endforeach()
|
||||
else()
|
||||
install(
|
||||
DIRECTORY "${source_directory}"
|
||||
DESTINATION "${WRAP_TOOLBOX_INSTALL_PATH}"
|
||||
FILES_MATCHING ${patterns_args}
|
||||
PATTERN "${exclude_patterns}" EXCLUDE)
|
||||
endif()
|
||||
|
||||
endfunction()
|
|
@ -49,6 +49,8 @@ class MatlabWrapper(object):
|
|||
}
|
||||
"""Methods that should not be wrapped directly"""
|
||||
whitelist = ['serializable', 'serialize']
|
||||
"""Methods that should be ignored"""
|
||||
ignore_methods = ['pickle']
|
||||
"""Datatypes that do not need to be checked in methods"""
|
||||
not_check_type = []
|
||||
"""Data types that are primitive types"""
|
||||
|
@ -563,6 +565,8 @@ class MatlabWrapper(object):
|
|||
for method in methods:
|
||||
if method.name in self.whitelist:
|
||||
continue
|
||||
if method.name in self.ignore_methods:
|
||||
continue
|
||||
|
||||
comment += '%{name}({args})'.format(name=method.name, args=self._wrap_args(method.args))
|
||||
|
||||
|
@ -587,7 +591,7 @@ class MatlabWrapper(object):
|
|||
file_name = self._wrapper_name() + '.cpp'
|
||||
|
||||
wrapper_file = textwrap.dedent('''\
|
||||
# include <wrap/matlab.h>
|
||||
# include <gtwrap/matlab.h>
|
||||
# include <map>
|
||||
''')
|
||||
|
||||
|
@ -612,6 +616,9 @@ class MatlabWrapper(object):
|
|||
methods = self._group_methods(methods)
|
||||
|
||||
for method in methods:
|
||||
if method in self.ignore_methods:
|
||||
continue
|
||||
|
||||
if globals:
|
||||
self._debug("[wrap_methods] wrapping: {}..{}={}".format(method[0].parent.name, method[0].name,
|
||||
type(method[0].parent.name)))
|
||||
|
@ -861,6 +868,8 @@ class MatlabWrapper(object):
|
|||
method_name = method[0].name
|
||||
if method_name in self.whitelist and method_name != 'serialize':
|
||||
continue
|
||||
if method_name in self.ignore_methods:
|
||||
continue
|
||||
|
||||
if method_name == 'serialize':
|
||||
serialize[0] = True
|
||||
|
@ -932,6 +941,9 @@ class MatlabWrapper(object):
|
|||
format_name = list(static_method[0].name)
|
||||
format_name[0] = format_name[0].upper()
|
||||
|
||||
if static_method[0].name in self.ignore_methods:
|
||||
continue
|
||||
|
||||
method_text += textwrap.indent(textwrap.dedent('''\
|
||||
function varargout = {name}(varargin)
|
||||
'''.format(name=''.join(format_name))),
|
||||
|
@ -1464,7 +1476,7 @@ class MatlabWrapper(object):
|
|||
"""Generate the c++ wrapper."""
|
||||
# Includes
|
||||
wrapper_file = textwrap.dedent('''\
|
||||
#include <wrap/matlab.h>
|
||||
#include <gtwrap/matlab.h>
|
||||
#include <map>\n
|
||||
#include <boost/archive/text_iarchive.hpp>
|
||||
#include <boost/archive/text_oarchive.hpp>
|
||||
|
@ -1473,7 +1485,16 @@ class MatlabWrapper(object):
|
|||
|
||||
includes_list = sorted(list(self.includes.keys()), key=lambda include: include.header)
|
||||
|
||||
wrapper_file += reduce(lambda x, y: str(x) + '\n' + str(y), includes_list) + '\n'
|
||||
# Check the number of includes.
|
||||
# If no includes, do nothing, if 1 then just append newline.
|
||||
# if more than one, concatenate them with newlines.
|
||||
if len(includes_list) == 0:
|
||||
pass
|
||||
elif len(includes_list) == 1:
|
||||
wrapper_file += (str(includes_list[0]) + '\n')
|
||||
else:
|
||||
wrapper_file += reduce(lambda x, y: str(x) + '\n' + str(y), includes_list)
|
||||
wrapper_file += '\n'
|
||||
|
||||
typedef_instances = '\n'
|
||||
typedef_collectors = ''
|
||||
|
|
|
@ -76,6 +76,21 @@ class PybindWrapper(object):
|
|||
gtsam::deserialize(serialized, *self);
|
||||
}}, py::arg("serialized"))
|
||||
'''.format(class_inst=cpp_class + '*'))
|
||||
if cpp_method == "pickle":
|
||||
if not cpp_class in self._serializing_classes:
|
||||
raise ValueError("Cannot pickle a class which is not serializable")
|
||||
return textwrap.dedent('''
|
||||
.def(py::pickle(
|
||||
[](const {cpp_class} &a){{ // __getstate__
|
||||
/* Returns a string that encodes the state of the object */
|
||||
return py::make_tuple(gtsam::serialize(a));
|
||||
}},
|
||||
[](py::tuple t){{ // __setstate__
|
||||
{cpp_class} obj;
|
||||
gtsam::deserialize(t[0].cast<std::string>(), obj);
|
||||
return obj;
|
||||
}}))
|
||||
'''.format(cpp_class=cpp_class))
|
||||
|
||||
is_method = isinstance(method, instantiator.InstantiatedMethod)
|
||||
is_static = isinstance(method, parser.StaticMethod)
|
||||
|
@ -318,3 +333,4 @@ class PybindWrapper(object):
|
|||
wrapped_namespace=wrapped_namespace,
|
||||
boost_class_export=boost_class_export,
|
||||
)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <wrap/matlab.h>
|
||||
#include <gtwrap/matlab.h>
|
||||
#include <map>
|
||||
|
||||
#include <boost/archive/text_iarchive.hpp>
|
||||
|
|
|
@ -47,6 +47,17 @@ PYBIND11_MODULE(geometry_py, m_) {
|
|||
[](gtsam::Point2* self, string serialized){
|
||||
gtsam::deserialize(serialized, *self);
|
||||
}, py::arg("serialized"))
|
||||
|
||||
.def(py::pickle(
|
||||
[](const gtsam::Point2 &a){ // __getstate__
|
||||
/* Returns a string that encodes the state of the object */
|
||||
return py::make_tuple(gtsam::serialize(a));
|
||||
},
|
||||
[](py::tuple t){ // __setstate__
|
||||
gtsam::Point2 obj;
|
||||
gtsam::deserialize(t[0].cast<std::string>(), obj);
|
||||
return obj;
|
||||
}))
|
||||
;
|
||||
|
||||
py::class_<gtsam::Point3, std::shared_ptr<gtsam::Point3>>(m_gtsam, "Point3")
|
||||
|
@ -62,6 +73,17 @@ PYBIND11_MODULE(geometry_py, m_) {
|
|||
gtsam::deserialize(serialized, *self);
|
||||
}, py::arg("serialized"))
|
||||
|
||||
.def(py::pickle(
|
||||
[](const gtsam::Point3 &a){ // __getstate__
|
||||
/* Returns a string that encodes the state of the object */
|
||||
return py::make_tuple(gtsam::serialize(a));
|
||||
},
|
||||
[](py::tuple t){ // __setstate__
|
||||
gtsam::Point3 obj;
|
||||
gtsam::deserialize(t[0].cast<std::string>(), obj);
|
||||
return obj;
|
||||
}))
|
||||
|
||||
.def_static("staticFunction",[](){return gtsam::Point3::staticFunction();})
|
||||
.def_static("StaticFunctionRet",[]( double z){return gtsam::Point3::StaticFunctionRet(z);}, py::arg("z"));
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@ class Point2 {
|
|||
VectorNotEigen vectorConfusion();
|
||||
|
||||
void serializable() const; // Sets flag and creates export, but does not make serialization functions
|
||||
|
||||
// enable pickling in python
|
||||
void pickle() const;
|
||||
};
|
||||
|
||||
#include <gtsam/geometry/Point3.h>
|
||||
|
@ -35,6 +38,9 @@ class Point3 {
|
|||
|
||||
// enabling serialization functionality
|
||||
void serialize() const; // Just triggers a flag internally and removes actual function
|
||||
|
||||
// enable pickling in python
|
||||
void pickle() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue