Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrapper Update #727

Merged
merged 14 commits into from
Mar 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/scripts/python.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ PATH=$PATH:$($PYTHON -c "import site; print(site.USER_BASE)")/bin


BUILD_PYBIND="ON"
TYPEDEF_POINTS_TO_VECTORS="ON"

sudo $PYTHON -m pip install -r $GITHUB_WORKSPACE/python/requirements.txt

Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ if(GTSAM_BUILD_PYTHON OR GTSAM_INSTALL_MATLAB_TOOLBOX)
# Need to set this for the wrap package so we don't use the default value.
set(WRAP_PYTHON_VERSION ${GTSAM_PYTHON_VERSION}
CACHE STRING "The Python version to use for wrapping")
# Set the include directory for matlab.h
set(GTWRAP_INCLUDE_NAME "wrap")
add_subdirectory(wrap)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/wrap/cmake")
endif()
Expand Down
2 changes: 1 addition & 1 deletion matlab/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ if(GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX)

# Wrap
matlab_wrap(${GTSAM_SOURCE_DIR}/gtsam_unstable/gtsam_unstable.i "gtsam" ""
"${mexFlags}")
"${mexFlags}" "${ignore}")
endif(GTSAM_UNSTABLE_INSTALL_MATLAB_TOOLBOX)

# Record the root dir for gtsam - needed during external builds, e.g., ROS
Expand Down
52 changes: 0 additions & 52 deletions wrap/.github/workflows/ci.yml

This file was deleted.

39 changes: 39 additions & 0 deletions wrap/.github/workflows/linux-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Wrap CI for Linux

on: [pull_request]

jobs:
build:
name: Tests for 🐍 ${{ matrix.python-version }}
runs-on: ubuntu-18.04

strategy:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Install Dependencies
run: |
sudo apt-get -y update
sudo apt install cmake build-essential pkg-config libpython-dev python-numpy libboost-all-dev

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Python Dependencies
run: |
sudo pip3 install -U pip setuptools
sudo pip3 install -r requirements.txt

- name: Build and Test
run: |
cmake .
cd tests
# Use Pytest to run all the tests.
pytest
38 changes: 38 additions & 0 deletions wrap/.github/workflows/macos-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Wrap CI for macOS

on: [pull_request]

jobs:
build:
name: Tests for 🐍 ${{ matrix.python-version }}
runs-on: macos-10.15

strategy:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Install Dependencies
run: |
brew install cmake ninja boost

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Python Dependencies
run: |
pip3 install -r requirements.txt

- name: Build and Test
run: |
cmake .
cd tests
# Use Pytest to run all the tests.
pytest

5 changes: 5 additions & 0 deletions wrap/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ __pycache__/
*build*
*dist*
*.egg-info

# Files related to code coverage stats
**/.coverage

gtwrap/matlab_wrapper.tpl
15 changes: 11 additions & 4 deletions wrap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ else()
set(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/cmake")
endif()

# Configure the include directory for matlab.h
# This allows the #include to be either gtwrap/matlab.h, wrap/matlab.h or something custom.
if(NOT DEFINED GTWRAP_INCLUDE_NAME)
set(GTWRAP_INCLUDE_NAME "gtwrap" CACHE INTERNAL "Directory name for Matlab includes")
endif()
configure_file(${PROJECT_SOURCE_DIR}/templates/matlab_wrapper.tpl.in ${PROJECT_SOURCE_DIR}/gtwrap/matlab_wrapper.tpl)

# Install CMake scripts to the standard CMake script directory.
install(FILES cmake/gtwrapConfig.cmake cmake/MatlabWrap.cmake
cmake/PybindWrap.cmake cmake/GtwrapUtils.cmake
Expand All @@ -31,17 +38,17 @@ include(GNUInstallDirs)

# 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(DIRECTORY gtwrap DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap")

# Install wrapping scripts as binaries to `CMAKE_INSTALL_PREFIX/bin` so they can
# 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})
DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})

# 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(DIRECTORY pybind11 DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap")

# Install the matlab.h file to `CMAKE_INSTALL_PREFIX/lib/gtwrap/matlab.h`.
install(FILES matlab.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gtwrap")
install(FILES matlab.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/gtwrap")
17 changes: 10 additions & 7 deletions wrap/DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the
- Class variables are read-write so they can be updated directly in Python.

- Pointer types
- To declare a pointer type (including shared pointers), simply add an asterisk (i.e. `*`) to the class name.
- E.g. `gtsam::noiseModel::Base*` to define the wrapping for the `Base` noise model shared pointer.
- To declare a simple/raw pointer, simply add an `@` to the class name, e.g.`Pose3@`.
- To declare a shared pointer (e.g. `gtsam::noiseModel::Base::shared_ptr`), use an asterisk (i.e. `*`). E.g. `gtsam::noiseModel::Base*` to define the wrapping for the `Base` noise model shared pointer.

- Comments can use either C++ or C style, with multiple lines.

Expand All @@ -76,9 +76,13 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the
- Functions specified outside of a class are **global**.
- Can be overloaded with different arguments.
- Can have multiple functions of the same name in different namespaces.
- Functions can be templated and have multiple template arguments, e.g.
```cpp
template<T, >
```

- Using classes defined in other modules
- If you are using a class `OtherClass` not wrapped in an interface file, add `class OtherClass;` as a forward declaration to avoid a dependency error.
- If you are using a class `OtherClass` not wrapped in an interface file, add `class OtherClass;` as a forward declaration to avoid a dependency error. `OtherClass` should be in the same project.

- Virtual inheritance
- Specify fully-qualified base classes, i.e. `virtual class Derived : ns::Base {` where `ns` is the namespace.
Expand Down Expand Up @@ -140,9 +144,9 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the

- Forward declarations and class definitions for **Pybind**:
- Need to specify the base class (both this forward class and base class are declared in an external Pybind header)
This is so that Pybind can generate proper inheritance.
- This is so that Pybind can generate proper inheritance.

Example when wrapping a gtsam-based project:
- Example for when wrapping a gtsam-based project:

```cpp
// forward declarations
Expand All @@ -153,8 +157,7 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the
virtual class MyFactor : gtsam::NoiseModelFactor {...};
```

- **DO NOT** re-define an overriden function already declared in the external (forward-declared) base class
- This will cause an ambiguity problem in Pybind header file.
- **DO NOT** re-define an overriden function already declared in the external (forward-declared) base class. This will cause an ambiguity problem in the Pybind header file.


### TODO
Expand Down
51 changes: 38 additions & 13 deletions wrap/cmake/GtwrapUtils.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Utilities to help with wrapping.

# Use CMake's find_package to find the version of Python installed.
macro(get_python_version)
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
# Use older version of cmake's find_python
Expand All @@ -13,19 +14,6 @@ macro(get_python_version)

find_package(PythonLibs ${PYTHON_VERSION_STRING})

set(Python_VERSION_MAJOR
${PYTHON_VERSION_MAJOR}
PARENT_SCOPE)
set(Python_VERSION_MINOR
${PYTHON_VERSION_MINOR}
PARENT_SCOPE)
set(Python_VERSION_PATCH
${PYTHON_VERSION_PATCH}
PARENT_SCOPE)
set(Python_EXECUTABLE
${PYTHON_EXECUTABLE}
PARENT_SCOPE)

else()
# Get info about the Python interpreter
# https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython
Expand All @@ -40,6 +28,40 @@ macro(get_python_version)
endif()
endmacro()

# Depending on the version of CMake, ensure all the appropriate variables are set.
macro(configure_python_variables)
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
set(Python_VERSION_MAJOR
${PYTHON_VERSION_MAJOR}
CACHE INTERNAL "")
set(Python_VERSION_MINOR
${PYTHON_VERSION_MINOR}
CACHE INTERNAL "")
set(Python_VERSION_PATCH
${PYTHON_VERSION_PATCH}
CACHE INTERNAL "")
set(Python_EXECUTABLE
${PYTHON_EXECUTABLE}
CACHE PATH "")

else()
# Set both sets of variables
set(PYTHON_VERSION_MAJOR
${Python_VERSION_MAJOR}
CACHE INTERNAL "")
set(PYTHON_VERSION_MINOR
${Python_VERSION_MINOR}
CACHE INTERNAL "")
set(PYTHON_VERSION_PATCH
${Python_VERSION_PATCH}
CACHE INTERNAL "")
set(PYTHON_EXECUTABLE
${Python_EXECUTABLE}
CACHE PATH "")

endif()
endmacro()

# Set the Python version for the wrapper and set the paths to the executable and
# include/library directories. WRAP_PYTHON_VERSION can be "Default" or a
# specific major.minor version.
Expand Down Expand Up @@ -71,4 +93,7 @@ macro(gtwrap_get_python_version WRAP_PYTHON_VERSION)
EXACT)
endif()

# (Always) Configure the variables once we find the python package
configure_python_variables()

endmacro()
10 changes: 8 additions & 2 deletions wrap/cmake/PybindWrap.cmake
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
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()

# Get the Python version
include(GtwrapUtils)
message(STATUS "Checking Python Version")
gtwrap_get_python_version(${WRAP_PYTHON_VERSION})

message(STATUS "Setting Python version for wrapper")
set(PYBIND11_PYTHON_VERSION ${WRAP_PYTHON_VERSION})

# 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
Expand Down
21 changes: 11 additions & 10 deletions wrap/cmake/gtwrapConfig.cmake
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
# This config file modifies CMAKE_MODULE_PATH so that the wrap cmake files may
# be included This file also allows the use of `find_package(gtwrap)` in CMake.

# Standard includes
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)

set(GTWRAP_DIR "${CMAKE_CURRENT_LIST_DIR}")

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")

if(WIN32 AND NOT CYGWIN)
set(GTWRAP_CMAKE_DIR "${GTWRAP_DIR}")
set(GTWRAP_SCRIPT_DIR ${GTWRAP_CMAKE_DIR}/../../../bin)
set(GTWRAP_PYTHON_PACKAGE_DIR ${GTWRAP_CMAKE_DIR}/../../../share/gtwrap)
set(GTWRAP_SCRIPT_DIR ${CMAKE_INSTALL_FULL_BINDIR})
set(GTWRAP_PYTHON_PACKAGE_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap)
else()
set(GTWRAP_CMAKE_DIR "${GTWRAP_DIR}")
set(GTWRAP_SCRIPT_DIR ${GTWRAP_CMAKE_DIR}/../../../bin)
set(GTWRAP_PYTHON_PACKAGE_DIR ${GTWRAP_CMAKE_DIR}/../../../share/gtwrap)
set(GTWRAP_SCRIPT_DIR ${CMAKE_INSTALL_FULL_BINDIR})
set(GTWRAP_PYTHON_PACKAGE_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap)
endif()

# Standard includes
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)

# Load all the CMake scripts from the standard location
include(${GTWRAP_CMAKE_DIR}/PybindWrap.cmake)
include(${GTWRAP_CMAKE_DIR}/GtwrapUtils.cmake)
Expand All @@ -28,4 +29,4 @@ 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(${GTWRAP_CMAKE_DIR}/../../gtwrap/pybind11 pybind11)
add_subdirectory(${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap/pybind11 pybind11)
Loading