diff --git a/.github/workflows/dolfinx-tests.yml b/.github/workflows/dolfinx-tests.yml index 9e0615e17..b85d22e9d 100644 --- a/.github/workflows/dolfinx-tests.yml +++ b/.github/workflows/dolfinx-tests.yml @@ -31,10 +31,12 @@ jobs: run: cat .github/workflows/fenicsx-refs.env >> $GITHUB_ENV - name: Install Basix run: | - cmake -G Ninja -DCMAKE_BUILD_TYPE=Developer -B build-dir -S ./cpp - cmake --build build-dir - cmake --install build-dir - python3 -m pip install --break-system-packages ./python + cmake -G Ninja -DCMAKE_BUILD_TYPE=Developer -B build-dir -S cpp/ + cmake --build build-dir/ + cmake --install build-dir/ + # This tests non-RPATH based linking. + ldconfig + python3 -m pip -v install -Ccmake.args=-DBASIX_SET_INSTALL_RPATH=OFF --break-system-packages python/ - name: Install FEniCS Python components run: | python3 -m pip install --break-system-packages git+https://github.com/${{ env.ufl_repository }}.git@${{ env.ufl_ref }} diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index 8ebe0d91e..4a002dfdc 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -134,7 +134,7 @@ jobs: git commit --allow-empty -m "Update Basix docs FEniCS/basix@${{ github.sha }}" git push - isolated-python-build: + no-isolation-python-build: name: Build Python using '--no-build-isolation' runs-on: ubuntu-latest steps: @@ -148,7 +148,10 @@ jobs: - name: Install Python dependencies run: pip install nanobind scikit-build-core[pyproject] - name: Install Basix - run: pip install --no-build-isolation . + run: | + pip install scikit-build-core + python -m scikit_build_core.build requires | python -c "import sys, json; print(' '.join(json.load(sys.stdin)))" | xargs pip install + pip install --no-build-isolation . - name: Install mypy run: pip install mypy - name: Run mypy (module) @@ -158,8 +161,8 @@ jobs: # - name: Run mypy (demo) # run: mypy demo/python - build-cmake: - name: Build using C++ and Python parts separately and run tests + build-separately: + name: Build C++ and Python parts separately and run tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 @@ -189,7 +192,7 @@ jobs: run: pytest demo/cpp/test.py build-cpp-only: - name: Build C++ only and run demos + name: Build C++ part only and run demos runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 1a28e798f..7be1fb712 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -43,13 +43,6 @@ jobs: - uses: actions/checkout@v7 - - name: Export GitHub Actions cache environment variables - uses: actions/github-script@v9 - with: - script: | - core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); - core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - - name: Set up Python uses: actions/setup-python@v6 with: @@ -58,7 +51,7 @@ jobs: - name: Set up CMake uses: lukka/get-cmake@latest with: - cmakeVersion: "~3.30.0" + cmakeVersion: "latest" - name: Install Basix (combined) run: | @@ -100,7 +93,7 @@ jobs: - name: Set up CMake uses: lukka/get-cmake@latest with: - cmakeVersion: "~3.30.0" + cmakeVersion: "latest" - name: Install Basix (C++) run: | diff --git a/INSTALL.md b/INSTALL.md index fa9c3f362..ed951937b 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -2,7 +2,7 @@ ## Standard -Basix can be installed using +Basix can be installed using: ```console pip install . ``` @@ -21,8 +21,9 @@ cmake -DCMAKE_BUILD_TYPE=Release -B build-dir -S . cmake --build build-dir cmake --install build-dir ``` -Using the CMake build type `Release` is strongly recommended for -performance. + +Using the CMake build type `Release` or `RelWithDebug` is strongly recommended +for performance. ### Python interface @@ -35,10 +36,13 @@ pip install . For a debug and editable build for development: ```console -pip -v install --check-build-dependencies --config-settings=build-dir="build" --config-settings=cmake.build-type="Debug" --config-settings=install.strip=false --no-build-isolation -e . +pip -v install --check-build-dependencies -Cbuild-dir="build" -Ccmake.build-type="Development" -Cinstall.strip=false --no-build-isolation -e . ``` -When using the `--no-build-isolation` option all build and runtime -dependencies must already be installed. +When using the `--no-build-isolation` option all build dependencies must +already be installed (see `python/pyproject.toml`). + +RPATH manipulation can be disabled by passing +`-Ccmake.args=-DBASIX_SET_INSTALL_RPATH=FALSE`. ## Running the unit tests diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 6e287e977..4c7dc518f 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -114,7 +114,7 @@ endif() target_include_directories(basix PUBLIC $ - "$") + "$") target_compile_definitions(basix PUBLIC MDSPAN_USE_PAREN_OPERATOR=1) target_compile_definitions(basix PUBLIC MDSPAN_USE_BRACKET_OPERATOR=0) @@ -188,7 +188,7 @@ endif() # Configure CMake helpers include(CMakePackageConfigHelpers) -write_basic_package_version_file(BasixConfigVersion.cmake VERSION ${PACKAGE_VERSION} +write_basic_package_version_file(BasixConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion) configure_package_config_file(BasixConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/BasixConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/basix) diff --git a/pyproject.toml b/pyproject.toml index 053c9e110..87b532bfd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,10 @@ testpaths = ["test"] [tool.scikit-build] wheel.packages = ["python/basix"] +[tool.scikit-build.cmake.define] +# Set to FALSE to disable install RPATH adjustments +BASIX_SET_INSTALL_RPATH = "TRUE" + [tool.cibuildwheel] build-frontend = { name = "build", args = [ "-Cwheel.py-api=cp312", diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 73183e35a..c3f178391 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,17 +1,12 @@ cmake_minimum_required(VERSION 3.21) -# nanobind uses aligned deallocators only present on macOS > 10.14 -if(APPLE) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") -endif() - -project(basix_nanobind VERSION LANGUAGES CXX) +project(basix_nanobind LANGUAGES CXX) if(WIN32) # Windows requires all symbols to be manually exported. # This flag exports all symbols automatically, as in Unix. set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) -endif(WIN32) +endif() # See https://gitlab.kitware.com/cmake/cmake/-/issues/16414 if(TARGET basix) @@ -28,6 +23,9 @@ include(FeatureSummary) option(ENABLE_CLANG_TIDY "Run clang-tidy while building" OFF) add_feature_info(ENABLE_CLANG_TIDY ENABLE_CLANG_TIDY "Run clang-tidy while building") +option(BASIX_SET_INSTALL_RPATH "Set rpath of _basixcpp to location of installed C++ library" TRUE) +add_feature_info(BASIX_SET_INSTALL_RPATH BASIX_SET_INSTALL_RPATH "Set rpath of _basixcpp to location of installed C++ library") + feature_summary(WHAT ALL) # Detect the installed nanobind package and import it into CMake @@ -42,7 +40,7 @@ if(NOT "${SKBUILD_SABI_VERSION}" STREQUAL "") set(NANOBIND_SABI "STABLE_ABI") endif() nanobind_add_module(_basixcpp NB_SUPPRESS_WARNINGS ${NANOBIND_SABI} wrapper.cpp) -target_compile_definitions(_basixcpp PRIVATE cxx_std_20) +target_compile_features(_basixcpp PRIVATE cxx_std_20) if(ENABLE_CLANG_TIDY) find_program(CLANG_TIDY NAMES clang-tidy REQUIRED) @@ -98,15 +96,19 @@ target_compile_definitions( target_compile_definitions(_basixcpp PRIVATE MDSPAN_USE_PAREN_OPERATOR=1) target_compile_definitions(_basixcpp PRIVATE MDSPAN_USE_BRACKET_OPERATOR=0) -# Add relative rpath so _basixcpp can find the Basix::basix library -# when the build is relocated -if(BASIX_FULL_SKBUILD) +if(BASIX_FULL_SKBUILD AND BASIX_SET_INSTALL_RPATH) + # If building bundled C++ and Python wrapper wheel `pip install .` add relative + # rpath so _basixcpp can find the bundled Basix::basix library when the wheel + # is relocated. if(APPLE) set_target_properties(_basixcpp PROPERTIES INSTALL_RPATH "@loader_path/lib") elseif(UNIX) set_target_properties(_basixcpp PROPERTIES INSTALL_RPATH "$ORIGIN/lib") endif() -else() +elseif(BASIX_SET_INSTALL_RPATH) + # If building standalone Python wrapper `pip install python/` put absolute + # path to Basix C++ library on rpath - can help linking if it is outside a + # system directory. The build is non-relocatable. get_target_property(_location Basix::basix LOCATION) get_filename_component(_basix_dir ${_location} DIRECTORY) set_target_properties(_basixcpp PROPERTIES INSTALL_RPATH ${_basix_dir}) @@ -114,8 +116,9 @@ endif() # and the nanobind typing stubs. if (WIN32) - # On Windows we cannot import basix._basixcpp without installing the package - # alongside its external dlls. + # On Windows we cannot import basix._basixcpp without bundling in all + # external dlls and relying on Windows library search order - effectively a + # 'static binary build'. # This *must* be called prior to nanobind_add_stub install(TARGETS _basixcpp LIBRARY DESTINATION basix) diff --git a/python/README.md b/python/README.md index 8cf91df56..007244023 100644 --- a/python/README.md +++ b/python/README.md @@ -1,8 +1,3 @@ -# Re-generating nanobind stubs +# Basix Python -To update the nanobind type stubs, after installing the Basix Python -interface, run: -```sh -python -m nanobind.stubgen -m basix._basixcpp -M basix/py.typed -p pattern_stub.txt -o basix/_basixcpp.pyi -``` -from the `python/` directory. \ No newline at end of file +Please see `../INSTALL.md` and `../README.md`. diff --git a/python/pyproject.toml b/python/pyproject.toml index 63e6d6613..a54328b66 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -34,3 +34,7 @@ ignore_missing_imports = true [tool.scikit-build] wheel.packages = ["basix"] + +[tool.scikit-build.cmake.define] +# Set to FALSE to disable all install RPATH adjustments +BASIX_SET_INSTALL_RPATH = "TRUE"