commit
						e24def4abb
					
				|  | @ -0,0 +1,175 @@ | |||
| # This workflow builds the Python wheels using cibuildwheel and uploads them to TestPyPI. | ||||
| # It can be triggered on push to the develop branch or manually via Github Actions. | ||||
| 
 | ||||
| name: Build Wheels (cibuildwheel) | ||||
| 
 | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - develop | ||||
|   workflow_dispatch: | ||||
| 
 | ||||
| jobs: | ||||
|   # Get the system time and store it in an output. This is used to tag the wheels. | ||||
|   # This needs to be done in a separate job so that each matrix job in build_wheels can | ||||
|   # access the same timestamp. | ||||
|   get_system_time: | ||||
|     name: Get System Time | ||||
|     runs-on: ubuntu-latest | ||||
|     outputs: | ||||
|       timestamp: ${{ steps.get_time.outputs.timestamp }} | ||||
|     steps: | ||||
|       - name: Get system time | ||||
|         id: get_time | ||||
|         run: echo "timestamp=$(date +'%Y%m%d%H%M')" >> "$GITHUB_OUTPUT" | ||||
| 
 | ||||
|   build_wheels: | ||||
|     name: Build Wheels | ||||
|     needs: get_system_time | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           # Linux x86_64 | ||||
|           - os: ubuntu-latest | ||||
|             python_version: "3.10" | ||||
|             cibw_python_version: 310 | ||||
|             platform_id: manylinux_x86_64 | ||||
|             manylinux_image: manylinux2014 | ||||
|           - os: ubuntu-latest | ||||
|             python_version: "3.11" | ||||
|             cibw_python_version: 311 | ||||
|             platform_id: manylinux_x86_64 | ||||
|             manylinux_image: manylinux2014 | ||||
|           - os: ubuntu-latest | ||||
|             python_version: "3.12" | ||||
|             cibw_python_version: 312 | ||||
|             platform_id: manylinux_x86_64 | ||||
|             manylinux_image: manylinux2014 | ||||
|           - os: ubuntu-latest | ||||
|             python_version: "3.13" | ||||
|             cibw_python_version: 313 | ||||
|             platform_id: manylinux_x86_64 | ||||
|             manylinux_image: manylinux2014 | ||||
| 
 | ||||
|           # Linux aarch64 | ||||
|           - os: ubuntu-24.04-arm | ||||
|             python_version: "3.10" | ||||
|             cibw_python_version: 310 | ||||
|             platform_id: manylinux_aarch64 | ||||
|             manylinux_image: manylinux2014 | ||||
|           - os: ubuntu-24.04-arm | ||||
|             python_version: "3.11" | ||||
|             cibw_python_version: 311 | ||||
|             platform_id: manylinux_aarch64 | ||||
|             manylinux_image: manylinux2014 | ||||
|           - os: ubuntu-24.04-arm | ||||
|             python_version: "3.12" | ||||
|             cibw_python_version: 312 | ||||
|             platform_id: manylinux_aarch64 | ||||
|             manylinux_image: manylinux2014 | ||||
|           - os: ubuntu-24.04-arm | ||||
|             python_version: "3.13" | ||||
|             cibw_python_version: 313 | ||||
|             platform_id: manylinux_aarch64 | ||||
|             manylinux_image: manylinux2014 | ||||
| 
 | ||||
|           # MacOS x86_64 | ||||
|           # - os: macos-13 | ||||
|           #   python_version: "3.10" | ||||
|           #   cibw_python_version: 310 | ||||
|           #   platform_id: macosx_x86_64 | ||||
|           # - os: macos-13 | ||||
|           #   python_version: "3.11" | ||||
|           #   cibw_python_version: 311 | ||||
|           #   platform_id: macosx_x86_64 | ||||
|           # - os: macos-13 | ||||
|           #   python_version: "3.12" | ||||
|           #   cibw_python_version: 312 | ||||
|           #   platform_id: macosx_x86_64 | ||||
|           # - os: macos-13 | ||||
|           #   python_version: "3.13" | ||||
|           #   cibw_python_version: 313 | ||||
|           #   platform_id: macosx_x86_64 | ||||
| 
 | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
| 
 | ||||
|       - name: Set up Python ${{ matrix.python_version }} | ||||
|         uses: actions/setup-python@v5 | ||||
|         with: | ||||
|           python-version: ${{ matrix.python_version }} | ||||
| 
 | ||||
|       # Set the DEVELOP flag and the TIMESTAMP environment variables. This is used in the | ||||
|       # top-level CMakeLists.txt to generate the GTSAM_VERSION_STRING. | ||||
|       - name: Set Develop Flag | ||||
|         run: | | ||||
|           echo "DEVELOP=1" >> $GITHUB_ENV | ||||
|           echo "TIMESTAMP=${{ needs.get_system_time.outputs.timestamp }}" >> $GITHUB_ENV | ||||
| 
 | ||||
|       - name: Install Dependencies | ||||
|         run: | | ||||
|           python3 -m pip install -r python/dev_requirements.txt | ||||
|           if [ "$RUNNER_OS" == "Linux" ]; then | ||||
|             sudo apt-get install -y wget libicu-dev python3-pip python3-setuptools libboost-all-dev ninja-build | ||||
|           elif [ "$RUNNER_OS" == "macOS" ]; then | ||||
|             brew install wget icu4c boost ninja python-setuptools | ||||
|           else | ||||
|             echo "$RUNNER_OS not supported" | ||||
|             exit 1 | ||||
|           fi | ||||
| 
 | ||||
|       # We first build the Python wrapper module on the host machine. This is done because cibuildwheel | ||||
|       # expects a setup.py file to be present in the project directory. | ||||
|       # | ||||
|       # The Python wrapper module is then rebuilt within the cibuildwheel container before building | ||||
|       # the wheels to ensure platform compatibility. | ||||
|       - name: Run CMake | ||||
|         run: | | ||||
|           cmake . -B build -DGTSAM_BUILD_PYTHON=1 -DGTSAM_PYTHON_VERSION=${{ matrix.python_version }} | ||||
| 
 | ||||
|       - name: Build and test wheels | ||||
|         env: | ||||
|           # Generate the platform identifier. See https://cibuildwheel.pypa.io/en/stable/options/#build-skip. | ||||
|           CIBW_BUILD: cp${{ matrix.cibw_python_version }}-${{ matrix.platform_id }} | ||||
|           CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux_image }} | ||||
|           CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux_image }} | ||||
|           CIBW_ARCHS: all | ||||
|           CIBW_ENVIRONMENT_PASS_LINUX: DEVELOP TIMESTAMP | ||||
| 
 | ||||
|           # Use build instead of pip wheel to build the wheels. This is recommended by PyPA. | ||||
|           # See https://cibuildwheel.pypa.io/en/stable/options/#build-frontend. | ||||
|           CIBW_BUILD_FRONTEND: "build" | ||||
|           CIBW_BEFORE_ALL: bash {project}/build_tools/wheels/cibw_before_all.sh ${{ matrix.python_version }} {project} | ||||
| 
 | ||||
|           CIBW_BUILD_VERBOSITY: 1 | ||||
| 
 | ||||
|         run: bash build_tools/wheels/build_wheels.sh | ||||
| 
 | ||||
|       - name: Store artifacts | ||||
|         uses: actions/upload-artifact@v4 | ||||
|         with: | ||||
|           name: cibw-wheels-cp${{ matrix.cibw_python_version }}-${{ matrix.platform_id }} | ||||
|           path: wheelhouse/*.whl | ||||
| 
 | ||||
|   upload_all: | ||||
|     name: Upload All | ||||
|     needs: build_wheels | ||||
|     runs-on: ubuntu-latest | ||||
|     permissions: | ||||
|       id-token: write | ||||
|     steps: | ||||
|       - name: Download Artifacts | ||||
|         uses: actions/download-artifact@v4 | ||||
|         with: | ||||
|           path: dist/ | ||||
|           merge-multiple: true | ||||
| 
 | ||||
|       - name: Publish to PyPI | ||||
|         uses: pypa/gh-action-pypi-publish@release/v1 | ||||
|         with: | ||||
|           verbose: true | ||||
|           packages-dir: dist/ | ||||
|           # repository-url: https://test.pypi.org/legacy/ | ||||
|  | @ -1,4 +1,4 @@ | |||
| /build* | ||||
| /build | ||||
| /debug* | ||||
| .idea | ||||
| *.pyc | ||||
|  |  | |||
|  | @ -10,10 +10,23 @@ set (GTSAM_VERSION_PATCH 0) | |||
| set (GTSAM_PRERELEASE_VERSION "a0") | ||||
| math (EXPR GTSAM_VERSION_NUMERIC "10000 * ${GTSAM_VERSION_MAJOR} + 100 * ${GTSAM_VERSION_MINOR} + ${GTSAM_VERSION_PATCH}") | ||||
| 
 | ||||
| if ("${GTSAM_PRERELEASE_VERSION}" STREQUAL "") | ||||
| # Set the version string for the library.  | ||||
| # | ||||
| # If the environment variable DEVELOP is set, then the version string will be | ||||
| # "MAJOR.MINORprerelease.devTIMESTAMP". TIMESTAMP is another environment variable that should be set to the current | ||||
| # datetime. See build-cibw.yaml for example usage. | ||||
| # | ||||
| # If the prerelease version is empty, then the version string will be "MAJOR.MINOR.PATCH". Otherwise, the version | ||||
| # string will be "MAJOR.MINORprerelease". | ||||
| if (DEFINED ENV{DEVELOP}) | ||||
|     set (GTSAM_VERSION_STRING "${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}${GTSAM_PRERELEASE_VERSION}.dev$ENV{TIMESTAMP}") | ||||
|     set (SETUP_NAME "gtsam-develop") | ||||
| elseif ("${GTSAM_PRERELEASE_VERSION}" STREQUAL "") | ||||
|     set (GTSAM_VERSION_STRING "${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}.${GTSAM_VERSION_PATCH}") | ||||
|     set (SETUP_NAME "gtsam") | ||||
| else() | ||||
|     set (GTSAM_VERSION_STRING "${GTSAM_VERSION_MAJOR}.${GTSAM_VERSION_MINOR}${GTSAM_PRERELEASE_VERSION}") | ||||
|     set (SETUP_NAME "gtsam") | ||||
| endif() | ||||
| 
 | ||||
| project(GTSAM | ||||
|  |  | |||
|  | @ -0,0 +1,10 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| # This script calls cibuildwheel to build the wheels for the project. It is used in the build-cibw.yml workflow in .github/workflows. | ||||
| # Note that the build/python directory contains the wrapper module built for the specified Python version. | ||||
| 
 | ||||
| set -e | ||||
| set -x | ||||
| 
 | ||||
| python -m pip install cibuildwheel | ||||
| python -m cibuildwheel build/python --output-dir wheelhouse | ||||
|  | @ -0,0 +1,63 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| # This script is invoked prior to building the wheels with cibuildwheel. It is used in the build-cibw.yml workflow in .github/workflows. | ||||
| # It installs the necessary dependencies and builds the wrapper module for the specified Python version. | ||||
| 
 | ||||
| set -e | ||||
| set -x | ||||
| 
 | ||||
| PYTHON_VERSION="$1" | ||||
| PROJECT_DIR="$2" | ||||
| ARCH=$(uname -m) | ||||
| 
 | ||||
| export PYTHON="python${PYTHON_VERSION}" | ||||
| 
 | ||||
| if [ "$(uname)" == "Linux" ]; then | ||||
|     # manylinux2014 is based on CentOS 7, so use yum to install dependencies | ||||
|     yum install -y wget | ||||
| 
 | ||||
|     # Install Boost from source | ||||
|     wget https://archives.boost.io/release/1.87.0/source/boost_1_87_0.tar.gz --quiet | ||||
|     tar -xzf boost_1_87_0.tar.gz | ||||
|     cd boost_1_87_0 | ||||
|     ./bootstrap.sh --prefix=/opt/boost | ||||
|     ./b2 install --prefix=/opt/boost --with=all  | ||||
|     cd .. | ||||
| elif [ "$(uname)" == "Darwin" ]; then | ||||
|     brew install wget cmake boost | ||||
| fi | ||||
| 
 | ||||
| $(which $PYTHON) -m pip install -r $PROJECT_DIR/python/dev_requirements.txt | ||||
| 
 | ||||
| # Remove build/cache files that were generated on host | ||||
| rm -rf $PROJECT_DIR/build | ||||
| rm -rf CMakeCache.txt CMakeFiles | ||||
| 
 | ||||
| # Build the Python wrapper module | ||||
| cmake $PROJECT_DIR \ | ||||
|     -B build \ | ||||
|     -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \ | ||||
|     -DGTSAM_BUILD_TESTS=OFF \ | ||||
|     -DGTSAM_BUILD_UNSTABLE=${GTSAM_BUILD_UNSTABLE:-ON} \ | ||||
|     -DGTSAM_USE_QUATERNIONS=OFF \ | ||||
|     -DGTSAM_WITH_TBB=${GTSAM_WITH_TBB:-OFF} \ | ||||
|     -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF \ | ||||
|     -DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF \ | ||||
|     -DGTSAM_BUILD_PYTHON=ON \ | ||||
|     -DGTSAM_UNSTABLE_BUILD_PYTHON=${GTSAM_BUILD_UNSTABLE:-ON} \ | ||||
|     -DGTSAM_PYTHON_VERSION=$PYTHON_VERSION \ | ||||
|     -DPYTHON_EXECUTABLE:FILEPATH=$(which $PYTHON) \ | ||||
|     -DGTSAM_ALLOW_DEPRECATED_SINCE_V43=OFF \ | ||||
|     -DCMAKE_INSTALL_PREFIX=$PROJECT_DIR/gtsam_install | ||||
| 
 | ||||
| cd $PROJECT_DIR/build/python | ||||
| 
 | ||||
| # Install the Python wrapper module and generate Python stubs | ||||
| if [ "$(uname)" == "Linux" ]; then | ||||
|     make -j $(nproc) install | ||||
|     make -j $(nproc) python-stubs | ||||
| elif [ "$(uname)" == "Darwin" ]; then | ||||
|     make -j $(sysctl -n hw.logicalcpu) install | ||||
|     make -j $(sysctl -n hw.logicalcpu) python-stubs | ||||
| fi | ||||
| 
 | ||||
|  | @ -284,9 +284,9 @@ endif() | |||
| add_custom_target( | ||||
|         python-stubs | ||||
|         COMMAND | ||||
|         ${CMAKE_COMMAND} -E env | ||||
|         "PYTHONPATH=${GTSAM_PYTHON_BUILD_DIRECTORY}/$ENV{PYTHONPATH}" | ||||
|         pybind11-stubgen -o . --enum-class-locations \"KernelFunctionType|NoiseFormat:gtsam.gtsam\" --enum-class-locations \"OrderingType:gtsam.gtsam.Ordering\" --numpy-array-use-type-var --ignore-all-errors gtsam | ||||
|           ${CMAKE_COMMAND} -E env | ||||
|           "PYTHONPATH=${GTSAM_PYTHON_BUILD_DIRECTORY}/$ENV{PYTHONPATH}" | ||||
|         ${PYTHON_EXECUTABLE} -m pybind11_stubgen -o . --enum-class-locations \"KernelFunctionType|NoiseFormat:gtsam.gtsam\" --enum-class-locations \"OrderingType:gtsam.gtsam.Ordering\" --numpy-array-use-type-var --ignore-all-errors gtsam | ||||
|         DEPENDS ${GTSAM_PYTHON_DEPENDENCIES} ${GTSAM_PYTHON_TEST_FILES} ${GTSAM_PYTHON_TARGET} | ||||
|         WORKING_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/" | ||||
| ) | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| """Setup file to install the GTSAM package.""" | ||||
| 
 | ||||
| from setuptools import setup, find_namespace_packages | ||||
| from setuptools import setup, find_namespace_packages, Distribution | ||||
| 
 | ||||
| packages = find_namespace_packages( | ||||
|     where=".", | ||||
|  | @ -20,8 +20,14 @@ package_data = { | |||
| # Cleaner to read in the contents rather than copy them over. | ||||
| readme_contents = open("${GTSAM_SOURCE_DIR}/README.md").read() | ||||
| 
 | ||||
| # The cibuildwheel tool won't recognize a wheel as platform-dependent unless the ext_modules option is defined in setup.py. This is used to define C/C++ source files that need to be built for the wheel. | ||||
| # However, we pre-build our C++ files. Thus, we force cibuildwheel to think that there are ext_modules defined by overwriting the has_ext_modules() function. | ||||
| class BinaryDistribution(Distribution): | ||||
|     def has_ext_modules(foo): | ||||
|         return True | ||||
| 
 | ||||
| setup( | ||||
|     name='gtsam', | ||||
|     name='${SETUP_NAME}', | ||||
|     description='Georgia Tech Smoothing And Mapping library', | ||||
|     url='https://gtsam.org/', | ||||
|     version='${GTSAM_VERSION_STRING}',  # https://www.python.org/dev/peps/pep-0440/ | ||||
|  | @ -46,6 +52,7 @@ setup( | |||
|     packages=packages, | ||||
|     include_package_data=True, | ||||
|     package_data=package_data, | ||||
|     distclass=BinaryDistribution, | ||||
|     test_suite="gtsam.tests", | ||||
|     install_requires=open("${GTSAM_SOURCE_DIR}/python/requirements.txt").readlines(), | ||||
|     zip_safe=False, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue