Skip to content

Commit

Permalink
[nanobind] merge pyproject change from main (#2840)
Browse files Browse the repository at this point in the history
* Improve comment (#2839)

* Use `pyproject.toml` for install of Python part (#2707)

* Try using pyproject

* fixup pip command

* Find python

* debug

* Try by adding path explicitly

* Try no build isolation on mac.

* Try this on macos.

* Update CI

* Typo

* Fix.

* Should be dependency of scikit-build-core.

* Attempt fix for ubuntu.

* Fix?

* Add pyproject variant

* Typo.

* Explicit python intepreter.

* Try forcing x86-64 arch.

* Try this ordering.

* Upgrade pip etc.

* And on mac.

* This works locally on my macOS system.

pip install --no-build-isolation is required.

* Works locally, not totally happy with the RPATH stuff.

* Tidy.

* Fix circleci

* Tidy.

* Update minimum pybind11.

* Don't think these belong here.

* Change email.

* Tweaks to Dockerfiles and workflows.

* Update macos workflow

* Typo

* Fix.

* Get cmake to set rpath automatically.

* Don't understand why but doesn't run on circleci, try this.

* Typo

* Tweak.

* Update macos.yml

* Try removing.

* Exclude .cpp files as suggested.

* Add --check-build-dependencies

* Not necessary, think this is well known now.

* Fix typo no install.

* Update build-requirements.txt

* Update pyproject.toml

---------

Co-authored-by: Jack S. Hale <mail@jackhale.co.uk>
Co-authored-by: Garth N. Wells <gnw20@cam.ac.uk>

* Update config

* Small updates

---------

Co-authored-by: Chris Richardson <chris@bpi.cam.ac.uk>
Co-authored-by: Jack S. Hale <mail@jackhale.co.uk>
  • Loading branch information
3 people committed Oct 30, 2023
1 parent 48e352f commit 98596e1
Show file tree
Hide file tree
Showing 18 changed files with 122 additions and 173 deletions.
13 changes: 7 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ regression-tests-cpp-mpi: &regression-tests-cpp-mpi
ctest --verbose -R demo -R mpi_3
build-python-interface: &build-python-interface
name: Build Python/pybind11 interface
name: Build Python/nanobind interface
command: |
export CMAKE_BUILD_PARALLEL_LEVEL=2
cd python
pip3 -v install --global-option build --global-option --debug . --user
pip3 install -r build-requirements.txt
pip3 -v install --config-setting cmake.build-type=Debug --no-build-isolation --user .
demos-python: &demos-python
name: Run demos (Python, serial)
Expand All @@ -81,14 +82,14 @@ unit-tests-python: &unit-tests-python
name: Run unit tests (Python, serial)
command: |
mkdir -p ~/junit
cd python/test/unit
python3 -m pytest -n=4 --durations=50 --junitxml=~/junit/test-results.xml .
cd python/test
python3 -m pytest -n=4 --durations=50 --junitxml=~/junit/test-results.xml unit/
unit-tests-python-mpi: &unit-tests-python-mpi
name: Run unit tests (Python, MPI)
command: |
cd python/test/unit
mpirun -np 3 python3 -m pytest .
cd python/test
mpirun -np 3 python3 -m pytest unit/
jobs:
build-real:
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/ccpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ jobs:
python3 -m pip install git+https://github.com/FEniCS/basix.git@${{ github.event.inputs.basix_ref }}
python3 -m pip install git+https://github.com/FEniCS/ffcx.git@${{ github.event.inputs.ffcx_ref }}
- name: Install matplotlib
run: pip3 install matplotlib
- name: Flake8 checks
run: |
cd python/
Expand All @@ -80,7 +78,7 @@ jobs:
python3 -m isort --check .
- name: mypy checks
run: |
python3 -m pip install types-setuptools mypy --upgrade
python3 -m pip install mypy types-setuptools --upgrade # TO REMOVE
cd python/
mypy dolfinx
mypy demo
Expand Down Expand Up @@ -112,7 +110,7 @@ jobs:
- name: Build C++ interface documentation
run: |
python3 -m pip install breathe
python3 -m pip install breathe # TO REMOVE
export DOLFINX_VERSION=`cmake -L build | grep DOXYGEN_DOLFINX_VERSION | cut -f2 -d "="`
echo $DOLFINX_VERSION
cd cpp/doc
Expand Down Expand Up @@ -142,10 +140,11 @@ jobs:
- name: Build Python interface
run: |
python3 -m pip install git+https://github.com/wjakob/nanobind.git
CMAKE_BUILD_TYPE=Debug python3 -m pip -v install python/
python3 -m pip install -r python/build-requirements.txt # TO REMOVE
python3 -m pip -v install python/
- name: Build Python interface documentation
run: |
python3 -m pip install sphinx==5.0.2
python3 -m pip install sphinx==5.0.2 # TO REMOVE
cd python/doc
make html
Expand Down
23 changes: 11 additions & 12 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,32 +28,31 @@ jobs:
- name: Install Python dependencies
run: |
pip install pip --upgrade
pip install numpy setuptools wheel
pip install cython
pip install mpi4py
python -m pip install --upgrade pip setuptools wheel
python -m pip install cython numpy mpi4py
- name: Install minimal PETSc and petsc4y
- name: Install minimal PETSc and petsc4py
run: |
export PATH="$(brew --prefix bison)/bin:$PATH"
git clone -b release https://gitlab.com/petsc/petsc.git petsc
cd petsc
./configure \
python ./configure \
--with-64-bit-indices=no \
--with-debugging=no \
--with-fortran-bindings=no \
--with-scalar-type=real \
--with-shared-libraries \
--with-scalar-type=real \
-–with-petsc4py=yes \
--download-ptscotch
make all
cd src/binding/petsc4py
PETSC_DIR=$GITHUB_WORKSPACE/petsc PETSC_ARCH=arch-darwin-c-opt arch -x86_64 python -m pip install --no-cache-dir -v .
- name: Install FEniCSx dependencies
run: |
pip install git+https://github.com/FEniCS/basix.git
pip install git+https://github.com/FEniCS/ufl.git
pip install git+https://github.com/FEniCS/ffcx.git
python -m pip install git+https://github.com/FEniCS/basix.git
python -m pip install git+https://github.com/FEniCS/ufl.git
python -m pip install git+https://github.com/FEniCS/ffcx.git
- uses: actions/checkout@v4
with:
Expand All @@ -69,9 +68,9 @@ jobs:
env:
PYTHONPATH: ${{ github.workspace }}/petsc/${{ env.PETSC_ARCH }}/lib:${{ env.PYTHONPATH }}
run: |
echo "Path: ${PYTHONPATH}"
pip install git+https://github.com/wjakob/nanobind.git
pip install dolfinx/python/
python -m pip install -r dolfinx/python/build-requirements.txt
python -m pip install --check-build-dependencies --no-build-isolation dolfinx/python/
- name: Basic test
env:
PYTHONPATH: ${{ github.workspace }}/petsc/${{ env.PETSC_ARCH }}/lib:${{ env.PYTHONPATH }}
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/oneapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,24 +88,26 @@ jobs:
run: |
. /opt/intel/oneapi/setvars.sh
pip install git+https://github.com/wjakob/nanobind.git
pip install python/
pip -v install -r python/build-requirements.txt # TO REMOVE
pip -v install --check-build-dependencies --no-build-isolation python/
- name: Set default DOLFINx JIT options
run: |
mkdir -p ~/.config/dolfinx
echo '{ "cffi_extra_compile_args": ["-g0", "-O0" ] }' > ~/.config/dolfinx/dolfinx_jit_options.json
- name: Run DOLFINx demos (Python, serial)
run: |
. /opt/intel/oneapi/setvars.sh
pip install matplotlib
pytest -n=2 -m serial --durations=10 python/demo/test.py
pip install matplotlib # TO REMOVE
pytest -v -n=2 -m serial --durations=10 python/demo/test.py
- name: Run DOLFINx demos (Python, MPI (np=2))
run: |
. /opt/intel/oneapi/setvars.sh
pytest -m mpi --num-proc=2 python/demo/test.py
- name: Run DOLFINx Python unit tests (serial)
run: |
. /opt/intel/oneapi/setvars.sh
pytest -n=auto --durations=50 python/test/unit/
cd python/test
pytest -n=auto --durations=50 unit/
- name: Run DOLFINx Python unit tests (MPI, np=2)
run: |
. /opt/intel/oneapi/setvars.sh
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/redhat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Upgrade pip and setuptools
run: |
python3 -m pip install --upgrade pip setuptools wheel
- name: Install FEniCS Python components
run: |
python3 -m pip install git+https://github.com/FEniCS/ufl.git
Expand Down Expand Up @@ -61,7 +65,8 @@ jobs:
- name: Build Python interface
run: |
python3 -m pip install git+https://github.com/wjakob/nanobind.git
python3 -m pip install --global-option build --global-option --debug python/
python3 -m pip -v install -r python/build-requirements.txt # TO REMOVE
python3 -m pip -v install --check-build-dependencies --no-build-isolation --config-settings=cmake.build-type=Debug python/
- name: Set default DOLFINx JIT options
run: |
Expand Down
4 changes: 2 additions & 2 deletions cpp/dolfinx/fem/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -1195,8 +1195,8 @@ pack_coefficients(const Expression<T, U>& e,
return {std::move(c), cstride};
}

/// @brief Pack constants of u of generic type U ready for assembly
/// @warning This function is subject to change
/// @brief Pack constants of u into a sigle array ready for assembly.
/// @warning This function is subject to change.
template <typename U>
std::vector<typename U::scalar_type> pack_constants(const U& u)
{
Expand Down
4 changes: 2 additions & 2 deletions docker/Dockerfile.end-user
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ ONBUILD RUN cd dolfinx && \
PETSC_ARCH=linux-gnu-real64-32 cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr/local/dolfinx-real -DCMAKE_BUILD_TYPE=${DOLFINX_CMAKE_BUILD_TYPE} -DCMAKE_CXX_FLAGS=${DOLFINX_CMAKE_CXX_FLAGS} ../cpp && \
ninja install && \
cd ../python && \
CXXFLAGS=${DOLFINX_CMAKE_CXX_FLAGS} PETSC_ARCH=linux-gnu-real64-32 pip3 install -v --target /usr/local/dolfinx-real/lib/python${PYTHON_VERSION}/dist-packages --no-dependencies --no-cache-dir . && \
CXXFLAGS=${DOLFINX_CMAKE_CXX_FLAGS} PETSC_ARCH=linux-gnu-real64-32 pip3 install -v --no-build-isolation --target /usr/local/dolfinx-real/lib/python${PYTHON_VERSION}/dist-packages --no-dependencies --no-cache-dir . && \
git clean -fdx && \
cd ../ && \
mkdir -p build-complex && \
Expand All @@ -99,7 +99,7 @@ ONBUILD RUN cd dolfinx && \
ninja install && \
. /usr/local/dolfinx-complex/lib/dolfinx/dolfinx.conf && \
cd ../python && \
CXXFLAGS=${DOLFINX_CMAKE_CXX_FLAGS} PETSC_ARCH=linux-gnu-complex128-32 pip3 install -v --target /usr/local/dolfinx-complex/lib/python${PYTHON_VERSION}/dist-packages --no-dependencies --no-cache-dir .
CXXFLAGS=${DOLFINX_CMAKE_CXX_FLAGS} PETSC_ARCH=linux-gnu-complex128-32 pip3 install -v --no-build-isolation --target /usr/local/dolfinx-complex/lib/python${PYTHON_VERSION}/dist-packages --no-dependencies --no-cache-dir .

# Real by default.
ONBUILD ENV PKG_CONFIG_PATH=/usr/local/dolfinx-real/lib/pkgconfig:$PKG_CONFIG_PATH \
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.oneapi
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ ENV CC=icx \

# Install Python packages (via pip)
RUN . /opt/intel/oneapi/setvars.sh && \
pip install --no-cache-dir cppimport mpi4py nanobind==${NANOBIND_VERSION} pytest pytest-xdist
pip install --no-cache-dir cppimport matplotlib mpi4py nanobind==${NANOBIND_VERSION} pytest pytest-xdist scikit-build-core[pyproject]

# Install KaHIP
RUN . /opt/intel/oneapi/setvars.sh && \
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.redhat
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ RUN curl -L -O https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-${HDF5_SERIES

# First set of dependencies for building and running Python DOLFINx
# Second set of dependencies for running DOLFINx tests
RUN python3 -m pip install --no-cache-dir cffi numba mpi4py nanobind wheel && \
RUN python3 -m pip install --no-cache-dir cffi numba mpi4py nanobind scikit-build-core[pyproject] wheel && \
python3 -m pip install --no-cache-dir cppimport pytest pytest-xdist scipy matplotlib

# Build PETSc
Expand Down
4 changes: 2 additions & 2 deletions docker/Dockerfile.test-env
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ RUN if [ "$MPI" = "mpich" ]; then \
# - Second set of packages are recommended and/or required to build
# documentation or run tests.
RUN pip3 install --no-cache-dir --upgrade setuptools pip && \
pip3 install --no-cache-dir cffi mpi4py numba numpy==${NUMPY_VERSION} scipy && \
pip3 install --no-cache-dir clang-format cppimport cmakelang flake8 isort jupytext matplotlib mypy myst-parser nanobind==${PYBIND11_VERSION} pytest pytest-xdist sphinx sphinx_rtd_theme
pip3 install -no-cache-dir cffi mpi4py numba numpy==${NUMPY_VERSION} scikit-build-core[pyproject] && \
pip3 install --no-cache-dir breath clang-format cppimport cmakelang flake8 isort jupytext matplotlib mypy myst-parser nanobind==${NANOBIND_VERSION} pytest pytest-xdist scipy sphinx==5.0.2 sphinx_rtd_theme types-setuptools

# Install KaHIP
RUN wget -nc --quiet https://github.com/kahip/kahip/archive/v${KAHIP_VERSION}.tar.gz && \
Expand Down
3 changes: 3 additions & 0 deletions python/.flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
max-line-length = 120
ignore = W503
32 changes: 13 additions & 19 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.18)

project(dolfinx_nanobind)

Expand All @@ -8,22 +8,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# set(CMAKE_BUILD_TYPE Debug)

# Development component which includes both Development.Module and
# Development.Embed is not required for building a Python module. Correct
# COMPONENT specification Development.Module added only in CMake 3.18 and above.
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.18.0")
find_package(
Python3
COMPONENTS Interpreter Development.Module
REQUIRED
)
else()
find_package(
Python3
COMPONENTS Interpreter Development
REQUIRED
)
endif()
find_package(
Python3
COMPONENTS Interpreter Development.Module
REQUIRED
)

execute_process(
COMMAND
Expand All @@ -38,11 +27,12 @@ find_package(nanobind CONFIG REQUIRED)

execute_process(
COMMAND
${Python3_EXECUTABLE} -c "import basix, os, sys; sys.stdout.write(os.path.dirname(basix.__file__))"
${Python3_EXECUTABLE} -c "import os, sys, basix; sys.stdout.write(os.path.dirname(basix.__file__))"
OUTPUT_VARIABLE BASIX_PY_DIR
RESULT_VARIABLE BASIX_PY_COMMAND_RESULT
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE BASIX_ERROR_OUT OUTPUT_STRIP_TRAILING_WHITESPACE
)

find_package(Basix REQUIRED CONFIG HINTS ${BASIX_PY_DIR})

find_package(DOLFINX REQUIRED CONFIG)
Expand Down Expand Up @@ -109,3 +99,7 @@ if(NOT MPI4PY_COMMAND_RESULT)
else()
message(FATAL_ERROR "mpi4py could not be found.")
endif()

set_target_properties(cpp PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)

install(TARGETS cpp DESTINATION dolfinx)
23 changes: 10 additions & 13 deletions python/README.rst
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
DOLFINx Python interface
========================

Building the DOLFINx Python interface uses nanobind.
This document explains how to install the DOLFINx Python interface. Note that
this interface must be built without PEP517 build isolation by passing
`--no-build-isolation` flag to `pip install`. This is because the Python
interface explicitly depends on the system built petsc4py and mpi4py.

1. Install nanobind from source, e.g.::
1. Build and install the DOLFINx C++ library in the usual way.

python3 -m pip install git+https://github.com/wjakob/nanobind.git
2. Ensure the build time requirements are installed::

The FEniCS Docker images are configured with nanobind.

2. Build and install the DOLFINx C++ library in the usual way.
pip install -v -r build-requirements.txt

3. Build DOLFINx Python interface::

pip3 -v install . --user

To install in a local build directory::

python3 setup.py build
pip -v install --check-build-dependencies --no-build-isolation .

and set the ``PYTHONPATH``. To build in debug mode::
To build in debug and editable mode for development::

python3 setup.py build --debug
pip -v install --check-build-dependencies --config-settings=build-dir="build" --config-settings=cmake.build-type="Debug" --no-build-isolation -e .
4 changes: 4 additions & 0 deletions python/build-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nanobind>=1.7.0
scikit-build-core[pyproject]
petsc4py
mpi4py
2 changes: 1 addition & 1 deletion python/demo/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

def pytest_addoption(parser):
parser.addoption("--mpiexec", action="store", default="mpirun",
help="Name of program to run MPI, e.g. mpiexex")
help="Name of program to run MPI, e.g. mpiexec")
parser.addoption("--num-proc", action="store", default=1,
help="Number of MPI processes to use")

Expand Down
48 changes: 48 additions & 0 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# The DOLFINx Python interface must be built without build isolation (PEP517)
# due to its runtime and build time dependency on system built petsc4py and
# mpi4py.
# pip install -r build-requirements.txt
[build-system]
requires = ["scikit-build-core[pyproject]", "nanobind>=1.6.0", "petsc4py", "mpi4py"]
build-backend = "scikit_build_core.build"

[project]
name = "fenics-dolfinx"
version = "0.8.0.dev0"
description = "DOLFINx Python interface"
readme = "../README.md"
requires-python = ">=3.8.0"
license = {file = "../COPYING"}
authors = [{email="fenics-steering-council@googlegroups.com"}, {name="FEniCS Steering Council"}]
packages = ["dolfinx"]
dependencies = ["numpy>=1.21", "cffi", "petsc4py", "mpi4py",
"fenics-ffcx>=0.8.0.dev0,<0.9.0",
"fenics-ufl>=2023.3.0.dev0,<2023.4.0"]

[project.optional-dependencies]
docs = ["markdown", "pylit3", "pyyaml", "sphinx==5.0.2", "sphinx_rtd_theme"]
lint = ["flake8", "pydocstyle"]
optional = ["numba"]
test = ["pytest", "sympy", "scipy", "matplotlib", "fenics-dolfinx[optional]"]
ci = ["mypy", "pytest-xdist", "types-setuptools", "fenics-dolfinx[build]",
"fenics-dolfinx[docs]", "fenics-dolfinx[lint]", "fenics-dolfinx[optional]",
"fenics-dolfinx[test]"]

[tool.scikit-build]
wheel.packages = ["dolfinx"]
sdist.exclude = ["*.cpp"]

[tool.pytest]
junit_family = "xunit2"

[tool.mypy]
# Suggested at https://blog.wolt.com/engineering/2021/09/30/professional-grade-mypy-configuration/
# Goal would be to make all of the below True long-term
disallow_untyped_defs = false
disallow_any_unimported = false
no_implicit_optional = false
check_untyped_defs = false
warn_return_any = false
warn_unused_ignores = false
show_error_codes = true
ignore_missing_imports = true
Loading

0 comments on commit 98596e1

Please sign in to comment.