diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 8e1ecf95..1bf70e42 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -130,6 +130,56 @@ jobs: name: wheel-linux-${{ matrix.python-version }} path: wheelhouse/*.whl + build-wheels-linux-hpc: + name: Build wheel on Ubuntu HPC profile (Python 3.12) + needs: [check-version] + runs-on: ubuntu-latest + if: needs.check-version.outputs.should_build == 'true' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install system dependencies + run: | + sudo apt update + sudo apt install -y cmake build-essential doxygen libtbb-dev + + - name: Install build dependencies + run: | + python -m pip install --upgrade pip + python -m pip install build wheel setuptools pybind11-stubgen + + - name: Build Ubuntu HPC wheel (-O3 only) + env: + CMAKE_ARGS: "-DDSF_HPC_RELEASE=ON -DDSF_OPTIMIZE_ARCH=OFF" + DSF_HPC_BUILD: "ON" + DSF_PACKAGE_VERSION: ${{ needs.check-version.outputs.publish_version }} + run: | + rm -rf dist wheelhouse + python -m build --wheel + + - name: Prepare wheel artifact + run: | + mkdir -p wheelhouse + cp dist/*.whl wheelhouse/ + + - name: Test wheel installation + run: | + python -m pip install wheelhouse/*.whl + python -c "import dsf; print('DSF Ubuntu HPC wheel installation successful')" + + - name: Upload Ubuntu HPC wheel as artifact + uses: actions/upload-artifact@v4 + with: + name: wheel-linux-hpc-3.12 + path: wheelhouse/*.whl + build-wheels-macos: name: Build wheels on macOS (Python ${{ matrix.python-version }}) needs: [check-version] @@ -263,7 +313,7 @@ jobs: publish: name: Publish to PyPI - needs: [check-version, build-wheels-linux, build-wheels-macos, build-wheels-windows, build-sdist] + needs: [check-version, build-wheels-linux, build-wheels-linux-hpc, build-wheels-macos, build-wheels-windows, build-sdist] runs-on: ubuntu-latest if: needs.check-version.outputs.should_build == 'true' diff --git a/CITATION.cff b/CITATION.cff index be34d1fa..f8162e18 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -12,5 +12,5 @@ authors: repository-code: 'https://github.com/physycom/DynamicalSystemFramework' url: 'https://physycom.github.io/DynamicalSystemFramework/' license: CC-BY-NC-SA-4.0 -version: 5.3.1 +version: 5.3.2 date-released: '2026-03-06' diff --git a/CMakeLists.txt b/CMakeLists.txt index 8127c7c1..d32918e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ option(DSF_BENCHMARKS "Build DSF benchmarks" OFF) option(DSF_BUILD_PIC "Build DSF with position-independent code" OFF) option(BUILD_PYTHON_BINDINGS "Build Python bindings" OFF) option(DSF_OPTIMIZE_ARCH "Optimize for native architecture" ON) +option(DSF_HPC_RELEASE "Build release flags suitable for HPC infrastructure" OFF) # If CMAKE_BUILD_TYPE not set, default to Debug if(NOT CMAKE_BUILD_TYPE) @@ -47,21 +48,33 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +if(DSF_HPC_RELEASE) + set(DSF_OPTIMIZE_ARCH OFF) +endif() + # Ensure optimization flags are applied only in Release mode if(CMAKE_BUILD_TYPE MATCHES "Release") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast -flto=auto") - if(DSF_OPTIMIZE_ARCH) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + if(DSF_HPC_RELEASE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast -flto=auto") + if(DSF_OPTIMIZE_ARCH) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + endif() endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2") endif() elseif(CMAKE_BUILD_TYPE MATCHES "Profile") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast -flto=auto -pg") - if(DSF_OPTIMIZE_ARCH) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + if(DSF_HPC_RELEASE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -pg") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast -flto=auto -pg") + if(DSF_OPTIMIZE_ARCH) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + endif() endif() endif() elseif(CMAKE_BUILD_TYPE MATCHES "Coverage") diff --git a/setup.py b/setup.py index 99221703..11c71f76 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ from pathlib import Path import platform import re +import shlex import shutil import subprocess import sys @@ -78,6 +79,26 @@ def build_extension(self, ext: CMakeExtension): "-DBUILD_PYTHON_BINDINGS=ON", ] + # Forward generic CMake args from environment (e.g. CI overrides). + env_cmake_args = os.environ.get("CMAKE_ARGS", "").strip() + if env_cmake_args: + cmake_args.extend(shlex.split(env_cmake_args)) + + # Optional HPC release profile for source builds/wheels. + if os.environ.get("DSF_HPC_BUILD", "").lower() in { + "1", + "on", + "true", + "yes", + }: + cmake_args.extend( + [ + "-DDSF_HPC_RELEASE=ON", + "-DDSF_OPTIMIZE_ARCH=OFF", + "-DCMAKE_POSITION_INDEPENDENT_CODE=ON", + ] + ) + if platform.system() == "Windows": cmake_args += [f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{cfg.upper()}={extdir}"] if "CMAKE_TOOLCHAIN_FILE" in os.environ: @@ -553,4 +574,9 @@ def run_stubgen(self): "shapely", "folium", ], + extras_require={ + # Reserved marker extra for HPC-oriented deployments. + # Build-time behavior is driven through DSF_HPC_BUILD env/CMAKE args. + "hpc": [], + }, ) diff --git a/src/dsf/dsf.hpp b/src/dsf/dsf.hpp index f339db36..6c3f6c8d 100644 --- a/src/dsf/dsf.hpp +++ b/src/dsf/dsf.hpp @@ -9,7 +9,7 @@ static constexpr uint8_t DSF_VERSION_MAJOR = 5; static constexpr uint8_t DSF_VERSION_MINOR = 3; -static constexpr uint8_t DSF_VERSION_PATCH = 1; +static constexpr uint8_t DSF_VERSION_PATCH = 2; static auto const DSF_VERSION = std::format("{}.{}.{}", DSF_VERSION_MAJOR, DSF_VERSION_MINOR, DSF_VERSION_PATCH);