-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from borglab/full-working-example
Full Working Example
- Loading branch information
Showing
10 changed files
with
308 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,5 +33,5 @@ | |
|
||
# Directories | ||
.ipynb_checkpoints/* | ||
build/* | ||
**/build/* | ||
example/__pycache__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
# gtsam-project-python | ||
Project template using GTSAM + python wrapping | ||
|
||
# DISCLAIMER | ||
Under construction, doesn't work yet!! :( | ||
Please refer to the [tutorial](TUTORIAL.md) to get started. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# Tutorial | ||
|
||
This is a tutorial on how to wrap your own C++ projects using GTSAM's python wrapper. | ||
|
||
# Prerequisites | ||
|
||
We assume you have Python 3 installed. We support Python 3.6 and up. | ||
|
||
We also assume some knowledge of how Python packaging and setup works. If you understand how to write your own basic `setup.py` file, you should be fine. | ||
Using this template project, you should only need to update the metadata information about your project. Check out the [python packaging website](https://packaging.python.org/tutorials/packaging-projects/) to learn more. | ||
|
||
As a bonus, if you understand Cython's build process, this tutorial should be fairly intuitive. | ||
|
||
**NOTE** This tutorial has been tested using GTSAM version 4.0.x and above. | ||
|
||
# Project Setup | ||
|
||
As a set of minimal requirements, the project should be set up as follows: | ||
|
||
``` | ||
top-level-directory | ||
| | ||
|- CMakeLists.txt | ||
|- <project>.h | ||
|- __init__.py.in | ||
|- setup.py | ||
|- src/ | ||
``` | ||
|
||
The files are | ||
|
||
1. `CMakeLists.txt`: The cmake definition file. | ||
2. `<project>.h`: The header file which specifies all the code components to be wrapped. | ||
3. `__init__.py.in`: Template __init__.py file used by cmake. | ||
4. `setup.py`: The file used by setuptools to generate the egg/wheel. | ||
5. `src/`: All your C++ source code goes here. | ||
|
||
|
||
# CMake Configuration | ||
|
||
In this section, we will go through a step-by-step process of defining the `CMakeLists.txt` file which will generated our wrapped code. | ||
|
||
An illustrative example is provided in the `src` directory of this repository. | ||
|
||
1. Define project name. | ||
2. Optionally, set the Python version you'd like to target. This should ideally be the same as the version you used to build the wrapper. | ||
3. Include `GTSAM` package. This allows use to use the cython install path automatically. CMake will take care of the rest. | ||
|
||
```cmake | ||
find_package(GTSAM REQUIRED) | ||
include_directories(${GTSAM_CYTHON_INSTALL_PATH}) | ||
include_directories(${GTSAM_EIGENCY_INSTALL_PATH}) | ||
``` | ||
4. The second package is `GTSAMCMakeTools`. This gives us access to the wrapping functions which we will use later on. | ||
```cmake | ||
find_package(GTSAMCMakeTools CONFIG) | ||
include(GtsamCythonWrap) # Automatic Cython wrapper generation | ||
``` | ||
5. These next few steps should be familiar for CMake users. We first include the project source directory. | ||
```cmake | ||
include_directories(BEFORE "${PROJECT_SOURCE_DIR}") | ||
``` | ||
6. Now we can specify the building and linking of our project code as a shared library. | ||
```cmake | ||
add_library(${PROJECT_NAME} SHARED src/greeting.h src/greeting.cpp) | ||
target_link_libraries(${PROJECT_NAME} gtsam) | ||
``` | ||
7. And finally, we can install the shared library. | ||
```cmake | ||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin) | ||
``` | ||
8. Now we get to the wrapping part. To specify our project as a package we need to include an `__init__.py` file at the top level. This will allow python imports to work correctly. We can use the basic `__init__.py.in` template in this repo since it is pretty generic. | ||
```cmake | ||
configure_file(${PROJECT_SOURCE_DIR}/__init__.py.in ${PROJECT_BINARY_DIR}/cython/${PROJECT_NAME}/__init__.py) | ||
``` | ||
9. To help build and install the wrapped project, we make use of a `setup.py` file. This file can be customized as per your requirements. **NOTE** This command only copies over the `setup.py` file, so make sure you make any updates **BEFORE** you run `cmake`. | ||
```cmake | ||
configure_file(${PROJECT_SOURCE_DIR}/setup.py ${PROJECT_BINARY_DIR}/cython/setup.py COPYONLY) | ||
``` | ||
10. Finally, we specify the wrapping function so that the GTSAM wrapper can do its job. We require only one function `wrap_and_install_library_cython` which takes the following 5 arguments: | ||
1. Interface Header: A `.h` file which defines what classes, functions, etc., are to be wrapped. | ||
2. Extra Imports: This is a set of `cython` imports included in the generated Cython files. You can use this to specify any additional imports your project may be dependent on. | ||
3. Install Path: This is the location where the wrapped package will be installed on running `make install`. | ||
4. Libraries: A semi-colon separated list of libraries which the project will be linked against. At the very least, you should link against `gtsam` and the generated shared object file. | ||
5. Dependencies: This is a semi-colon separated list of dependency targets that need to be built before the code can be compiled and wrapped. This is nothing but a list of CMake targets. | ||
```cmake | ||
wrap_and_install_library_cython("example.h" # interface_header | ||
"" # extra imports | ||
"./${PROJECT_NAME}" # install path | ||
"gtsam;${PROJECT_NAME}" # library to link with | ||
"wrap;gtsam" # dependencies which need to be built before wrapping | ||
) | ||
``` | ||
# Compiling | ||
To compile and wrap the code, the familiar CMake process is followed. Starting from the directory where the `setup.py` file is located, we create a build directory and run `cmake` and `make`. | ||
```sh | ||
mkdir build && cd build | ||
cmake .. && make | ||
``` | ||
|
||
Finally, we go into the generated `cython` directory where the `setup.py` file is present, and run `python setup.py build` to generate the final package. | ||
|
||
# Installing | ||
|
||
To install the package, in the `cython` directory we can run `python setup.py build`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# This file should be used as a template for creating new projects with Python wrapping using the CMake tools | ||
|
||
################################################################################### | ||
# 1. To create your own project, replace "example" with the actual name of your project | ||
cmake_minimum_required(VERSION 3.0) | ||
project(example CXX C) | ||
|
||
################################################################################### | ||
# 2. Set the python version | ||
set(GTSAM_PYTHON_VERSION "3.6") | ||
|
||
################################################################################### | ||
# 3. Find GTSAM components so we have access to the GTSAM Cython install path | ||
find_package(GTSAM REQUIRED) # Uses installed package | ||
# Note: Since Jan-2019, GTSAMConfig.cmake defines exported CMake targets | ||
# that automatically do include the include_directories() without the need | ||
# to call include_directories(), just target_link_libraries(NAME gtsam) | ||
#include_directories(${GTSAM_INCLUDE_DIR}) | ||
|
||
# Include the required GTSAM Cython libraries | ||
include_directories(${GTSAM_CYTHON_INSTALL_PATH}) | ||
include_directories(${GTSAM_EIGENCY_INSTALL_PATH}) | ||
|
||
################################################################################### | ||
# 4. Get the wrapping functions | ||
# Include GTSAM CMake tools | ||
find_package(GTSAMCMakeTools CONFIG) | ||
#include(GtsamBuildTypes) # Load build type flags and default to Debug mode | ||
#include(GtsamTesting) # Easy functions for creating unit tests and scripts | ||
include(GtsamCythonWrap) # Automatic Cython wrapper generation | ||
|
||
################################################################################### | ||
# 5. Add the local source directory for CMake | ||
# Ensure that local folder is searched before library folders | ||
include_directories(BEFORE "${PROJECT_SOURCE_DIR}") | ||
|
||
|
||
################################################################################### | ||
# 6. Build static library from common sources | ||
add_library(${PROJECT_NAME} SHARED src/greeting.h src/greeting.cpp) | ||
target_link_libraries(${PROJECT_NAME} gtsam) | ||
|
||
################################################################################### | ||
# 7. Install library | ||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin) | ||
|
||
################################################################################### | ||
# # Build tests (CMake tracks the dependecy to link with GTSAM through our project's static library) | ||
# gtsamAddTestsGlob("${PROJECT_NAME}" "tests/test*.cpp" "" "${PROJECT_NAME}") | ||
|
||
################################################################################### | ||
# # Build scripts (CMake tracks the dependecy to link with GTSAM through our project's static library) | ||
# gtsamAddExamplesGlob("*.cpp" "" "${PROJECT_NAME}") | ||
|
||
################################################################################### | ||
# 8. Copy the __init__.py file so Cython recognizes this as a package. | ||
# This function also updates the contents to use the correct package name. | ||
configure_file(${PROJECT_SOURCE_DIR}/__init__.py.in ${PROJECT_BINARY_DIR}/cython/${PROJECT_NAME}/__init__.py) | ||
|
||
################################################################################### | ||
# 9. (Strict) Copy over the setup.py file so we can build and install the package. | ||
configure_file(${PROJECT_SOURCE_DIR}/setup.py ${PROJECT_BINARY_DIR}/cython/setup.py COPYONLY) | ||
|
||
################################################################################### | ||
# 10. Build Cython wrapper (CMake tracks the dependecy to link with GTSAM through our project's static library) | ||
wrap_and_install_library_cython("example.h" # interface_header | ||
"" # extra imports | ||
"./${PROJECT_NAME}" # install path | ||
"gtsam;${PROJECT_NAME}" # library to link with | ||
"wrap;gtsam" # dependencies which need to be built before wrapping | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .${PROJECT_NAME} import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* ---------------------------------------------------------------------------- | ||
* GTSAM Copyright 2010, Georgia Tech Research Corporation, | ||
* Atlanta, Georgia 30332-0415 | ||
* All Rights Reserved | ||
* Authors: Frank Dellaert, et al. (see THANKS for the full author list) | ||
* See LICENSE for the license information | ||
* -------------------------------------------------------------------------- */ | ||
|
||
/** | ||
* @file example.h | ||
* @brief Example wrapper interface file for Python | ||
* @author Varun Agrawal | ||
*/ | ||
|
||
// This is an interface file for automatic Python wrapper generation. See | ||
// gtsam.h for full documentation and more examples. | ||
|
||
#include <src/greeting.h> | ||
|
||
namespace example { | ||
|
||
class Greeting { | ||
Greeting(); | ||
void sayHello() const; | ||
void sayGoodbye() const; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import os | ||
import sys | ||
try: | ||
from setuptools import setup, find_packages | ||
except ImportError: | ||
from distutils.core import setup, find_packages | ||
|
||
packages = find_packages() | ||
|
||
setup( | ||
name='example', | ||
description='Simple example of wrapping projects with Python and GTSAM', | ||
url='https://gtsam.org/', | ||
version='1.0.0', | ||
author='Varun Agrawal', | ||
author_email='[email protected]', | ||
license='Simplified BSD license', | ||
keywords='wrapper tutorial example', | ||
long_description="", | ||
long_description_content_type='text/markdown', | ||
python_requires='>=3.6', | ||
# https://pypi.org/pypi?%3Aaction=list_classifiers | ||
classifiers=[ | ||
'Development Status :: 5 - Production/Stable', | ||
'Intended Audience :: Education', | ||
'Intended Audience :: Developers', | ||
'Intended Audience :: Science/Research', | ||
'Operating System :: MacOS', | ||
'Operating System :: Microsoft :: Windows', | ||
'Operating System :: POSIX', | ||
'License :: OSI Approved :: BSD License', | ||
'Programming Language :: Python :: 2', | ||
'Programming Language :: Python :: 3', | ||
], | ||
|
||
packages=packages, | ||
# Load the built shared object files | ||
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>=0.25.2 | ||
backports_abc>=0.5 | ||
numpy>=1.12.0 | ||
'''.splitlines() if len(line.strip()) > 0 and not line.strip().startswith('#')] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#include "greeting.h" | ||
|
||
namespace example { | ||
|
||
/// Print a greeting | ||
void Greeting::sayHello() const { | ||
std::cout << "Hello from GTSAM!" << std::endl; | ||
std::cout << "Here's a Rot3 for you " << gtsam::Rot3() << std::endl; | ||
} | ||
|
||
/// Print a farewell | ||
void Greeting::sayGoodbye() const { | ||
std::cout << "Goodbye, robot" << std::endl; | ||
} | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#include <gtsam/geometry/Rot3.h> | ||
#include <iostream> | ||
#include <string> | ||
|
||
namespace example { | ||
|
||
class Greeting { | ||
public: | ||
/// Print a greeting | ||
void sayHello() const; | ||
|
||
/// Print a farewell | ||
void sayGoodbye() const; | ||
}; | ||
|
||
} // namespace example |