Skip to content

Commit b7ecdef

Browse files
Experimental binary wheel builder (#4042)
* Try wheel build. * Fix. * Fix. * Fix. * Fix. * Extra repos. * Load mpich module * Source profile to get module * Update image to get newer boost. * Use distro cmake for initial build * No messing with Boost. * Use system cmake (missed one) * Pin versions. * Fix directories * Fix. * Back to build * Disable build isolation and install build deps. * Small tweaks. * Install build deps from normal pypa. * The way RedHat sets up HDF5 is a bit tricky. * Works locally. * Add FFCx and UFL back. * Pin versions. * Fix? * Fix. * To main * Updates for 0.11.dev0 * Try latest Python * Install ptscotch * Try adding SCOTCH DIRs manually - surely there is a way to get this done automatically? * Add devel. * Build SCOTCH from source * Fix. * Fix. * scotch build shared libs * Don't install crappy system cmake. * Try using build not pip * Try in proper directory * Switch to Development.Module * Try pip again * Attempt to fix simple503 repo * Change order. * Fix paths * Hints for MPI and HDF5 * Add lower bound on SCOTCH version - earlier versions do not have config mode. * Fix syntax. * Remove FATAL_ERROR * Exclude shared objects related to MPI * Fix duplicate fix wheel * Try 3.12 ABI wheel * Don't remove libsz * Remove hdf5-devel from package installation * Tweak options being passed up to cmake via scikit-build-core * Re-enable MPI check. * Disable again. * Update build-wheels.yml * Add HDF5_INCLUDE_DIRS to cmake arguments * Tested interactively - need HDF5_C_INCLUDE_DIR (!) * Add check back in * Hack to get includes in right place * Tidy up * Try on ARM * Fixes * Fix syntax * Use native build type * Install ninja * Tweak. * Fix ninja-build * Fix basix wheel build * Fix. * Fixes and isolate to Linux. * Change clashing artifact names * Enable debug symbols * Full debug build * Run tests and demos * Precise path * Use the wheel-built MPICH * Wrap both calls in mpiexec * Seems unnecessary, only transitive through libmpi * Reformat some lines and skip failing tests * Fix linebreaks * Fix linebreak * Fix for rank 1 * Use system MPI - would probably be good to test in a range of other containers. * Update build-wheels.yml * Add demo optional dependency group * Run tests in clean image * Skip demos. * Remove test extra * Fix. * Add networkx to demo dep set * Intel MPI only on x86-64 * Cleanup using sudo - docker user is root --------- Co-authored-by: Chris Richardson <chris@bpi.cam.ac.uk>
1 parent a3260ce commit b7ecdef

5 files changed

Lines changed: 110 additions & 84 deletions

File tree

.github/workflows/build-wheels.yml

Lines changed: 95 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
inputs:
99
dolfinx_ref:
1010
description: "dolfinx git ref to checkout"
11-
default: ""
11+
default: "main"
1212
type: string
1313

1414
build_fenicsx_stack:
@@ -18,24 +18,24 @@ on:
1818

1919
basix_ref:
2020
description: "basix git ref to checkout"
21-
default: ""
21+
default: "main"
2222
type: string
2323

2424
ufl_ref:
2525
description: "ufl git ref to checkout"
26-
default: ""
26+
default: "main"
2727
type: string
2828

2929
ffcx_ref:
3030
description: "ffcx git ref to checkout"
31-
default: ""
31+
default: "main"
3232
type: string
3333

3434
workflow_call:
3535
inputs:
3636
dolfinx_ref:
3737
description: "dolfinx git ref to checkout"
38-
default: ""
38+
default: "main"
3939
type: string
4040

4141
build_fenicsx_stack:
@@ -45,51 +45,40 @@ on:
4545

4646
basix_ref:
4747
description: "basix git ref to checkout"
48-
default: ""
48+
default: "main"
4949
type: string
5050

5151
ufl_ref:
5252
description: "ufl git ref to checkout"
53-
default: ""
53+
default: "main"
5454
type: string
5555

5656
ffcx_ref:
5757
description: "ffcx git ref to checkout"
58-
default: ""
58+
default: "main"
5959
type: string
6060

6161
jobs:
6262
build_wheels:
6363
name: Build wheels
64-
runs-on: ubuntu-latest
64+
runs-on: ${{ matrix.os }}
65+
strategy:
66+
matrix:
67+
os: [ubuntu-latest, ubuntu-24.04-arm]
6568

6669
env:
67-
MPI4PY_VERSION: 3.1.2
68-
PETSC4PY_VERSION: 3.16.1
69-
CIBW_MANYLINUX_X86_64_IMAGE: docker.io/fenicsproject/wheelbuilder_x86_64:latest
70-
CIBW_BUILD: cp37-manylinux_x86_64 cp38-manylinux_x86_64 cp39-manylinux_x86_64
70+
CIBW_BUILD: cp312-manylinux_x86_64 cp312-manylinux_aarch64
7171
CIBW_BUILD_VERBOSITY: 1
72-
CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=file:///project/simple PETSC_DIR=/usr/local MAKEFLAGS=-j2
72+
CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=file:///project/simple
73+
CIBW_ARCHS_LINUX: native
74+
CIBW_MANYLINUX_X86_64_IMAGE: quay.io/pypa/manylinux_2_34_x86_64:latest
75+
CIBW_MANYLINUX_AARCH64_IMAGE: quay.io/pypa/manylinux_2_34_aarch64:latest
7376

7477
steps:
7578
- uses: actions/setup-python@v6
7679

7780
- name: Install Python dependencies
78-
run: python -m pip install cibuildwheel simple503 wheel
79-
80-
- name: Checkout Basix
81-
if: ${{ github.event.inputs.build_fenicsx_stack == 'true' }}
82-
uses: actions/checkout@v6
83-
with:
84-
repository: FEniCS/basix
85-
path: basix
86-
ref: ${{ github.event.inputs.basix_ref }}
87-
88-
- name: Build Basix wheel
89-
if: ${{ github.event.inputs.build_fenicsx_stack == 'true' }}
90-
run: |
91-
cd basix
92-
python -m cibuildwheel --output-dir ../wheelhouse .
81+
run: python -m pip install cibuildwheel simple503 build
9382

9483
- name: Checkout UFL
9584
if: ${{ github.event.inputs.build_fenicsx_stack == 'true' }}
@@ -101,7 +90,8 @@ jobs:
10190

10291
- name: Build UFL wheel
10392
if: ${{ github.event.inputs.build_fenicsx_stack == 'true' }}
104-
run: python -m pip wheel --no-deps -w wheelhouse ./ufl
93+
run: |
94+
python -m build -o wheelhouse/ ufl/
10595
10696
- name: Checkout FFCx
10797
if: ${{ github.event.inputs.build_fenicsx_stack == 'true' }}
@@ -113,38 +103,28 @@ jobs:
113103

114104
- name: Build FFCx wheel
115105
if: ${{ github.event.inputs.build_fenicsx_stack == 'true' }}
116-
run: python -m pip wheel --no-deps -w wheelhouse ./ffcx
117-
118-
- name: Download mpi4py
119106
run: |
120-
curl -L -O https://github.com/mpi4py/mpi4py/releases/download/${MPI4PY_VERSION}/mpi4py-${MPI4PY_VERSION}.tar.gz
121-
mkdir -p mpi4py
122-
tar -xf mpi4py-${MPI4PY_VERSION}.tar.gz -C mpi4py --strip-components 1
107+
python -m build -o wheelhouse/ ffcx/
108+
109+
- name: Checkout Basix
110+
if: ${{ github.event.inputs.build_fenicsx_stack == 'true' }}
111+
uses: actions/checkout@v6
112+
with:
113+
repository: FEniCS/basix
114+
path: basix
115+
ref: ${{ github.event.inputs.basix_ref }}
123116

124-
- name: Build mpi4py wheels
125-
run: python -m cibuildwheel --output-dir wheelhouse mpi4py
117+
- name: Build Basix wheel
118+
if: ${{ github.event.inputs.build_fenicsx_stack == 'true' }}
119+
working-directory: basix/
120+
run: |
121+
python -m cibuildwheel --output-dir ../wheelhouse/ .
126122
127123
- name: Make temporary simple503 repository
128124
run: |
129125
mkdir -p simple
130126
cp wheelhouse/* simple/
131-
python -m simple503 --base-url file:///project/simple simple
132-
133-
- name: Download petsc4py
134-
run: |
135-
curl -L -O https://pypi.io/packages/source/p/petsc4py/petsc4py-${PETSC4PY_VERSION}.tar.gz
136-
mkdir -p petsc4py
137-
tar -xf petsc4py-${PETSC4PY_VERSION}.tar.gz -C petsc4py --strip-components 1
138-
139-
- name: Build petsc4py wheels
140-
run: python -m cibuildwheel --output-dir wheelhouse petsc4py
141-
env:
142-
CIBW_BEFORE_BUILD: python -m pip install numpy # Not specified correctly in petsc4py
143-
144-
- name: Update temporary simple503 repository
145-
run: |
146-
cp wheelhouse/* simple/
147-
python -m simple503 --base-url file:///project/simple simple
127+
python -m simple503 --base-url file:///project/simple simple/
148128
149129
- name: Checkout DOLFINx
150130
uses: actions/checkout@v6
@@ -155,50 +135,88 @@ jobs:
155135
# fenics-ffcx and fenics-basix are required by DOLFINx C++ build
156136
# mpi4py and petsc4py are build_requirements of DOLFINx Python
157137
- name: Build DOLFINx wheel
158-
run: python -m cibuildwheel --output-dir wheelhouse dolfinx/python
138+
run: |
139+
python -m cibuildwheel --output-dir wheelhouse/ dolfinx/python
159140
env:
160-
CIBW_BEFORE_BUILD: python -m pip -v install --prefer-binary fenics-ffcx fenics-basix && python -m pip -v install --prefer-binary petsc4py mpi4py && cmake -S dolfinx/cpp -B build-dir -DPython3_EXECUTABLE=$(which python) && cmake --build build-dir && cmake --install build-dir
161-
CIBW_REPAIR_WHEEL_COMMAND_LINUX: export LD_LIBRARY_PATH=$(python -c "import site; print(site.getsitepackages()[0] + '/fenics_basix.libs')") && auditwheel repair -w {dest_dir} {wheel}
141+
CIBW_BEFORE_BUILD_LINUX: >
142+
dnf -y update &&
143+
dnf install -y dnf-plugins-core &&
144+
dnf install -y epel-release &&
145+
/usr/bin/crb enable &&
146+
dnf -y update &&
147+
dnf -y install boost-devel boost-program-options git hdf5-mpich-devel make \
148+
mpich-devel ninja-build openblas-devel pugixml-devel spdlog-devel &&
149+
ln -s /usr/include/mpich-$(arch) /usr/lib64/mpich/include &&
150+
git clone --branch v7.0.9 --single-branch https://gitlab.inria.fr/scotch/scotch.git &&
151+
cmake -G Ninja -S scotch/ -B scotch-build-dir/ -DCMAKE_INSTALL_PREFIX=/usr/local \
152+
-DBUILD_SHARED_LIBS=ON -DMPI_HOME=/usr/lib64/mpich &&
153+
cmake --build scotch-build-dir/ &&
154+
cmake --install scotch-build-dir/ &&
155+
pip -v install 'fenics-basix==0.11.0.dev0' 'fenics-ffcx==0.11.0.dev0' &&
156+
pip -v install mpi4py scikit-build-core[pyproject] nanobind &&
157+
cmake -G Ninja -S dolfinx/cpp -B dolfinx-build-dir/ -DPython3_EXECUTABLE=$(which python) \
158+
-DHDF5_ROOT=/usr/lib64/mpich -DMPI_HOME=/usr/lib64/mpich -DCMAKE_BUILD_TYPE=RelWithDebug &&
159+
cmake --build dolfinx-build-dir/ &&
160+
cmake --install dolfinx-build-dir/
161+
CIBW_CONFIG_SETTINGS_LINUX: >
162+
cmake.args="-DMPI_HOME=/usr/lib64/mpich;-DHDF5_ROOT=/usr/lib64/mpich"
163+
wheel.py-api=cp312
164+
cmake.build-type="RelWithDebug"
165+
CIBW_BUILD_FRONTEND: "build; args: -nx"
166+
CIBW_REPAIR_WHEEL_COMMAND_LINUX: >
167+
export LD_LIBRARY_PATH=$(python -c "import site; print(site.getsitepackages()[0] + '/fenics_basix.libs')"):${LD_LIBRARY_PATH} &&
168+
auditwheel repair --exclude libmpi.so.* -w {dest_dir} {wheel} &&
169+
pipx run abi3audit --verbose --strict --report {wheel}
170+
CIBW_TEST_REQUIRES: pytest-xdist
171+
CIBW_TEST_EXTRAS: test
172+
CIBW_TEST_COMMAND: >
173+
. /etc/profile &&
174+
module load mpi/mpich-$(arch) &&
175+
python -m pytest -n auto \
176+
-m "not adios2 and not petsc4py" {project}/dolfinx/python/test/unit &&
177+
mpiexec -n 2 python -m pytest \
178+
-m "not adios2 and not petsc4py" {project}/dolfinx/python/test/unit
162179
163180
- name: Update temporary simple503 repository
164181
run: |
165182
cp wheelhouse/* simple
166183
python -m simple503 --base-url file:///shared simple
167184
168-
# Artifact can be unzipped into $(pwd) and tested with e.g.:
169-
# docker run -ti -v $(pwd):/shared --env PIP_EXTRA_INDEX_URL=file:///shared python:3.9 /bin/bash -l
170185
- name: Upload simple503-test artifact
171186
uses: actions/upload-artifact@v6
172187
with:
173-
name: "simple503-test"
188+
name: simple503-test-${{ matrix.os }}
174189
path: simple/*
175190

191+
- name: Test in clean python image with pypi MPICH
192+
run: >
193+
cd dolfinx &&
194+
sudo git clean -fdx && cd ../ &&
195+
docker run -v $(pwd)/dolfinx:/dolfinx -v $(pwd)/simple:/shared \
196+
--env PIP_EXTRA_INDEX_URL=file:///shared python:3.13 \
197+
/bin/bash -l -c "pip install mpich fenics-dolfinx[test] && mpiexec -n 2 python -m pytest -m 'not adios2 and not petsc4py' /dolfinx/python/test/unit"
198+
199+
- name: Test in clean python image with pypi Intel MPI (x86_64 only)
200+
if: runner.arch == 'X64'
201+
run: >
202+
cd dolfinx &&
203+
sudo git clean -fdx && cd ../ &&
204+
docker run -v $(pwd)/dolfinx:/dolfinx -v $(pwd)/simple:/shared \
205+
--env PIP_EXTRA_INDEX_URL=file:///shared python:3.14 \
206+
/bin/bash -l -c "pip install impi-rt fenics-dolfinx[test] && mpiexec -n 2 python -m pytest -m 'not adios2 and not petsc4py' /dolfinx/python/test/unit"
207+
176208
- name: Upload wheelhouse artifact
177209
uses: actions/upload-artifact@v6
178210
with:
179-
name: wheelhouse
211+
name: wheelhouse-${{ matrix.os }}
180212
path: wheelhouse/*
181213

182214
- name: Update FEniCS Project simple503 repository
183215
run: |
184216
python -m simple503 --base-url http://packages.fenicsproject.org/simple simple
185217
186-
# For manual upload.
187218
- name: Upload simple503 artifact
188219
uses: actions/upload-artifact@v6
189220
with:
190-
name: "simple503"
221+
name: simple503-${{ matrix.os }}
191222
path: simple/*
192-
193-
# Extract mpiexec from docker image
194-
- name: Extract mpiexec.hydra from Docker image
195-
run: |
196-
export CONTAINER_ID=$(docker create ${CIBW_MANYLINUX_X86_64_IMAGE})
197-
docker cp ${CONTAINER_ID}:/usr/local/bin/mpiexec.hydra mpiexec.hydra
198-
docker rm ${CONTAINER_ID}
199-
200-
- name: Upload mpiexec artifact
201-
uses: actions/upload-artifact@v6
202-
with:
203-
name: "mpiexec.hydra"
204-
path: mpiexec.hydra

cpp/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,10 +439,11 @@ elseif(_REQUIRE_SLEPC AND NOT PETSC_FOUND)
439439
message(FATAL_ERROR "SLEPc requested, but no configured because PETSc was not found.")
440440
endif()
441441

442+
# SCOTCH 7.0.1 was first version with ScotchConfig.cmake
442443
if(DOLFINX_ENABLE_SCOTCH AND _REQUIRE_SCOTCH)
443-
find_package(SCOTCH REQUIRED CONFIG)
444+
find_package(SCOTCH 7.0.1 REQUIRED CONFIG)
444445
elseif(DOLFINX_ENABLE_SCOTCH)
445-
find_package(SCOTCH CONFIG)
446+
find_package(SCOTCH 7.0.1 CONFIG)
446447
endif()
447448

448449
if(TARGET SCOTCH::scotch AND NOT TARGET SCOTCH::ptscotch)

cpp/cmake/templates/DOLFINXConfig.cmake.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ if(@SLEPC_FOUND@)
9999
endif()
100100

101101
if(@ADIOS2_FOUND@)
102-
find_dependency(ADIOS2 2.8.1 COMPONENTS CXX)
102+
find_dependency(ADIOS2 2.8.1 COMPONENTS CXX MPI)
103103
endif()
104104

105105
if(NOT TARGET dolfinx)

python/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ endif(WIN32)
1010

1111
find_package(
1212
Python
13-
COMPONENTS Interpreter Development ${SKBUILD_SABI_COMPONENT}
13+
COMPONENTS Interpreter Development.Module ${SKBUILD_SABI_COMPONENT}
1414
REQUIRED
1515
)
1616

python/pyproject.toml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,26 @@ dependencies = [
2828
]
2929

3030
[project.optional-dependencies]
31+
demo = [
32+
"gmsh",
33+
"networkx",
34+
"numba",
35+
"matplotlib",
36+
"scipy",
37+
"pyamg",
38+
"pyvista",
39+
]
3140
docs = [
3241
"breathe",
3342
"jupytext",
3443
"markdown",
35-
"matplotlib",
3644
"myst_parser",
37-
"numba",
38-
"scipy",
3945
"packaging",
4046
"pyyaml",
4147
"sphinx",
4248
"sphinx_rtd_theme",
4349
"sphinx_codeautolink[ipython]",
50+
"fenics-dolfinx[demo]",
4451
]
4552
lint = ["ruff>=0.2.0"]
4653
optional = ["numba", "pyamg"]

0 commit comments

Comments
 (0)