diff --git a/.github/scripts/python.sh b/.github/scripts/python.sh index 08b8084a05..c851c7e36c 100644 --- a/.github/scripts/python.sh +++ b/.github/scripts/python.sh @@ -65,14 +65,13 @@ function build() # Set to 2 cores so that Actions does not error out during resource provisioning. cmake --build build -j2 - $PYTHON -m pip install --user build/python + cmake --build build --target python-install } function test() { - cd $GITHUB_WORKSPACE/python/gtsam/tests - $PYTHON -m unittest discover -v - cd $GITHUB_WORKSPACE + cmake --build build --target python-test + cmake --build build --target python-test-unstable } # select between build or test diff --git a/.github/workflows/build-python.yml b/.github/workflows/build-python.yml index 91bc4e80ac..134b85dd6c 100644 --- a/.github/workflows/build-python.yml +++ b/.github/workflows/build-python.yml @@ -18,9 +18,11 @@ jobs: CTEST_PARALLEL_LEVEL: 2 CMAKE_BUILD_TYPE: ${{ matrix.build_type }} PYTHON_VERSION: ${{ matrix.python_version }} + BOOST_VERSION: 1.72.0 + BOOST_EXE: boost_1_72_0-msvc-14.2 strategy: - fail-fast: true + fail-fast: false matrix: # Github Actions requires a single row to be added to the build matrix. # See https://help.github.com/en/articles/workflow-syntax-for-github-actions. @@ -30,6 +32,7 @@ jobs: ubuntu-20.04-gcc-9-tbb, ubuntu-20.04-clang-9, macOS-11-xcode-13.4.1, + windows-2019-msbuild, ] build_type: [Release] @@ -56,6 +59,10 @@ jobs: compiler: xcode version: "13.4.1" + - name: windows-2019-msbuild + os: windows-2019 + platform: 64 + steps: - name: Checkout uses: actions/checkout@v3 @@ -97,29 +104,75 @@ jobs: echo "CC=clang" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV + - name: Setup msbuild (Windows) + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x${{matrix.platform}} + toolset: "29" + + - name: cl version + if: runner.os == 'Windows' + shell: cmd + run: | + cl + + - name: Setup python (Windows) + uses: actions/setup-python@v4 + if: runner.os == 'Windows' + with: + python-version: ${{ matrix.python_version }} + + - name: Install ninja (Windows) + if: runner.os == 'Windows' + shell: bash + run: | + choco install ninja + ninja --version + where ninja + + - name: Install Boost (Windows) + if: runner.os == 'Windows' + shell: powershell + run: | + # Snippet from: https://github.com/actions/virtual-environments/issues/2667 + $BOOST_PATH = "C:\hostedtoolcache\windows\Boost\$env:BOOST_VERSION\x86_64" + + # Use the prebuilt binary for Windows + $Url = "https://sourceforge.net/projects/boost/files/boost-binaries/$env:BOOST_VERSION/$env:BOOST_EXE-${{matrix.platform}}.exe" + (New-Object System.Net.WebClient).DownloadFile($Url, "$env:TEMP\boost.exe") + Start-Process -Wait -FilePath "$env:TEMP\boost.exe" "/SILENT","/SP-","/SUPPRESSMSGBOXES","/DIR=$BOOST_PATH" + + # Set the BOOST_ROOT variable + echo "BOOST_ROOT=$BOOST_PATH" >> $env:GITHUB_ENV + - name: Set GTSAM_WITH_TBB Flag if: matrix.flag == 'tbb' run: | echo "GTSAM_WITH_TBB=ON" >> $GITHUB_ENV echo "GTSAM Uses TBB" - - name: Set Swap Space + - name: Set Swap Space (Linux) if: runner.os == 'Linux' uses: pierotofy/set-swap-space@master with: swap-size-gb: 6 - - name: Install System Dependencies + - name: Install System Dependencies (Linux, macOS) + if: runner.os != 'Windows' run: | bash .github/scripts/python.sh -d - name: Install Python Dependencies + shell: bash run: python$PYTHON_VERSION -m pip install -r python/dev_requirements.txt - name: Build + shell: bash run: | bash .github/scripts/python.sh -b - name: Test + shell: bash run: | bash .github/scripts/python.sh -t diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index f0568394fa..f259d9ae47 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -98,6 +98,7 @@ jobs: uses: ilammy/msvc-dev-cmd@v1 with: arch: x${{ matrix.platform }} + toolset: "29" - name: Configuration shell: bash diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 0000000000..a687b19a74 --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,101 @@ +name: Linux +on: + pull_request: + branches: + - "*" # Pull request for all branches + schedule: + - cron: '10 12 * * 0' + +# Every time you make a push to your PR, it cancel immediately the previous checks, +# and start a new one. The other runner will be available more quickly to your PR. +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build: + name: vcpkg-ubuntu-${{ matrix.type }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - type: x64 + BUILD_DIR: gtsam/3rdparty/vcpkg/cache + VCPKG_ROOT: gtsam/3rdparty/vcpkg/cache/vcpkg + VCPKG_LINK: https://github.com/microsoft/vcpkg/ + VCPKG_CONFIGS: gtsam/3rdparty/vcpkg + BINARY_CACHE: gtsam/3rdparty/cache/linux + env: + BUILD_DIR: ${{ matrix.BUILD_DIR }} + VCPKG_ROOT: ${{ matrix.VCPKG_ROOT }} + VCPKG_LINK: ${{ matrix.VCPKG_LINK }} + VCPKG_CONFIGS: ${{ matrix.VCPKG_CONFIGS }} + BINARY_CACHE: ${{ matrix.BINARY_CACHE }} + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Cache dependencies + uses: actions/cache/restore@v3 + with: + path: | + ${{ matrix.BINARY_CACHE }} + key: linux-${{ hashFiles('.github/workflows/linux.yml') }} + restore-keys: linux-${{ hashFiles('.github/workflows/linux.yml') }} + + - name: Install ninja + if: success() + run: | + sudo apt install -y ninja-build + ninja --version + whereis ninja + + - name: Init vcpkg + if: success() + run: | + mkdir -p $BUILD_DIR + git -C $BUILD_DIR clone $VCPKG_LINK + + - name: Vcpkg build & cmake config + if: success() + run: | + export VCPKG_BINARY_SOURCES="clear;files,$PWD/$BINARY_CACHE,readwrite;" + mkdir -p $BINARY_CACHE + export CMAKE_GENERATOR=Ninja + cmake . -B build \ + -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_MANIFEST_DIR=$VCPKG_CONFIGS/manifest \ + -DVCPKG_INSTALLED_DIR=$VCPKG_ROOT/installed \ + -DVCPKG_OVERLAY_TRIPLETS=$VCPKG_CONFIGS/triplets \ + -DVCPKG_TARGET_TRIPLET=x64-linux-release \ + -DVCPKG_INSTALL_OPTIONS=--clean-after-build \ + -DGTSAM_BUILD_EXAMPLES_ALWAYS=ON \ + -DGTSAM_ROT3_EXPMAP=ON \ + -DGTSAM_POSE3_EXPMAP=ON \ + -DGTSAM_BUILD_PYTHON=ON \ + -DGTSAM_BUILD_TESTS=ON \ + -DGTSAM_BUILD_UNSTABLE=ON \ + -DGTSAM_USE_SYSTEM_EIGEN=ON \ + -DGTSAM_USE_SYSTEM_METIS=ON \ + -DGTSAM_SUPPORT_NESTED_DISSECTION=ON + + - name: Save cache dependencies + id: cache-save + uses: actions/cache/save@v3 + with: + path: | + ${{ matrix.BINARY_CACHE }} + key: linux-${{ hashFiles('.github/workflows/linux.yml') }}-${{ hashFiles('gtsam/3rdparty/vcpkg/cache/vcpkg/installed/vcpkg/updates/*') }} + + + - name: Cmake build + if: success() + run: | + cmake --build build --config Release -j 2 + + - name: Run tests + if: success() + run: | + # metis test are failing. remove this comment when fix it. + # cmake --build build --target check -j 2 diff --git a/.github/workflows/osx.yml b/.github/workflows/osx.yml new file mode 100644 index 0000000000..b84eb4fe7c --- /dev/null +++ b/.github/workflows/osx.yml @@ -0,0 +1,109 @@ +name: OSX +on: + pull_request: + branches: + - "*" # Pull request for all branches + schedule: + - cron: '10 12 * * 0' + +# Every time you make a push to your PR, it cancel immediately the previous checks, +# and start a new one. The other runner will be available more quickly to your PR. +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build: + name: vcpkg-macos-${{ matrix.type }} + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + include: + - type: x64 + BUILD_DIR: gtsam/3rdparty/vcpkg/cache + VCPKG_ROOT: gtsam/3rdparty/vcpkg/cache/vcpkg + VCPKG_LINK: https://github.com/microsoft/vcpkg/ + VCPKG_CONFIGS: gtsam/3rdparty/vcpkg + BINARY_CACHE: gtsam/3rdparty/cache/osx + env: + BUILD_DIR: ${{ matrix.BUILD_DIR }} + VCPKG_ROOT: ${{ matrix.VCPKG_ROOT }} + VCPKG_LINK: ${{ matrix.VCPKG_LINK }} + VCPKG_CONFIGS: ${{ matrix.VCPKG_CONFIGS }} + BINARY_CACHE: ${{ matrix.BINARY_CACHE }} + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Cache dependencies + uses: actions/cache/restore@v3 + with: + path: | + ${{ matrix.BINARY_CACHE }} + key: osx-${{ hashFiles('.github/workflows/osx.yml') }} + restore-keys: osx-${{ hashFiles('.github/workflows/osx.yml') }} + + - name: Install Dependencies + run: | + sudo xcode-select -switch /Applications/Xcode.app + + - name: Install python packages + if: success() + run: | + pip3 install pyparsing + + - name: Install ninja + if: success() + run: | + brew install ninja + ninja --version + whereis ninja + + - name: Init vcpkg + if: success() + run: | + mkdir -p $BUILD_DIR + git -C $BUILD_DIR clone $VCPKG_LINK + + - name: Vcpkg build & cmake config + if: success() + run: | + export VCPKG_BINARY_SOURCES="clear;files,$PWD/$BINARY_CACHE,readwrite;" + mkdir -p $BINARY_CACHE + export CMAKE_GENERATOR=Ninja + cmake . -B build \ + -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_MANIFEST_DIR=$VCPKG_CONFIGS/manifest \ + -DVCPKG_INSTALLED_DIR=$VCPKG_ROOT/installed \ + -DVCPKG_OVERLAY_TRIPLETS=$VCPKG_CONFIGS/triplets \ + -DVCPKG_TARGET_TRIPLET=x64-osx-release \ + -DVCPKG_INSTALL_OPTIONS=--clean-after-build \ + -DGTSAM_BUILD_EXAMPLES_ALWAYS=ON \ + -DGTSAM_ROT3_EXPMAP=ON \ + -DGTSAM_POSE3_EXPMAP=ON \ + -DGTSAM_BUILD_PYTHON=ON \ + -DGTSAM_BUILD_TESTS=ON \ + -DGTSAM_BUILD_UNSTABLE=ON \ + -DGTSAM_USE_SYSTEM_EIGEN=ON \ + -DGTSAM_USE_SYSTEM_METIS=ON \ + -DGTSAM_SUPPORT_NESTED_DISSECTION=ON + + - name: Save cache dependencies + id: cache-save + uses: actions/cache/save@v3 + with: + path: | + ${{ matrix.BINARY_CACHE }} + key: osx-${{ hashFiles('.github/workflows/osx.yml') }}-${{ hashFiles('gtsam/3rdparty/vcpkg/cache/vcpkg/installed/vcpkg/updates/*') }} + + - name: Cmake build + if: success() + run: | + cmake --build build --config Release -j 2 + + - name: Run tests + if: success() + run: | + # metis test are failing. remove this comment when fix it. + # cmake --build build --target check -j 2 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000000..0e5b3c656d --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,135 @@ +name: Windows +on: + pull_request: + branches: + - "*" # Pull request for all branches + schedule: + - cron: '10 12 * * 0' + +# Every time you make a push to your PR, it cancel immediately the previous checks, +# and start a new one. The other runner will be available more quickly to your PR. +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build: + name: vcpkg-windows-${{ matrix.type }} + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + include: + - type: x64 + BUILD_DIR: gtsam/3rdparty/vcpkg/cache + VCPKG_ROOT: gtsam/3rdparty/vcpkg/cache/vcpkg + VCPKG_LINK: https://github.com/microsoft/vcpkg/ + VCPKG_CONFIGS: gtsam/3rdparty/vcpkg + BINARY_CACHE: gtsam/3rdparty/vcpkg/cache/windows + env: + BUILD_DIR: ${{ matrix.BUILD_DIR }} + VCPKG_ROOT: ${{ matrix.VCPKG_ROOT }} + VCPKG_LINK: ${{ matrix.VCPKG_LINK }} + VCPKG_CONFIGS: ${{ matrix.VCPKG_CONFIGS }} + BINARY_CACHE: ${{ matrix.BINARY_CACHE }} + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Restore cache dependencies + uses: actions/cache/restore@v3 + with: + path: | + ${{ matrix.BINARY_CACHE }} + key: windows-${{ hashFiles('.github/workflows/windows.yml') }} + restore-keys: windows-${{ hashFiles('.github/workflows/windows.yml') }} + + - name: Setup msbuild + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + toolset: "29" + + - name: cl version + shell: cmd + run: | + cl + + - uses: actions/setup-python@v4 + with: + python-version: '3' + + - name: Install python packages + if: success() + shell: cmd + run: | + python --version + python -m pip --version + python -m pip install -r python/dev_requirements.txt + + - name: Install ninja + if: success() + shell: cmd + run: | + choco install ninja + ninja --version + where ninja + + - name: Init vcpkg + if: success() + shell: bash + run: | + mkdir -p $BUILD_DIR + git -C $BUILD_DIR clone $VCPKG_LINK + + - name: Vcpkg build & cmake config + if: success() + shell: bash + run: | + export VCPKG_ROOT=${{ matrix.VCPKG_ROOT }} + export VCPKG_BINARY_SOURCES="clear;files,${GITHUB_WORKSPACE}/${BINARY_CACHE},readwrite;" + mkdir -p $BINARY_CACHE + export CMAKE_GENERATOR=Ninja + export CL=-openmp:experimental + cmake . -B build \ + -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_MANIFEST_DIR=$VCPKG_CONFIGS/manifest \ + -DVCPKG_INSTALLED_DIR=$VCPKG_ROOT/installed \ + -DVCPKG_OVERLAY_TRIPLETS=$VCPKG_CONFIGS/triplets \ + -DVCPKG_TARGET_TRIPLET=x64-windows-release \ + -DVCPKG_INSTALL_OPTIONS=--clean-after-build \ + -DCMAKE_BUILD_TYPE=Release \ + -DGTSAM_BUILD_EXAMPLES_ALWAYS=ON \ + -DGTSAM_ROT3_EXPMAP=ON \ + -DGTSAM_POSE3_EXPMAP=ON \ + -DGTSAM_BUILD_PYTHON=ON \ + -DGTSAM_BUILD_TESTS=ON \ + -DGTSAM_BUILD_UNSTABLE=OFF \ + -DGTSAM_USE_SYSTEM_EIGEN=ON \ + -DGTSAM_USE_SYSTEM_METIS=ON \ + -DGTSAM_SUPPORT_NESTED_DISSECTION=ON + + - name: Save cache dependencies + id: cache-save + uses: actions/cache/save@v3 + with: + path: | + ${{ matrix.BINARY_CACHE }} + key: windows-${{ hashFiles('.github/workflows/windows.yml') }}-${{ hashFiles('gtsam\3rdparty\vcpkg\cache\vcpkg\installed\vcpkg\updates\*') }} + + - name: Cmake build + shell: bash + run: | + cmake --build build --config Release -j 2 + + - name: Run Python tests + shell: bash + run: | + cmake --build build --target python-install + cmake --build build --target python-test + + - name: Run tests + shell: bash + run: | + # metis test are failing. remove this comment when fix it. + # cmake --build build --target check -j 1 diff --git a/.gitignore b/.gitignore index e3f7613fee..2db05da938 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ CMakeLists.txt.user* xcode/ /Dockerfile /python/gtsam/notebooks/.ipynb_checkpoints/ellipses-checkpoint.ipynb +gtsam/3rdparty/vcpkg/cache diff --git a/CMakeLists.txt b/CMakeLists.txt index 66b1804aff..05df8a8cdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,10 @@ cmake_minimum_required(VERSION 3.0) +# This is required to avoid an error in modern pybind11 cmake scripts: +if(POLICY CMP0057) + cmake_policy(SET CMP0057 NEW) +endif() + # Set the version number for the library set (GTSAM_VERSION_MAJOR 4) set (GTSAM_VERSION_MINOR 3) diff --git a/cmake/HandleMetis.cmake b/cmake/HandleMetis.cmake index 5cbec4ff58..10dbb53de5 100644 --- a/cmake/HandleMetis.cmake +++ b/cmake/HandleMetis.cmake @@ -13,10 +13,9 @@ option(GTSAM_USE_SYSTEM_METIS "Find and use system-installed libmetis. If 'off', if(GTSAM_USE_SYSTEM_METIS) # Debian package: libmetis-dev - find_path(METIS_INCLUDE_DIR metis.h REQUIRED) - find_library(METIS_LIBRARY metis REQUIRED) + find_package(metis CONFIG REQUIRED) - if(METIS_INCLUDE_DIR AND METIS_LIBRARY) + if(metis_FOUND) mark_as_advanced(METIS_INCLUDE_DIR) mark_as_advanced(METIS_LIBRARY) @@ -27,7 +26,7 @@ if(GTSAM_USE_SYSTEM_METIS) $ $ ) - target_link_libraries(metis-gtsam-if INTERFACE ${METIS_LIBRARY}) + target_link_libraries(metis-gtsam-if INTERFACE ${METIS_LIBRARY} metis) endif() else() # Bundled version: diff --git a/gtsam/3rdparty/GeographicLib/cmake/FindGeographicLib.cmake b/gtsam/3rdparty/GeographicLib/cmake/FindGeographicLib.cmake index 58932cc70f..0d27617ee3 100644 --- a/gtsam/3rdparty/GeographicLib/cmake/FindGeographicLib.cmake +++ b/gtsam/3rdparty/GeographicLib/cmake/FindGeographicLib.cmake @@ -6,8 +6,11 @@ # GeographicLib_LIBRARIES = /usr/local/lib/libGeographic.so # GeographicLib_LIBRARY_DIRS = /usr/local/lib -find_library (GeographicLib_LIBRARIES Geographic - PATHS "${CMAKE_INSTALL_PREFIX}/../GeographicLib/lib") +find_package(GeographicLib CONFIG) +if(NOT GeographicLib_FOUND) + find_library (GeographicLib_LIBRARIES Geographic + PATHS "${CMAKE_INSTALL_PREFIX}/../GeographicLib/lib") +endif() if (GeographicLib_LIBRARIES) get_filename_component (GeographicLib_LIBRARY_DIRS @@ -32,9 +35,9 @@ if (GeographicLib_LIBRARIES) unset (_ROOT_DIR) endif () -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args (GeographicLib DEFAULT_MSG - GeographicLib_LIBRARY_DIRS GeographicLib_LIBRARIES - GeographicLib_INCLUDE_DIRS) +# include (FindPackageHandleStandardArgs) +# find_package_handle_standard_args (GeographicLib DEFAULT_MSG +# GeographicLib_LIBRARY_DIRS GeographicLib_LIBRARIES +# GeographicLib_INCLUDE_DIRS) mark_as_advanced (GeographicLib_LIBRARY_DIRS GeographicLib_LIBRARIES GeographicLib_INCLUDE_DIRS) diff --git a/gtsam/3rdparty/cephes/CMakeLists.txt b/gtsam/3rdparty/cephes/CMakeLists.txt index e840e9e493..6fcb3a316e 100644 --- a/gtsam/3rdparty/cephes/CMakeLists.txt +++ b/gtsam/3rdparty/cephes/CMakeLists.txt @@ -8,6 +8,7 @@ project( set(CEPHES_HEADER_FILES cephes.h + dllexport.h cephes/cephes_names.h cephes/dd_idefs.h cephes/dd_real.h diff --git a/gtsam/3rdparty/cephes/cephes.h b/gtsam/3rdparty/cephes/cephes.h index 629733eef0..cb807c629d 100644 --- a/gtsam/3rdparty/cephes/cephes.h +++ b/gtsam/3rdparty/cephes/cephes.h @@ -2,6 +2,7 @@ #define CEPHES_H #include "cephes/cephes_names.h" +#include "dllexport.h" #ifdef __cplusplus extern "C" { @@ -64,7 +65,7 @@ extern double igamc(double a, double x); extern double igam(double a, double x); extern double igam_fac(double a, double x); extern double igamci(double a, double q); -extern double igami(double a, double p); +GTSAM_EXTERN_EXPORT double igami(double a, double p); extern double incbet(double aa, double bb, double xx); extern double incbi(double aa, double bb, double yy0); diff --git a/gtsam/3rdparty/cephes/dllexport.h b/gtsam/3rdparty/cephes/dllexport.h new file mode 100644 index 0000000000..61d32738b0 --- /dev/null +++ b/gtsam/3rdparty/cephes/dllexport.h @@ -0,0 +1,60 @@ +/* ---------------------------------------------------------------------------- + + * 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 dllexport.h + * @brief Symbols for exporting classes and methods from DLLs + * @author Richard Roberts + * @date Mar 9, 2013 + */ + +// Macros for exporting DLL symbols on Windows +// Usage example: +// In header file: +// class GTSAM_EXPORT MyClass { ... }; +// +// Results in the following declarations: +// When included while compiling the GTSAM library itself: +// class __declspec(dllexport) MyClass { ... }; +// When included while compiling other code against GTSAM: +// class __declspec(dllimport) MyClass { ... }; + +#pragma once + +// Whether GTSAM is compiled as static or DLL in windows. +// This will be used to decide whether include __declspec(dllimport) or not in headers +#define GTSAM_SHARED_LIB + +#ifdef _WIN32 +# ifndef GTSAM_SHARED_LIB +# define GTSAM_EXPORT +# define GTSAM_EXTERN_EXPORT extern +# else +# ifdef GTSAM_EXPORTS +# define GTSAM_EXPORT __declspec(dllexport) +# define GTSAM_EXTERN_EXPORT __declspec(dllexport) extern +# else +# define GTSAM_EXPORT __declspec(dllimport) +# define GTSAM_EXTERN_EXPORT __declspec(dllimport) +# endif +# endif +#else +#ifdef __APPLE__ +# define GTSAM_EXPORT __attribute__((visibility("default"))) +# define GTSAM_EXTERN_EXPORT extern +#else +# define GTSAM_EXPORT +# define GTSAM_EXTERN_EXPORT extern +#endif +#endif + +#undef GTSAM_SHARED_LIB + diff --git a/gtsam/3rdparty/vcpkg/manifest/vcpkg.json b/gtsam/3rdparty/vcpkg/manifest/vcpkg.json new file mode 100644 index 0000000000..a2035ea316 --- /dev/null +++ b/gtsam/3rdparty/vcpkg/manifest/vcpkg.json @@ -0,0 +1,30 @@ +{ + "name": "gtsam", + "description": "Georgia Tech Smoothing and Mapping Library.", + "homepage": "gtsam.org", + "dependencies": [ + "boost-assign", + "boost-bimap", + "boost-chrono", + "boost-date-time", + "boost-filesystem", + "boost-format", + "boost-graph", + "boost-math", + "boost-program-options", + "boost-regex", + "boost-serialization", + "boost-system", + "boost-thread", + "boost-timer", + "eigen3", + "metis", + "tbb", + "pybind11", + "geographiclib", + { + "name":"intel-mkl", + "platform": "!windows" + } + ] +} diff --git a/gtsam/3rdparty/vcpkg/triplets/.gitkeep b/gtsam/3rdparty/vcpkg/triplets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gtsam/base/utilities.h b/gtsam/base/utilities.h index 03e9636da4..a67c5d1b6c 100644 --- a/gtsam/base/utilities.h +++ b/gtsam/base/utilities.h @@ -4,6 +4,8 @@ #include #include +#include + namespace gtsam { /** * For Python __str__(). @@ -11,7 +13,7 @@ namespace gtsam { * of an object when it prints to cout. * https://stackoverflow.com/questions/5419356/redirect-stdout-stderr-to-a-string */ -struct RedirectCout { +struct GTSAM_EXPORT RedirectCout { /// constructor -- redirect stdout buffer to a stringstream buffer RedirectCout() : ssBuffer_(), coutBuffer_(std::cout.rdbuf(ssBuffer_.rdbuf())) {} diff --git a/gtsam/discrete/DiscreteValues.h b/gtsam/discrete/DiscreteValues.h index 9ec08302bd..9fdff014cc 100644 --- a/gtsam/discrete/DiscreteValues.h +++ b/gtsam/discrete/DiscreteValues.h @@ -126,12 +126,12 @@ inline std::vector cartesianProduct(const DiscreteKeys& keys) { } /// Free version of markdown. -std::string markdown(const DiscreteValues& values, +std::string GTSAM_EXPORT markdown(const DiscreteValues& values, const KeyFormatter& keyFormatter = DefaultKeyFormatter, const DiscreteValues::Names& names = {}); /// Free version of html. -std::string html(const DiscreteValues& values, +std::string GTSAM_EXPORT html(const DiscreteValues& values, const KeyFormatter& keyFormatter = DefaultKeyFormatter, const DiscreteValues::Names& names = {}); diff --git a/gtsam/geometry/Rot3.h b/gtsam/geometry/Rot3.h index 2b9c5a45a8..7e05ee4daf 100644 --- a/gtsam/geometry/Rot3.h +++ b/gtsam/geometry/Rot3.h @@ -396,7 +396,7 @@ class GTSAM_EXPORT Rot3 : public LieGroup { Matrix3 AdjointMap() const { return matrix(); } // Chart at origin, depends on compile-time flag ROT3_DEFAULT_COORDINATES_MODE - struct ChartAtOrigin { + struct GTSAM_EXPORT ChartAtOrigin { static Rot3 Retract(const Vector3& v, ChartJacobian H = {}); static Vector3 Local(const Rot3& r, ChartJacobian H = {}); }; diff --git a/gtsam/nonlinear/CustomFactor.h b/gtsam/nonlinear/CustomFactor.h index ac29420320..c4015db373 100644 --- a/gtsam/nonlinear/CustomFactor.h +++ b/gtsam/nonlinear/CustomFactor.h @@ -42,7 +42,7 @@ using CustomErrorFunction = std::function + struct handle_matrix, true> { + inline Eigen::Matrix operator()(Key j, const Value* const pointer) { + auto ptr = dynamic_cast>*>(pointer); + if (ptr) { + // value returns a const Matrix&, and the return makes a copy !!!!! + return ptr->value(); + } else { + // If a fixed matrix was stored, we end up here as well. + throw ValuesIncorrectType(j, typeid(*pointer), typeid(Eigen::Matrix)); + } + } + }; + + // Handle fixed matrices + template + struct handle_matrix, false> { + inline Eigen::Matrix operator()(Key j, const Value* const pointer) { + auto ptr = dynamic_cast>*>(pointer); + if (ptr) { + // value returns a const MatrixMN&, and the return makes a copy !!!!! + return ptr->value(); + } else { + Matrix A; + // Check if a dynamic matrix was stored + auto ptr = dynamic_cast*>(pointer); + if (ptr) { + A = ptr->value(); + } else { + // Or a dynamic vector + A = handle_matrix()(j, pointer); // will throw if not.... + } + // Yes: check size, and throw if not a match + if (A.rows() != M || A.cols() != N) + throw NoMatchFoundForFixed(M, N, A.rows(), A.cols()); + else + return A; // copy but not malloc + } + } + }; + + // Handle matrices + template + struct handle> { + Eigen::Matrix operator()(Key j, const Value* const pointer) { + return handle_matrix, + (M == Eigen::Dynamic || N == Eigen::Dynamic)>()(j, pointer); + } + }; +#endif // #ifdef _WIN32 + } // internal /* ************************************************************************* */ diff --git a/gtsam/sfm/DsfTrackGenerator.h b/gtsam/sfm/DsfTrackGenerator.h index 27cfdfa2ba..35102401e9 100644 --- a/gtsam/sfm/DsfTrackGenerator.h +++ b/gtsam/sfm/DsfTrackGenerator.h @@ -69,7 +69,7 @@ using MatchIndicesMap = std::map; * correspondence indices, from each image. * @param Length-N list of keypoints, for N images/cameras. */ -std::vector tracksFromPairwiseMatches( +std::vector GTSAM_EXPORT tracksFromPairwiseMatches( const MatchIndicesMap& matches, const KeypointsVector& keypoints, bool verbose = false); diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index f874c2f217..a1121f01d5 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -23,14 +23,8 @@ include(PybindWrap) # Load the pybind11 code - -# This is required to avoid an error in modern pybind11 cmake scripts: -if(POLICY CMP0057) - cmake_policy(SET CMP0057 NEW) -endif() - # Prefer system pybind11 first, if not found, rely on bundled version: -find_package(pybind11 CONFIG QUIET) +find_package(pybind11 CONFIG) if (NOT pybind11_FOUND) add_subdirectory(${PROJECT_SOURCE_DIR}/wrap/pybind11 pybind11) endif() @@ -94,6 +88,14 @@ set(interface_headers set(GTSAM_PYTHON_TARGET gtsam_py) set(GTSAM_PYTHON_UNSTABLE_TARGET gtsam_unstable_py) +set(GTSAM_OUTPUT_NAME "gtsam") +set(GTSAM_UNSTABLE_OUTPUT_NAME "gtsam_unstable") + +if(MSVC) + set(GTSAM_OUTPUT_NAME "gtsam_py") + set(GTSAM_UNSTABLE_OUTPUT_NAME "gtsam_unstable_py") +endif() + pybind_wrap(${GTSAM_PYTHON_TARGET} # target "${interface_headers}" # interface_headers "gtsam.cpp" # generated_cpp @@ -109,12 +111,42 @@ pybind_wrap(${GTSAM_PYTHON_TARGET} # target set_target_properties(${GTSAM_PYTHON_TARGET} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" INSTALL_RPATH_USE_LINK_PATH TRUE - OUTPUT_NAME "gtsam" + OUTPUT_NAME "${GTSAM_OUTPUT_NAME}" LIBRARY_OUTPUT_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam" DEBUG_POSTFIX "" # Otherwise you will have a wrong name RELWITHDEBINFO_POSTFIX "" # Otherwise you will have a wrong name ) +if(WIN32) + set_target_properties(${GTSAM_PYTHON_TARGET} PROPERTIES + SUFFIX ".pyd" + ) + ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/${GTSAM_OUTPUT_NAME}.pyd" + "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/gtsam.pyd" + ) + ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$;$" + "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/" + COMMAND_EXPAND_LISTS + VERBATIM + ) + + if(DEFINED VCPKG_INSTALLED_DIR) + list(GET CMAKE_FIND_ROOT_PATH 0 VCPKG_BINARIES) + file(GLOB VCPKG_BINARIES "${VCPKG_BINARIES}/bin/*.dll") + ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${VCPKG_BINARIES}" + "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/" + COMMAND_EXPAND_LISTS + VERBATIM + ) + endif() +endif() + # Set the path for the GTSAM python module set(GTSAM_MODULE_PATH ${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam) @@ -188,7 +220,7 @@ if(GTSAM_UNSTABLE_BUILD_PYTHON) set_target_properties(${GTSAM_PYTHON_UNSTABLE_TARGET} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" INSTALL_RPATH_USE_LINK_PATH TRUE - OUTPUT_NAME "gtsam_unstable" + OUTPUT_NAME "${GTSAM_UNSTABLE_OUTPUT_NAME}" LIBRARY_OUTPUT_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable" DEBUG_POSTFIX "" # Otherwise you will have a wrong name RELWITHDEBINFO_POSTFIX "" # Otherwise you will have a wrong name @@ -208,13 +240,50 @@ if(GTSAM_UNSTABLE_BUILD_PYTHON) # Add gtsam_unstable to the install target list(APPEND GTSAM_PYTHON_DEPENDENCIES ${GTSAM_PYTHON_UNSTABLE_TARGET}) - + if(WIN32) + set_target_properties(${GTSAM_PYTHON_UNSTABLE_TARGET} PROPERTIES + SUFFIX ".pyd" + ) + ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_UNSTABLE_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/${GTSAM_UNSTABLE_OUTPUT_NAME}.pyd" + "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/gtsam_unstable.pyd" + ) + ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_UNSTABLE_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$;$" + "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/" + COMMAND_EXPAND_LISTS + VERBATIM + ) + if(DEFINED VCPKG_INSTALLED_DIR) + list(GET CMAKE_FIND_ROOT_PATH 0 VCPKG_BINARIES) + file(GLOB VCPKG_BINARIES "${VCPKG_BINARIES}/bin/*.dll") + ADD_CUSTOM_COMMAND(TARGET ${GTSAM_PYTHON_UNSTABLE_TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${VCPKG_BINARIES}" + "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/" + COMMAND_EXPAND_LISTS + VERBATIM + ) + endif() + endif() + # Custom make command to run all GTSAM_UNSTABLE Python tests + add_custom_target( + python-test-unstable + COMMAND + ${CMAKE_COMMAND} -E env # add package to python path so no need to install + "PYTHONPATH=${GTSAM_PYTHON_BUILD_DIRECTORY}/$ENV{PYTHONPATH}" + ${PYTHON_EXECUTABLE} -m unittest discover -v -s . + DEPENDS ${GTSAM_PYTHON_DEPENDENCIES} ${GTSAM_PYTHON_TEST_FILES} + WORKING_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam_unstable/tests" + ) endif() # Add custom target so we can install with `make python-install` set(GTSAM_PYTHON_INSTALL_TARGET python-install) add_custom_target(${GTSAM_PYTHON_INSTALL_TARGET} - COMMAND ${PYTHON_EXECUTABLE} -m pip install . + COMMAND ${PYTHON_EXECUTABLE} -m pip install --user . DEPENDS ${GTSAM_PYTHON_DEPENDENCIES} WORKING_DIRECTORY ${GTSAM_PYTHON_BUILD_DIRECTORY}) diff --git a/python/setup.py.in b/python/setup.py.in index e15e390754..824a6656ed 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -11,7 +11,8 @@ print("PACKAGES: ", packages) package_data = { '': [ "./*.so", - "./*.dll" + "./*.dll", + "./*.pyd", ] }