diff --git a/.github/workflows/cpp-test.yml b/.github/workflows/cpp-test.yml index 07f58608..616eae57 100644 --- a/.github/workflows/cpp-test.yml +++ b/.github/workflows/cpp-test.yml @@ -1,4 +1,4 @@ -name: C++ test linux +name: Test bmdscore Linux on: pull_request: diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test-linux.yml similarity index 78% rename from .github/workflows/python-test.yml rename to .github/workflows/python-test-linux.yml index 9a23d9a4..3b298c36 100644 --- a/.github/workflows/python-test.yml +++ b/.github/workflows/python-test-linux.yml @@ -1,4 +1,4 @@ -name: Python test linux +name: Test pybmds Linux on: pull_request: @@ -7,29 +7,31 @@ on: - main workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.ref_name }} + cancel-in-progress: true + jobs: test: - runs-on: ${{ matrix.os }} - strategy: - max-parallel: 4 - matrix: - python-version: ["3.11"] - os: ["ubuntu-22.04"] + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: "3.12" cache: pip - - name: Install dependencies and build pybmds + - name: Install dependencies run: | source ./tools/linux_ci_setup.sh + - name: Build pybmds + run: | source ./tools/linux_ci_env.sh python -m pip install -U pip wheel python -m pip install -e ".[dev,docs]" stubgen -p pybmds.bmdscore -o src ruff format src/pybmds/bmdscore.pyi + python -c "import pybmds; print(pybmds.bmdscore.version())" - name: Check linked files run: | ls -lah src/pybmds diff --git a/.github/workflows/python-test-windows.yml b/.github/workflows/python-test-windows.yml index bbde424b..20f61f9f 100644 --- a/.github/workflows/python-test-windows.yml +++ b/.github/workflows/python-test-windows.yml @@ -1,4 +1,4 @@ -name: Python test windows +name: Test pybmds Windows on: push: @@ -6,83 +6,53 @@ on: - main workflow_dispatch: -env: - PYTHON_LIBRARY_DIR: $Env:CONDA\Lib\site-packages - PYTHON_EXECUTABLE: $Env:CONDA\python.exe - BUILD_TYPE: Release - concurrency: group: ${{ github.workflow }}-${{ github.ref_name }} cancel-in-progress: true jobs: test: - runs-on: ${{ matrix.os }} - strategy: - max-parallel: 4 - matrix: - python-version: ["3.11"] - os: ["windows-2022"] - + runs-on: windows-2022 steps: - uses: actions/checkout@v4 - - name: set up python ${{ matrix.python-version }} + - name: set up Python uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: "3.12" cache: pip - - name: set dependency directory - run: echo "DEPENDENCY_DIR=$HOME\github-deps" >> $env:GITHUB_ENV - - name: restore github dependencies from cache - id: cache-github + - name: Set dependency path + shell: bash + run: | + DEP="$GITHUB_WORKSPACE/deps" + echo "DEPENDENCY_DIR=$DEP" >> $GITHUB_ENV + echo "EIGEN_DIR=$DEP\eigen" >> $GITHUB_ENV + echo "NLOPT_DIR=$DEP\nlopt\src\api;$DEP\nlopt\build\Release;$DEP\nlopt\build" >> $GITHUB_ENV + echo "GSL_DIR=$DEP\gsl\build\Release;$DEP\gsl\build" >> $GITHUB_ENV + - name: Restore dependencies from cache + id: cache-dependencies uses: actions/cache@v4 with: path: ${{ env.DEPENDENCY_DIR }} - key: ${{runner.os}}-github-deps - - name: create dependency dir - if: steps.cache-github.outputs.cache-hit != 'true' - run: mkdir ${{ env.DEPENDENCY_DIR }} - - name: download eigen - if: steps.cache-github.outputs.cache-hit != 'true' - run: | - cd ${{ env.DEPENDENCY_DIR }} - git clone --depth 1 https://github.com/libigl/eigen.git - - name: install nlopt - if: steps.cache-github.outputs.cache-hit != 'true' - run: | - cd ${{ env.DEPENDENCY_DIR }} - git clone --depth 1 https://github.com/stevengj/nlopt.git - cd nlopt - mkdir build - cd build - cmake -DBUILD_SHARED_LIBS=OFF .. - cmake --build . --config Release - - name: install gsl - if: steps.cache-github.outputs.cache-hit != 'true' - run: | - cd ${{ env.DEPENDENCY_DIR }} - git clone --depth 1 https://github.com/ampl/gsl.git - cd gsl - mkdir build - cd build - cmake .. -DNO_AMPL_BINDINGS=1 - cmake --build . --config Release - - name: set eigen/nlopt/gsl directories - run: | - echo "EIGEN_DIR=${{ env.DEPENDENCY_DIR }}\eigen" >> $env:GITHUB_ENV - echo "NLOPT_DIR=${{ env.DEPENDENCY_DIR }}\nlopt\src\api;${{ env.DEPENDENCY_DIR }}\nlopt\build\Release;${{ env.DEPENDENCY_DIR }}\nlopt\build" >> $env:GITHUB_ENV - echo "GSL_DIR=${{ env.DEPENDENCY_DIR }}\gsl\build\Release;${{ env.DEPENDENCY_DIR }}\gsl\build" >> $env:GITHUB_ENV + key: ${{runner.os}}-cache-dependencies + - name: Build dependencies + if: steps.cache-dependencies.outputs.cache-hit != 'true' + shell: bash + run: tools/windows_ci.sh - name: Build package run: | python -m pip install -U pip wheel - python -m pip install -e ".[dev,docs]" + python -m pip install -e ".[dev]" stubgen -p pybmds.bmdscore -o src ruff format src/pybmds/bmdscore.pyi - python setup.py bdist_wheel + python -c "import pybmds; print(pybmds.bmdscore.version())" - name: Check shared object linked files run: | python -m pip install pefile python -c "from pathlib import Path; import pefile; fn = str(list(Path('src/pybmds').glob('bmdscore*'))[0].resolve()); pe = pefile.PE(fn); print([i.dll for i in pe.DIRECTORY_ENTRY_IMPORT])" + - name: Build package + run: | + python -m pip install -U pip wheel + python setup.py bdist_wheel - uses: actions/upload-artifact@v4 with: path: ./dist/*.whl diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml new file mode 100644 index 00000000..b37adc5f --- /dev/null +++ b/.github/workflows/wheels.yml @@ -0,0 +1,46 @@ +name: Build Python Packages + +on: + schedule: + - cron: '30 3 1 */1 *' # At 03:30 on the 1st of every month + push: + tags: + - '*' + workflow_dispatch: + +jobs: + + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-22.04, windows-2022, macos-14] + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Show wheels that will be built + run: | + python -m pip install cibuildwheel==2.18.1 + cibuildwheel --print-build-identifiers + - name: Build wheels + uses: pypa/cibuildwheel@v2.18.1 + env: + MACOSX_DEPLOYMENT_TARGET: "14.0" + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + + merge_wheels: + runs-on: ubuntu-22.04 + needs: build_wheels + steps: + - name: Merge Artifacts + uses: actions/upload-artifact/merge@v4 + with: + name: wheels + delete-merged: true diff --git a/CMAKE_README.md b/CMAKE_README.md index b5e0d568..b6e18409 100644 --- a/CMAKE_README.md +++ b/CMAKE_README.md @@ -24,8 +24,6 @@ Visual Studio 19 or greater |NLOPT_DIR|path to nlopt lib directory|/home/username/libs/nlopt-2.6.2/lib64| |CMAKE_C_COMPILER|path to c compiler|/usr/local/apps/gcc/9.1.0/bin/gcc| |CMAKE_CXX_COMPILER|path to c++ compiler|/usr/local/apps/gcc/9.1.0/bin/g++| -|PYTHON_EXECUTABLE|path to python executable |/home/username/mambaforge/bin/python| -|PYTHON_LIBRARY_DIR|path to python site-packages directory| /home/username/venv/Lib/site-packages| ## Build process diff --git a/CMakeLists.txt b/CMakeLists.txt index 09d84c56..b4808a56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,9 +40,6 @@ ENDIF() IF(DEFINED ENV{CMAKE_CXX_COMPILER}) set(CMAKE_CXX_COMPILER $ENV{CMAKE_CXX_COMPILER}) ENDIF() -IF(DEFINED ENV{PYTHON_LIBRARY_DIR}) - set(PYTHON_LIBRARY_DIR $ENV{PYTHON_LIBRARY_DIR}) -ENDIF() IF(WIN32) add_compile_definitions(RBMDS_EXPORTS) @@ -88,8 +85,3 @@ IF(WIN32) ELSE() target_link_libraries(bmdscore PUBLIC GSL::gsl GSL::gslcblas ${NLOPT_LIB}) ENDIF(WIN32) - -install(TARGETS bmdscore - COMPONENT python - LIBRARY DESTINATION "${PYTHON_LIBRARY_DIR}" - ) diff --git a/pyproject.toml b/pyproject.toml index 591153ae..f58a0ef3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,9 +57,46 @@ requires = [ build-backend = "setuptools.build_meta" [tool.cibuildwheel] -test-requires = "pytest" +archs = ["auto64"] +build = ["cp311-*", "cp312-*"] +skip = [ + "*-win32", + "*-win_arm64", + "*musllinux*", + "*i686", + "*-macosx_x86_64", + "*-macosx_universal2", +] +manylinux-x86_64-image = "manylinux_2_28" +manylinux-aarch64-image = "manylinux_2_28" +test-requires = ["pytest", "pytest-mpl"] test-command = "pytest {project}/tests" +[tool.cibuildwheel.windows] +before-build = "bash tools/windows_ci.sh" + +[tool.cibuildwheel.windows.environment] +EIGEN_DIR="D:/a/bmds/bmds/deps/eigen" +NLOPT_DIR="D:/a/bmds/bmds/deps/nlopt/src/api;D:/a/bmds/bmds/deps/nlopt/build/Release;D:/a/bmds/bmds/deps/nlopt/build" +GSL_DIR="D:/a/bmds/bmds/deps/gsl/build/Release;D:/a/bmds/bmds/deps/gsl/build" + +[tool.cibuildwheel.linux] +before-build = "tools/cibuildwheel-linux.sh" + +[tool.cibuildwheel.linux.environment] +EIGEN_DIR="/usr/include/eigen3" +NLOPT_DIR="/usr/local/lib64/" +CMAKE_C_COMPILER="/opt/rh/gcc-toolset-12/root/usr/bin/gcc" +CMAKE_CXX_COMPILER="/opt/rh/gcc-toolset-12/root/usr/bin/g++" + +[tool.cibuildwheel.macos] +before-build = "tools/cibuildwheel-mac.sh" + +[tool.cibuildwheel.macos.environment] +EIGEN_DIR="/opt/homebrew/Cellar/eigen/3.4.0_1/include/eigen3" +GSL_DIR="/opt/homebrew/Cellar/gsl/2.7.1" +NLOPT_DIR="/opt/homebrew/Cellar/nlopt/2.7.1/include" + [tool.coverage.run] include = [ "src/pybmds/*" diff --git a/tools/cibuildwheel-linux.sh b/tools/cibuildwheel-linux.sh new file mode 100755 index 00000000..cdf6a4b7 --- /dev/null +++ b/tools/cibuildwheel-linux.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -xe + +yum update -y +yum install -y cmake gsl-devel eigen3-devel + +cp ./vendor/nlopt-2.7.1.tar.gz ~ +cd ~ +tar -xf nlopt-2.7.1.tar.gz && cd nlopt-2.7.1 && mkdir build && cd build && cmake -DBUILD_SHARED_LIBS=OFF .. && make install +cd $GITHUB_WORKSPACE diff --git a/tools/cibuildwheel-mac.sh b/tools/cibuildwheel-mac.sh new file mode 100755 index 00000000..abd87b9e --- /dev/null +++ b/tools/cibuildwheel-mac.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -xe + +brew install gsl --quiet +brew install nlopt --quiet +brew install eigen --quiet + +cd $GITHUB_WORKSPACE diff --git a/tools/linux_ci.sh b/tools/linux_ci.sh new file mode 100644 index 00000000..04941cb0 --- /dev/null +++ b/tools/linux_ci.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +sudo apt-get update -y +sudo apt-get install -y automake build-essential libtool make cmake libgslcblas0 libgsl-dev libeigen3-dev libnlopt-dev libnlopt-cxx-dev lcov + +export "EIGEN_DIR=/usr/include/eigen3" +export "NLOPT_DIR=/usr/lib/x86_64-linux-gnu/" +export "CMAKE_C_COMPILER=/usr/bin/gcc-12" +export "CMAKE_CXX_COMPILER=/usr/bin/g++-12" diff --git a/tools/linux_ci_env.sh b/tools/linux_ci_env.sh index c8304fd2..16268272 100755 --- a/tools/linux_ci_env.sh +++ b/tools/linux_ci_env.sh @@ -4,6 +4,4 @@ export EIGEN_DIR="/usr/include/eigen3" export NLOPT_DIR="/usr/lib/x86_64-linux-gnu/" export CMAKE_C_COMPILER="/usr/bin/gcc-11" export CMAKE_CXX_COMPILER="/usr/bin/g++-11" -export PYTHON_EXECUTABLE=$(which python) -export PYTHON_LIBRARY_DIR=$(python -c "import site; print(site.getsitepackages()[0])") export TEST_EXC="'/usr/include/*'" diff --git a/tools/windows_ci.sh b/tools/windows_ci.sh new file mode 100755 index 00000000..ae07a909 --- /dev/null +++ b/tools/windows_ci.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -xe + +# only do this first time +DEPS="$GITHUB_WORKSPACE/deps" +if [ -d "$DEPS" ]; then + exit 0 +fi +mkdir -p $DEPS + +# filenames and versions +EIGEN="eigen-3.4.0" +NLOPT="nlopt-2.7.1" +GSL="ampl-gsl-60539d2" + +# eigen +cp $GITHUB_WORKSPACE/vendor/$EIGEN.tar.gz $DEPS +cd $DEPS && tar -xf $EIGEN.tar.gz && mv $EIGEN eigen && rm $EIGEN.tar.gz + +# nlopt +cp $GITHUB_WORKSPACE/vendor/$NLOPT.tar.gz $DEPS +cd $DEPS && tar -xf $NLOPT.tar.gz && mv $NLOPT nlopt && rm $NLOPT.tar.gz +cd nlopt && mkdir build && cd build +cmake -DBUILD_SHARED_LIBS=OFF .. +cmake --build . --config Release + +# gsl +cp $GITHUB_WORKSPACE/vendor/$GSL.tar.gz $DEPS +cd $DEPS && tar -xf $GSL.tar.gz && mv gsl-master gsl && rm $GSL.tar.gz +cd gsl && mkdir build && cd build +cmake -DNO_AMPL_BINDINGS=1 .. +cmake --build . --config Release diff --git a/vendor/ampl-gsl-60539d2.tar.gz b/vendor/ampl-gsl-60539d2.tar.gz new file mode 100644 index 00000000..5fd2d299 Binary files /dev/null and b/vendor/ampl-gsl-60539d2.tar.gz differ