Merge pull request #277 from borglab/feature/python-install
Auto-install Python Packagerelease/4.3a0
						commit
						c8ddd43f97
					
				|  | @ -34,7 +34,7 @@ cmake $CURRDIR -DCMAKE_BUILD_TYPE=Release \ | |||
| 
 | ||||
| make -j$(nproc) install | ||||
| 
 | ||||
| cd $CURRDIR/../gtsam_install/cython | ||||
| cd cython | ||||
| 
 | ||||
| sudo $PYTHON setup.py install | ||||
| 
 | ||||
|  |  | |||
|  | @ -454,12 +454,11 @@ endif() | |||
| if (GTSAM_INSTALL_CYTHON_TOOLBOX) | ||||
|   set(GTSAM_INSTALL_CYTHON_TOOLBOX 1) | ||||
|   # Set up cache options | ||||
|   set(GTSAM_CYTHON_INSTALL_PATH "" CACHE PATH "Cython toolbox destination, blank defaults to CMAKE_INSTALL_PREFIX/cython") | ||||
|   if(NOT GTSAM_CYTHON_INSTALL_PATH) | ||||
|     set(GTSAM_CYTHON_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/cython") | ||||
|   endif() | ||||
|   # Cython install path appended with Build type (e.g. cython, cythonDebug, etc). | ||||
|   # This does not override custom values set from the command line | ||||
|   set(GTSAM_CYTHON_INSTALL_PATH "${PROJECT_BINARY_DIR}/cython${GTSAM_BUILD_TAG}" CACHE PATH "Cython toolbox destination, blank defaults to PROJECT_BINARY_DIR/cython<GTSAM_BUILD_TAG>") | ||||
|   set(GTSAM_EIGENCY_INSTALL_PATH ${GTSAM_CYTHON_INSTALL_PATH}/gtsam_eigency) | ||||
|   add_subdirectory(cython) | ||||
|   add_subdirectory(cython ${GTSAM_CYTHON_INSTALL_PATH}) | ||||
| else() | ||||
|   set(GTSAM_INSTALL_CYTHON_TOOLBOX 0) # This will go into config.h | ||||
| endif() | ||||
|  |  | |||
|  | @ -41,9 +41,8 @@ execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" | |||
| function(wrap_and_install_library_cython interface_header extra_imports install_path libs dependencies) | ||||
|   # Paths for generated files | ||||
|   get_filename_component(module_name "${interface_header}" NAME_WE) | ||||
|   set(generated_files_path "${PROJECT_BINARY_DIR}/cython/${module_name}") | ||||
|   set(generated_files_path "${install_path}") | ||||
|   wrap_library_cython("${interface_header}" "${generated_files_path}" "${extra_imports}" "${libs}" "${dependencies}") | ||||
|   install_cython_wrapped_library("${interface_header}" "${generated_files_path}" "${install_path}") | ||||
| endfunction() | ||||
| 
 | ||||
| function(set_up_required_cython_packages) | ||||
|  | @ -138,6 +137,10 @@ function(cythonize target pyx_file output_lib_we output_dir include_dirs libs in | |||
|     target_link_libraries(${target} "${libs}") | ||||
|   endif() | ||||
|   add_dependencies(${target} ${target}_pyx2cpp) | ||||
| 
 | ||||
|   if(TARGET ${python_install_target}) | ||||
|     add_dependencies(${python_install_target} ${target}) | ||||
|   endif() | ||||
| endfunction() | ||||
| 
 | ||||
| # Internal function that wraps a library and compiles the wrapper | ||||
|  | @ -150,9 +153,12 @@ function(wrap_library_cython interface_header generated_files_path extra_imports | |||
|   get_filename_component(module_name "${interface_header}" NAME_WE) | ||||
| 
 | ||||
|   # Wrap module to Cython pyx | ||||
|   message(STATUS "Cython wrapper generating ${module_name}.pyx") | ||||
|   message(STATUS "Cython wrapper generating ${generated_files_path}/${module_name}.pyx") | ||||
|   set(generated_pyx "${generated_files_path}/${module_name}.pyx") | ||||
|   file(MAKE_DIRECTORY "${generated_files_path}") | ||||
|   if(NOT EXISTS ${generated_files_path}) | ||||
|     file(MAKE_DIRECTORY "${generated_files_path}") | ||||
|   endif() | ||||
| 
 | ||||
|   add_custom_command( | ||||
|     OUTPUT ${generated_pyx} | ||||
|     DEPENDS ${interface_header} wrap | ||||
|  | @ -175,46 +181,6 @@ function(wrap_library_cython interface_header generated_files_path extra_imports | |||
|       COMMAND cmake -E remove_directory ${generated_files_path}) | ||||
| endfunction() | ||||
| 
 | ||||
| # Internal function that installs a wrap toolbox | ||||
| function(install_cython_wrapped_library interface_header generated_files_path install_path) | ||||
|   get_filename_component(module_name "${interface_header}" NAME_WE) | ||||
| 
 | ||||
|   # NOTE: only installs .pxd and .pyx and binary files (not .cpp) - the trailing slash on the directory name | ||||
|   # here prevents creating the top-level module name directory in the destination. | ||||
|   # Split up filename to strip trailing '/' in GTSAM_CYTHON_INSTALL_PATH/subdirectory if there is one | ||||
|   get_filename_component(location "${install_path}" PATH) | ||||
|   get_filename_component(name "${install_path}" NAME) | ||||
|   message(STATUS "Installing Cython Toolbox to ${location}${GTSAM_BUILD_TAG}/${name}") #${GTSAM_CYTHON_INSTALL_PATH}" | ||||
| 
 | ||||
|   if(GTSAM_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() | ||||
| 
 | ||||
|       install(DIRECTORY "${generated_files_path}/" DESTINATION "${location}${build_type_tag}/${name}" | ||||
|           CONFIGURATIONS "${build_type}" | ||||
|           PATTERN "build" EXCLUDE | ||||
|           PATTERN "CMakeFiles" EXCLUDE | ||||
|           PATTERN "Makefile" EXCLUDE | ||||
|           PATTERN "*.cmake" EXCLUDE | ||||
|           PATTERN "*.cpp" EXCLUDE | ||||
|           PATTERN "*.py" EXCLUDE) | ||||
|     endforeach() | ||||
|   else() | ||||
|     install(DIRECTORY "${generated_files_path}/" DESTINATION ${install_path} | ||||
|         PATTERN "build" EXCLUDE | ||||
|         PATTERN "CMakeFiles" EXCLUDE | ||||
|         PATTERN "Makefile" EXCLUDE | ||||
|         PATTERN "*.cmake" EXCLUDE | ||||
|         PATTERN "*.cpp" EXCLUDE | ||||
|         PATTERN "*.py" EXCLUDE) | ||||
|   endif() | ||||
| endfunction() | ||||
| 
 | ||||
| # Helper function to install Cython scripts and handle multiple build types where the scripts | ||||
| # should be installed to all build type toolboxes | ||||
| # | ||||
|  | @ -232,50 +198,7 @@ function(install_cython_scripts source_directory dest_directory patterns) | |||
|   foreach(pattern ${patterns}) | ||||
|     list(APPEND patterns_args PATTERN "${pattern}") | ||||
|   endforeach() | ||||
|   if(GTSAM_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 GTSAM_CYTHON_INSTALL_PATH if there is one | ||||
|       get_filename_component(location "${dest_directory}" PATH) | ||||
|       get_filename_component(name "${dest_directory}" NAME) | ||||
|       install(DIRECTORY "${source_directory}" DESTINATION "${location}/${name}${build_type_tag}" CONFIGURATIONS "${build_type}" | ||||
| 
 | ||||
|   file(COPY "${source_directory}" DESTINATION "${dest_directory}" | ||||
|             FILES_MATCHING ${patterns_args} PATTERN "${exclude_patterns}" EXCLUDE) | ||||
|     endforeach() | ||||
|   else() | ||||
|     install(DIRECTORY "${source_directory}" DESTINATION "${dest_directory}" FILES_MATCHING ${patterns_args} PATTERN "${exclude_patterns}" EXCLUDE) | ||||
|   endif() | ||||
| 
 | ||||
| endfunction() | ||||
| 
 | ||||
| # Helper function to install specific files and handle multiple build types where the scripts | ||||
| # should be installed to all build type toolboxes | ||||
| # | ||||
| # Arguments: | ||||
| #  source_files: The source files to be installed. | ||||
| #  dest_directory: The destination directory to install to. | ||||
| function(install_cython_files source_files dest_directory) | ||||
| 
 | ||||
|   if(GTSAM_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 GTSAM_CYTHON_INSTALL_PATH if there is one | ||||
|       get_filename_component(location "${dest_directory}" PATH) | ||||
|       get_filename_component(name "${dest_directory}" NAME) | ||||
|       install(FILES "${source_files}" DESTINATION "${location}/${name}${build_type_tag}" CONFIGURATIONS "${build_type}") | ||||
|     endforeach() | ||||
|   else() | ||||
|     install(FILES "${source_files}" DESTINATION "${dest_directory}") | ||||
|   endif() | ||||
| 
 | ||||
| endfunction() | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,16 +3,32 @@ include(GtsamCythonWrap) | |||
| 
 | ||||
| # Create the cython toolbox for the gtsam library | ||||
| if (GTSAM_INSTALL_CYTHON_TOOLBOX) | ||||
|   # Add the new make target command | ||||
|   set(python_install_target python-install) | ||||
|   add_custom_target(${python_install_target} | ||||
|     COMMAND ${PYTHON_EXECUTABLE} ${GTSAM_CYTHON_INSTALL_PATH}/setup.py install | ||||
|     WORKING_DIRECTORY ${GTSAM_CYTHON_INSTALL_PATH}) | ||||
| 
 | ||||
|   # build and include the eigency version of eigency | ||||
|   add_subdirectory(gtsam_eigency) | ||||
|   include_directories(${PROJECT_BINARY_DIR}/cython/gtsam_eigency) | ||||
|   include_directories(${GTSAM_EIGENCY_INSTALL_PATH}) | ||||
| 
 | ||||
|   # Fix for error "C1128: number of sections exceeded object file format limit" | ||||
|   if(MSVC) | ||||
|     add_compile_options(/bigobj) | ||||
|   endif() | ||||
| 
 | ||||
|   # wrap gtsam | ||||
|   # First set up all the package related files. | ||||
|   # This also ensures the below wrap operations work correctly. | ||||
|   set(CYTHON_INSTALL_REQUIREMENTS_FILE "${PROJECT_SOURCE_DIR}/cython/requirements.txt") | ||||
| 
 | ||||
|   # Install the custom-generated __init__.py | ||||
|   # This makes the cython (sub-)directories into python packages, so gtsam can be found while wrapping gtsam_unstable | ||||
|   configure_file(${PROJECT_SOURCE_DIR}/cython/gtsam/__init__.py ${GTSAM_CYTHON_INSTALL_PATH}/gtsam/__init__.py COPYONLY) | ||||
|   configure_file(${PROJECT_SOURCE_DIR}/cython/gtsam_unstable/__init__.py ${GTSAM_CYTHON_INSTALL_PATH}/gtsam_unstable/__init__.py COPYONLY) | ||||
|   configure_file(${PROJECT_SOURCE_DIR}/cython/setup.py.in ${GTSAM_CYTHON_INSTALL_PATH}/setup.py) | ||||
| 
 | ||||
|   # Wrap gtsam | ||||
|   add_custom_target(gtsam_header DEPENDS "../gtsam.h") | ||||
|   wrap_and_install_library_cython("../gtsam.h" # interface_header | ||||
|                                   ""                  # extra imports | ||||
|  | @ -20,8 +36,9 @@ if (GTSAM_INSTALL_CYTHON_TOOLBOX) | |||
|                                   gtsam  # library to link with | ||||
|                                   "wrap;cythonize_eigency;gtsam;gtsam_header"  # dependencies which need to be built before wrapping | ||||
|                                   ) | ||||
|   add_dependencies(${python_install_target} gtsam gtsam_header) | ||||
| 
 | ||||
|   # wrap gtsam_unstable | ||||
|   # Wrap gtsam_unstable | ||||
|   if(GTSAM_BUILD_UNSTABLE) | ||||
|     add_custom_target(gtsam_unstable_header DEPENDS "../gtsam_unstable/gtsam_unstable.h") | ||||
|     wrap_and_install_library_cython("../gtsam_unstable/gtsam_unstable.h" # interface_header | ||||
|  | @ -30,17 +47,9 @@ if (GTSAM_INSTALL_CYTHON_TOOLBOX) | |||
|                                     gtsam_unstable  # library to link with | ||||
|                                     "gtsam_unstable;gtsam_unstable_header;cythonize_gtsam"  # dependencies to be built before wrapping | ||||
|                                     ) | ||||
|     add_dependencies(${python_install_target} gtsam_unstable gtsam_unstable_header) | ||||
|   endif() | ||||
| 
 | ||||
|   file(READ "${PROJECT_SOURCE_DIR}/cython/requirements.txt" CYTHON_INSTALL_REQUIREMENTS) | ||||
|   file(READ "${PROJECT_SOURCE_DIR}/README.md" README_CONTENTS) | ||||
| 
 | ||||
|   # Install the custom-generated __init__.py | ||||
|   # This is to make the build/cython/gtsam folder a python package, so gtsam can be found while wrapping gtsam_unstable | ||||
|   configure_file(${PROJECT_SOURCE_DIR}/cython/gtsam/__init__.py ${PROJECT_BINARY_DIR}/cython/gtsam/__init__.py COPYONLY) | ||||
|   configure_file(${PROJECT_SOURCE_DIR}/cython/gtsam_unstable/__init__.py ${PROJECT_BINARY_DIR}/cython/gtsam_unstable/__init__.py COPYONLY) | ||||
|   configure_file(${PROJECT_SOURCE_DIR}/cython/setup.py.in ${PROJECT_BINARY_DIR}/cython/setup.py) | ||||
|   install_cython_files("${PROJECT_BINARY_DIR}/cython/setup.py" "${GTSAM_CYTHON_INSTALL_PATH}") | ||||
|   # install scripts and tests | ||||
|   install_cython_scripts("${PROJECT_SOURCE_DIR}/cython/gtsam" "${GTSAM_CYTHON_INSTALL_PATH}" "*.py") | ||||
|   install_cython_scripts("${PROJECT_SOURCE_DIR}/cython/gtsam_unstable" "${GTSAM_CYTHON_INSTALL_PATH}" "*.py") | ||||
|  |  | |||
							
								
								
									
										134
									
								
								cython/README.md
								
								
								
								
							
							
						
						
									
										134
									
								
								cython/README.md
								
								
								
								
							|  | @ -1,43 +1,51 @@ | |||
| # Python Wrapper | ||||
| 
 | ||||
| This is the Cython/Python wrapper around the GTSAM C++ library. | ||||
| This is the Python wrapper around the GTSAM C++ library. We use Cython to generate the bindings to the underlying C++ code. | ||||
| 
 | ||||
| ## Requirements | ||||
| 
 | ||||
| - If you want to build the GTSAM python library for a specific python version (eg 3.6), | ||||
|   use the `-DGTSAM_PYTHON_VERSION=3.6` option when running `cmake` otherwise the default interpreter will be used. | ||||
| - If the interpreter is inside an environment (such as an anaconda environment or virtualenv environment), | ||||
|   then the environment should be active while building GTSAM. | ||||
| - This wrapper needs `Cython(>=0.25.2)`, `backports_abc(>=0.5)`, and `numpy(>=1.11.0)`. These can be installed as follows: | ||||
| 
 | ||||
|   ```bash | ||||
|   pip install -r <gtsam_folder>/cython/requirements.txt | ||||
|   ``` | ||||
| 
 | ||||
| - For compatibility with GTSAM's Eigen version, it contains its own cloned version of [Eigency](https://github.com/wouterboomsma/eigency.git), | ||||
|   named `gtsam_eigency`, to interface between C++'s Eigen and Python's numpy. | ||||
| 
 | ||||
| ## Install | ||||
| 
 | ||||
| - if you want to build the gtsam python library for a specific python version (eg 2.7), use the `-DGTSAM_PYTHON_VERSION=2.7` option when running `cmake` otherwise the default interpreter will be used. | ||||
|     - If the interpreter is inside an environment (such as an anaconda environment or virtualenv environment) then the environment should be active while building gtsam. | ||||
| - This wrapper needs Cython(>=0.25.2), backports_abc>=0.5, and numpy. These can be installed as follows: | ||||
| - Run cmake with the `GTSAM_INSTALL_CYTHON_TOOLBOX` cmake flag enabled to configure building the wrapper. The wrapped module will be built and copied to the directory defined by `GTSAM_CYTHON_INSTALL_PATH`, which is by default `<PROJECT_BINARY_DIR>/cython` in Release mode and `<PROJECT_BINARY_DIR>/cython<CMAKE_BUILD_TYPE>` for other modes. | ||||
| 
 | ||||
| ```bash | ||||
|  pip install -r <gtsam_folder>/cython/requirements.txt | ||||
| ``` | ||||
| - Build GTSAM and the wrapper with `make`. | ||||
| 
 | ||||
| - For compatibility with gtsam's Eigen version, it contains its own cloned version of [Eigency](https://github.com/wouterboomsma/eigency.git), | ||||
| named **gtsam_eigency**, to interface between C++'s Eigen and Python's numpy. | ||||
| - To install, simply run `make python-install`. | ||||
|   - The same command can be used to install into a virtual environment if it is active. | ||||
|   - **NOTE**: if you don't want GTSAM to install to a system directory such as `/usr/local`, pass `-DCMAKE_INSTALL_PREFIX="./install"` to cmake to install GTSAM to a subdirectory of the build directory. | ||||
| 
 | ||||
| - Build and install gtsam using cmake with `GTSAM_INSTALL_CYTHON_TOOLBOX` enabled. | ||||
| The wrapped module will be installed to `GTSAM_CYTHON_INSTALL_PATH`, which is | ||||
| by default: `<your CMAKE_INSTALL_PREFIX>/cython` | ||||
| 
 | ||||
| - To use the library without installing system-wide: modify your `PYTHONPATH` to include the `GTSAM_CYTHON_INSTALL_PATH`: | ||||
| ```bash | ||||
| export PYTHONPATH=$PYTHONPATH:<GTSAM_CYTHON_INSTALL_PATH> | ||||
| ``` | ||||
| - To install system-wide: run `make install` then navigate to `GTSAM_CYTHON_INSTALL_PATH` and run `python setup.py install` | ||||
|     - (the same command can be used to install into a virtual environment if it is active) | ||||
|     - note: if you don't want gtsam to install to a system directory such as `/usr/local`, pass `-DCMAKE_INSTALL_PREFIX="./install"` to cmake to install gtsam to a subdirectory of the build directory. | ||||
|     - if you run `setup.py` from the build directory rather than the installation directory, the script will warn you with the message: `setup.py is being run from an unexpected location`. | ||||
|       Before `make install` is run, not all the components of the package have been copied across, so running `setup.py` from the build directory would result in an incomplete package. | ||||
| - You can also directly run `make python-install` without running `make`, and it will compile all the dependencies accordingly. | ||||
| 
 | ||||
| ## Unit Tests | ||||
| 
 | ||||
| The Cython toolbox also has a small set of unit tests located in the | ||||
| test directory. To run them: | ||||
| 
 | ||||
| ```bash | ||||
|  cd <your GTSAM_CYTHON_INSTALL_PATH> | ||||
|  python -m unittest discover | ||||
| ``` | ||||
|   ```bash | ||||
|   cd <GTSAM_CYTHON_INSTALL_PATH> | ||||
|   python -m unittest discover | ||||
|   ``` | ||||
| 
 | ||||
| ## Utils | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| ## Examples | ||||
| 
 | ||||
| TODO | ||||
| 
 | ||||
| ## Writing Your Own Scripts | ||||
| 
 | ||||
|  | @ -46,79 +54,63 @@ See the tests for examples. | |||
| ### Some Important Notes: | ||||
| 
 | ||||
| - Vector/Matrix: | ||||
|   + GTSAM expects double-precision floating point vectors and matrices. | ||||
|     Hence, you should pass numpy matrices with dtype=float, or 'float64'. | ||||
|   + Also, GTSAM expects *column-major* matrices, unlike the default storage | ||||
|     scheme in numpy. Hence, you should pass column-major matrices to gtsam using | ||||
| 
 | ||||
|   - GTSAM expects double-precision floating point vectors and matrices. | ||||
|     Hence, you should pass numpy matrices with `dtype=float`, or `float64`. | ||||
|   - Also, GTSAM expects _column-major_ matrices, unlike the default storage | ||||
|     scheme in numpy. Hence, you should pass column-major matrices to GTSAM using | ||||
|     the flag order='F'. And you always get column-major matrices back. | ||||
|     For more details, see: https://github.com/wouterboomsma/eigency#storage-layout---why-arrays-are-sometimes-transposed | ||||
|   + Passing row-major matrices of different dtype, e.g. 'int', will also work | ||||
|     For more details, see [this link](https://github.com/wouterboomsma/eigency#storage-layout---why-arrays-are-sometimes-transposed). | ||||
|   - Passing row-major matrices of different dtype, e.g. `int`, will also work | ||||
|     as the wrapper converts them to column-major and dtype float for you, | ||||
|     using numpy.array.astype(float, order='F', copy=False). | ||||
|     However, this will result a copy if your matrix is not in the expected type | ||||
|     and storage order. | ||||
| 
 | ||||
| - Inner namespace: Classes in inner namespace will be prefixed by <innerNamespace>_ in Python. | ||||
| Examples: noiseModel_Gaussian, noiseModel_mEstimator_Tukey | ||||
| - Inner namespace: Classes in inner namespace will be prefixed by <innerNamespace>\_ in Python. | ||||
| 
 | ||||
|   Examples: `noiseModel_Gaussian`, `noiseModel_mEstimator_Tukey` | ||||
| 
 | ||||
| - Casting from a base class to a derive class must be done explicitly. | ||||
| Examples: | ||||
| ```Python | ||||
|       noiseBase = factor.noiseModel() | ||||
|       noiseGaussian = dynamic_cast_noiseModel_Gaussian_noiseModel_Base(noiseBase) | ||||
| ``` | ||||
| 
 | ||||
| ## Wrapping Your Own Project That Uses GTSAM | ||||
|   Examples: | ||||
| 
 | ||||
| - Set PYTHONPATH to include ${GTSAM_CYTHON_INSTALL_PATH} | ||||
|   + so that it can find gtsam Cython header: gtsam/gtsam.pxd | ||||
|   ```python | ||||
|   noiseBase = factor.noiseModel() | ||||
|   noiseGaussian = dynamic_cast_noiseModel_Gaussian_noiseModel_Base(noiseBase) | ||||
|   ``` | ||||
| 
 | ||||
| - In your CMakeList.txt | ||||
| ```cmake | ||||
| find_package(GTSAM REQUIRED) # Make sure gtsam's install folder is in your PATH | ||||
| set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${GTSAM_DIR}/../GTSAMCMakeTools") | ||||
| ## Wrapping Custom GTSAM-based Project | ||||
| 
 | ||||
| # Wrap | ||||
| include(GtsamCythonWrap) | ||||
| include_directories(${GTSAM_EIGENCY_INSTALL_PATH}) | ||||
| wrap_and_install_library_cython("your_project_interface.h" | ||||
|                                 "from gtsam.gtsam cimport *" # extra import of gtsam/gtsam.pxd Cython header | ||||
|                                 "your_install_path" | ||||
|                                 "libraries_to_link_with_the_cython_module" | ||||
|                                 "dependencies_which_need_to_be_built_before_the_wrapper" | ||||
|                                 ) | ||||
| #Optional: install_cython_scripts and install_cython_files. See GtsamCythonWrap.cmake. | ||||
| ``` | ||||
| Please refer to the template project and the corresponding tutorial available [here](https://github.com/borglab/GTSAM-project-python). | ||||
| 
 | ||||
| ## KNOWN ISSUES | ||||
| 
 | ||||
|   - Doesn't work with python3 installed from homebrew | ||||
|     - size-related issue: can only wrap up to a certain number of classes: up to mEstimator! | ||||
|     - Guess: 64 vs 32b? disutils Compiler flags? | ||||
|   - Bug with Cython 0.24: instantiated factor classes return FastVector<size_t> for keys(), which can't be casted to FastVector<Key> | ||||
|     - Upgrading to 0.25 solves the problem | ||||
|   - Need default constructor and default copy constructor for almost every classes... :( | ||||
|     - support these constructors by default and declare "delete" for special classes? | ||||
| 
 | ||||
| - Doesn't work with python3 installed from homebrew | ||||
|   - size-related issue: can only wrap up to a certain number of classes: up to mEstimator! | ||||
|   - Guess: 64 vs 32b? disutils Compiler flags? | ||||
| - Bug with Cython 0.24: instantiated factor classes return FastVector<size_t> for keys(), which can't be casted to FastVector<Key> | ||||
|   - Upgrading to 0.25 solves the problem | ||||
| - Need default constructor and default copy constructor for almost every classes... :( | ||||
|   - support these constructors by default and declare "delete" for special classes? | ||||
| 
 | ||||
| ### TODO | ||||
| 
 | ||||
| - [ ] allow duplication of parent' functions in child classes. Not allowed for now due to conflicts in Cython. | ||||
| - [ ] a common header for boost shared_ptr? (Or wait until everything is switched to std::shared_ptr in gtsam?) | ||||
| - [ ] a common header for boost shared_ptr? (Or wait until everything is switched to std::shared_ptr in GTSAM?) | ||||
| - [ ] inner namespaces ==> inner packages? | ||||
| - [ ] Wrap fixed-size Matrices/Vectors? | ||||
| 
 | ||||
| 
 | ||||
| ### Completed/Cancelled: | ||||
| 
 | ||||
| - [x] Fix Python tests: don't use " import <package> * ": Bad style!!! (18-03-17 19:50) | ||||
| - [x] Fix Python tests: don't use " import <package> \* ": Bad style!!! (18-03-17 19:50) | ||||
| - [x] Unit tests for cython wrappers @done (18-03-17 18:45) -- simply compare generated files | ||||
| - [x] Wrap unstable @done (18-03-17 15:30) | ||||
| - [x] Unify cython/gtsam.h and the original gtsam.h @done (18-03-17 15:30) | ||||
| - [x] Unify cython/GTSAM.h and the original GTSAM.h @done (18-03-17 15:30) | ||||
| - [x] 18-03-17: manage to unify the two versions by removing std container stubs from the matlab version,and keeping KeyList/KeyVector/KeySet as in the matlab version. Probably Cython 0.25 fixes the casting problem. | ||||
| - [x] 06-03-17: manage to remove the requirements for default and copy constructors | ||||
| - [ ] 25-11-16: Try to unify but failed. Main reasons are: Key/size_t, std containers, KeyVector/KeyList/KeySet. Matlab doesn't need to know about Key, but I can't make Cython to ignore Key as it couldn't cast KeyVector, i.e. FastVector<Key>, to FastVector<size_t>. | ||||
| - [ ] Marginal and JointMarginal: revert changes @failed (17-03-17 11:00) -- Cython does need a default constructor! It produces cpp code like this: ```gtsam::JointMarginal __pyx_t_1;```  Users don't have to wrap this constructor, however. | ||||
| - [ ] Marginal and JointMarginal: revert changes @failed (17-03-17 11:00) -- Cython does need a default constructor! It produces cpp code like this: `GTSAM::JointMarginal __pyx_t_1;` Users don't have to wrap this constructor, however. | ||||
| - [x] Convert input numpy Matrix/Vector to float dtype and storage order 'F' automatically, cannot crash! @done (15-03-17 13:00) | ||||
| - [x] Remove requirements.txt - Frank: don't bother with only 2 packages and a special case for eigency! @done (08-03-17 10:30) | ||||
| - [x] CMake install script @done (25-11-16 02:30) | ||||
|  | @ -132,7 +124,7 @@ wrap_and_install_library_cython("your_project_interface.h" | |||
| - [x] Casting from parent and grandparents @done (16-11-16 17:00) | ||||
| - [x] Allow overloading constructors. The current solution is annoying!!! @done (16-11-16 17:00) | ||||
| - [x] Support "print obj" @done (16-11-16 17:00) | ||||
| - [x] methods for FastVector: at, [], ...  @done (16-11-16 17:00) | ||||
| - [x] methods for FastVector: at, [], ... @done (16-11-16 17:00) | ||||
| - [x] Cython: Key and size_t: traits<size_t> doesn't exist @done (16-09-12 18:34) | ||||
| - [x] KeyVector, KeyList, KeySet... @done (16-09-13 17:19) | ||||
| - [x] [Nice to have] parse typedef @done (16-09-13 17:19) | ||||
|  |  | |||
|  | @ -4,11 +4,11 @@ include(GtsamCythonWrap) | |||
| # so that the cython-generated header "conversions_api.h" can be found when cythonizing eigency's core | ||||
| # and eigency's cython pxd headers can be found when cythonizing gtsam | ||||
| file(COPY "." DESTINATION ".") | ||||
| set(OUTPUT_DIR "${PROJECT_BINARY_DIR}/cython/gtsam_eigency") | ||||
| set(OUTPUT_DIR "${GTSAM_CYTHON_INSTALL_PATH}/gtsam_eigency") | ||||
| set(EIGENCY_INCLUDE_DIR ${OUTPUT_DIR}) | ||||
| 
 | ||||
| # This is to make the build/cython/gtsam_eigency folder a python package | ||||
| configure_file(__init__.py.in ${PROJECT_BINARY_DIR}/cython/gtsam_eigency/__init__.py) | ||||
| configure_file(__init__.py.in ${OUTPUT_DIR}/__init__.py) | ||||
| 
 | ||||
| # include eigency headers | ||||
| include_directories(${EIGENCY_INCLUDE_DIR}) | ||||
|  | @ -16,8 +16,8 @@ include_directories(${EIGENCY_INCLUDE_DIR}) | |||
| # Cythonize and build eigency | ||||
| message(STATUS "Cythonize and build eigency") | ||||
| # Important trick: use "../gtsam_eigency/conversions.pyx" to let cython know that the conversions module is | ||||
| # a part of the gtsam_eigency package and generate the function call import_gtsam_igency__conversions() | ||||
| # in conversions_api.h correctly!!! | ||||
| # a part of the gtsam_eigency package and generate the function call import_gtsam_eigency__conversions() | ||||
| # in conversions_api.h correctly! | ||||
| cythonize(cythonize_eigency_conversions "../gtsam_eigency/conversions.pyx" "conversions" | ||||
|   "${OUTPUT_DIR}" "${EIGENCY_INCLUDE_DIR}" "" "" "") | ||||
| cythonize(cythonize_eigency_core "../gtsam_eigency/core.pyx" "core" | ||||
|  | @ -37,13 +37,6 @@ add_dependencies(cythonize_eigency_core cythonize_eigency_conversions) | |||
| add_custom_target(cythonize_eigency) | ||||
| add_dependencies(cythonize_eigency cythonize_eigency_conversions cythonize_eigency_core) | ||||
| 
 | ||||
| # install | ||||
| install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||||
|         DESTINATION "${GTSAM_CYTHON_INSTALL_PATH}${GTSAM_BUILD_TAG}" | ||||
|         PATTERN "CMakeLists.txt" EXCLUDE | ||||
|         PATTERN "__init__.py.in" EXCLUDE) | ||||
| install(TARGETS cythonize_eigency_core cythonize_eigency_conversions | ||||
|         DESTINATION "${GTSAM_CYTHON_INSTALL_PATH}${GTSAM_BUILD_TAG}/gtsam_eigency") | ||||
| install(FILES ${OUTPUT_DIR}/conversions_api.h DESTINATION ${GTSAM_CYTHON_INSTALL_PATH}${GTSAM_BUILD_TAG}/gtsam_eigency) | ||||
| configure_file(__init__.py.in ${OUTPUT_DIR}/__init__.py) | ||||
| install(FILES ${OUTPUT_DIR}/__init__.py DESTINATION ${GTSAM_CYTHON_INSTALL_PATH}${GTSAM_BUILD_TAG}/gtsam_eigency) | ||||
| if(TARGET ${python_install_target}) | ||||
|   add_dependencies(${python_install_target} cythonize_eigency) | ||||
| endif() | ||||
|  |  | |||
|  | @ -7,6 +7,22 @@ except ImportError: | |||
| 
 | ||||
| packages = find_packages() | ||||
| 
 | ||||
| package_data = { | ||||
|     package: | ||||
|         [f for f in os.listdir(package.replace('.', os.path.sep)) if os.path.splitext(f)[1] in ('.so', '.pyd')] | ||||
|         for package in packages | ||||
| } | ||||
| 
 | ||||
| cython_install_requirements = open("${CYTHON_INSTALL_REQUIREMENTS_FILE}").readlines() | ||||
| 
 | ||||
| install_requires = [line.strip() \ | ||||
|     for line in cython_install_requirements \ | ||||
|     if len(line.strip()) > 0 and not line.strip().startswith('#') | ||||
| ] | ||||
| 
 | ||||
| # Cleaner to read in the contents rather than copy them over. | ||||
| readme_contents = open("${PROJECT_SOURCE_DIR}/README.md").read() | ||||
| 
 | ||||
| setup( | ||||
|     name='gtsam', | ||||
|     description='Georgia Tech Smoothing And Mapping library', | ||||
|  | @ -16,7 +32,7 @@ setup( | |||
|     author_email='frank.dellaert@gtsam.org', | ||||
|     license='Simplified BSD license', | ||||
|     keywords='slam sam robotics localization mapping optimization', | ||||
|     long_description='''${README_CONTENTS}''', | ||||
|     long_description=readme_contents, | ||||
|     long_description_content_type='text/markdown', | ||||
|     python_requires='>=2.7', | ||||
|     # https://pypi.org/pypi?%3Aaction=list_classifiers | ||||
|  | @ -34,11 +50,6 @@ setup( | |||
|     ], | ||||
| 
 | ||||
|     packages=packages, | ||||
|     package_data={package: | ||||
|         [f for f in os.listdir(package.replace('.', os.path.sep)) if os.path.splitext(f)[1] in ('.so', '.pyd')] | ||||
|         for package in packages | ||||
|     }, | ||||
|     install_requires=[line.strip() for line in ''' | ||||
| ${CYTHON_INSTALL_REQUIREMENTS} | ||||
| '''.splitlines() if len(line.strip()) > 0 and not line.strip().startswith('#')] | ||||
|     package_data=package_data, | ||||
|     install_requires=install_requires | ||||
| ) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue