Skip to content

Commit 32ac753

Browse files
authored
Merge pull request #4 from virtualcell/3-python-wheels
build python wheels for all platforms
2 parents e4584b9 + 9195935 commit 32ac753

File tree

89 files changed

+1582
-1474
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+1582
-1474
lines changed

.github/workflows/cd.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
name: CD
22

3-
on: [push, workflow_dispatch]
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- master
8+
release:
9+
types:
10+
- published
11+
412

513
env:
614
REGISTRY: ghcr.io

.github/workflows/pip.yml

Lines changed: 146 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ on:
66
push:
77
branches:
88
- master
9+
release:
10+
types:
11+
- published
912

1013
jobs:
1114
build:
@@ -14,9 +17,14 @@ jobs:
1417
strategy:
1518
fail-fast: false
1619
matrix:
17-
platform: [windows-latest, macos-13, macos-14, ubuntu-latest]
18-
# python-version: ["3.7", "3.12", "pypy-3.9"]
19-
python-version: ["3.12"]
20+
#platform: [ windows-latest, macos-13, macos-14, ubuntu-latest ]
21+
platform: [ macos-13, macos-14, ubuntu-latest ]
22+
python-version: ["3.9","3.10","3.11","3.12"]
23+
# exclude:
24+
# - platform: windows-latest
25+
# python-version: "3.9"
26+
# - platform: windows-latest
27+
# python-version: "3.12"
2028

2129
steps:
2230
- uses: actions/checkout@v4
@@ -79,49 +87,94 @@ jobs:
7987
mingw-w64-clang-x86_64-libaec
8088
mingw-w64-clang-x86_64-python-pip-tools
8189
82-
83-
- name: Install Linux Dependencies
84-
if: matrix.platform == 'ubuntu-latest'
85-
run: |
86-
sudo apt-get update
87-
sudo apt-get install -y libboost-all-dev
88-
sudo apt-get install -y libhdf5-dev
89-
sudo apt-get install -y ninja-build
90-
91-
gcc --version
92-
gfortran --version
93-
cmake --version
94-
dpkg -s libboost-all-dev
95-
dpkg -s libhdf5-dev
96-
97-
9890
- uses: actions/setup-python@v5
9991
with:
10092
python-version: "${{ matrix.python-version }}"
10193

10294
- name: Build and install macos-13
10395
run: |
96+
export MACOSX_DEPLOYMENT_TARGET=13.0
10497
PATH="/usr/local/opt/llvm/bin:$PATH"
105-
pip install --verbose .
98+
pip wheel . -w dist
99+
ls -al dist
100+
pip install delocate
101+
delocate-listdeps dist/*.whl
102+
delocate-wheel -v dist/*.whl
103+
pip install dist/*.whl
106104
if: matrix.platform == 'macos-13'
107105

108106
- name: Build and install macos-14
109107
run: |
110108
PATH="/opt/homebrew/opt/llvm/bin:$PATH"
111-
pip install --verbose .
109+
pip wheel . -w dist
110+
ls -al dist
111+
pip install delocate
112+
delocate-listdeps dist/*.whl
113+
delocate-wheel -v dist/*.whl
114+
pip install dist/*.whl
112115
if: matrix.platform == 'macos-14'
113116

114117
- name: Build and install windows-latest
115118
shell: msys2 {0}
116119
run: |
117-
pip install --verbose -Ccmake.define.CMAKE_C_COMPILER="clang.exe" -Ccmake.define.CMAKE_CXX_COMPILER="clang++.exe" .
120+
pip wheel --verbose -Ccmake.define.CMAKE_C_COMPILER="clang.exe" -Ccmake.define.CMAKE_CXX_COMPILER="clang++.exe" . -w dist
121+
pip install delvewheel
122+
for wheel_file in dist/*.whl; do
123+
echo "not inspecting $wheel_file"
124+
echo "delvewheel needed -v $wheel_file"
125+
echo "not repairing $wheel_file"
126+
echo "delvewheel repair -v $wheel_file"
127+
done
128+
pip install dist/*.whl
118129
if: matrix.platform == 'windows-latest'
119130

120-
- name: Build and install ubuntu-latest
131+
- name: Build and install manylinux for python 3.9
132+
run: |
133+
docker run --rm -v $(pwd):/io quay.io/pypa/manylinux2014_x86_64 \
134+
/bin/bash -c \
135+
"yum install -y boost-devel hdf5-devel ninja-build && \
136+
/opt/python/cp39-cp39/bin/pip wheel /io/ -w /io/dist && \
137+
auditwheel repair /io/dist/*.whl -w /io/dist/"
138+
echo "keeping only the manylinux wheels, remove those with -linux_x86_64.whl in the name"
139+
sudo rm -rf dist/*-linux_x86_64.whl
140+
pip install dist/*.whl
141+
if: matrix.platform == 'ubuntu-latest' && matrix.python-version == '3.9'
142+
143+
- name: Build and install manylinux for python 3.10
144+
run: |
145+
docker run --rm -v $(pwd):/io quay.io/pypa/manylinux2014_x86_64 \
146+
/bin/bash -c \
147+
"yum install -y boost-devel hdf5-devel ninja-build && \
148+
/opt/python/cp310-cp310/bin/pip wheel /io/ -w /io/dist && \
149+
auditwheel repair /io/dist/*.whl -w /io/dist/"
150+
echo "keeping only the manylinux wheels, remove those with -linux_x86_64.whl in the name"
151+
sudo rm -rf dist/*-linux_x86_64.whl
152+
pip install dist/*.whl
153+
if: matrix.platform == 'ubuntu-latest' && matrix.python-version == '3.10'
154+
155+
- name: Build and install manylinux for python 3.11
156+
run: |
157+
docker run --rm -v $(pwd):/io quay.io/pypa/manylinux2014_x86_64 \
158+
/bin/bash -c \
159+
"yum install -y boost-devel hdf5-devel ninja-build && \
160+
/opt/python/cp311-cp311/bin/pip wheel /io/ -w /io/dist && \
161+
auditwheel repair /io/dist/*.whl -w /io/dist/"
162+
echo "keeping only the manylinux wheels, remove those with -linux_x86_64.whl in the name"
163+
sudo rm -rf dist/*-linux_x86_64.whl
164+
pip install dist/*.whl
165+
if: matrix.platform == 'ubuntu-latest' && matrix.python-version == '3.11'
166+
167+
- name: Build and install manylinux for python 3.12
121168
run: |
122-
platform=linux
123-
pip install --verbose .
124-
if: matrix.platform == 'ubuntu-latest'
169+
docker run --rm -v $(pwd):/io quay.io/pypa/manylinux2014_x86_64 \
170+
/bin/bash -c \
171+
"yum install -y boost-devel hdf5-devel ninja-build && \
172+
/opt/python/cp312-cp312/bin/pip wheel /io/ -w /io/dist && \
173+
auditwheel repair /io/dist/*.whl -w /io/dist/"
174+
echo "keeping only the manylinux wheels, remove those with -linux_x86_64.whl in the name"
175+
sudo rm -rf dist/*-linux_x86_64.whl
176+
pip install dist/*.whl
177+
if: matrix.platform == 'ubuntu-latest' && matrix.python-version == '3.12'
125178

126179
- name: Test not windows
127180
run: |
@@ -136,8 +189,75 @@ jobs:
136189
pytest
137190
if: matrix.platform == 'windows-latest'
138191

192+
- name: set wheel_file and artifact_name environment vars (non-windows)
193+
if: matrix.platform != 'windows-latest'
194+
run: |
195+
for wheel_file in dist/*.whl; do
196+
echo "Uploading $wheel_file"
197+
echo "wheel_file=$wheel_file" >> $GITHUB_ENV
198+
echo "artifact_name=$(basename $wheel_file)" >> $GITHUB_ENV
199+
done
200+
201+
- name: set wheel_file and artifact_name environment vars (windows)
202+
if: matrix.platform == 'windows-latest'
203+
shell: pwsh
204+
run: |
205+
foreach ($wheel_file in Get-ChildItem -Path dist -Filter *.whl) {
206+
Write-Output "Uploading $wheel_file"
207+
echo "wheel_file=$wheel_file" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8
208+
echo "artifact_name=$(Split-Path $wheel_file -Leaf)" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8
209+
}
210+
211+
- name: Upload wheel file
212+
uses: actions/upload-artifact@v4
213+
with:
214+
name: ${{ env.artifact_name }}
215+
path: ${{ env.wheel_file }}
216+
139217
- name: Setup tmate session
140218
uses: mxschmitt/action-tmate@v3
141219
if: ${{ failure() }}
142220
with:
143221
github-token: ${{ secrets.GITHUB_TOKEN }}
222+
223+
publish-to-pypi:
224+
name: Publish to PyPI
225+
needs: build
226+
runs-on: ubuntu-latest
227+
if: github.event_name == 'release' && github.event.action == 'published'
228+
environment: pypi
229+
permissions:
230+
id-token: write
231+
232+
steps:
233+
- name: download all artifacts (wheels and executables)
234+
uses: actions/download-artifact@v4
235+
with:
236+
path: dist_temp/
237+
238+
- name: Install Python
239+
uses: actions/setup-python@v2
240+
with:
241+
python-version: '3.12'
242+
243+
- name: Publish wheels to PyPI
244+
env:
245+
TWINE_USERNAME: __token__
246+
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
247+
run: |
248+
pip install twine
249+
mkdir dist
250+
echo "current directory is $(pwd)"
251+
ls -al dist*
252+
echo "absolute paths of wheels:"
253+
find dist_temp -type f -name '*.whl' -exec sh -c 'echo "$(realpath {})"/' \;
254+
echo "moving wheels to dist directory"
255+
find dist_temp -type f -name '*.whl' -exec sh -c 'mv "$(realpath {})" dist/' \;
256+
twine upload --repository pypi dist/*.whl
257+
258+
- name: Setup tmate session for PyPI upload failure
259+
uses: mxschmitt/action-tmate@v3
260+
if: ${{ failure() }}
261+
with:
262+
github-token: ${{ secrets.GITHUB_TOKEN }}
263+

.github/workflows/wheels.yml

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Wheels
1+
name: "Wheels"
22

33
on:
44
workflow_dispatch:
@@ -107,7 +107,7 @@ jobs:
107107
mingw-w64-clang-x86_64-libzip
108108
mingw-w64-clang-x86_64-zlib
109109
mingw-w64-clang-x86_64-libaec
110-
110+
mingw-w64-clang-x86_64-python-pip-tools
111111
112112
- name: Install Linux Dependencies
113113
if: matrix.os == 'ubuntu-latest'
@@ -123,9 +123,40 @@ jobs:
123123
dpkg -s libboost-all-dev
124124
dpkg -s libhdf5-dev
125125
126+
# Used to host cibuildwheel
127+
- uses: actions/setup-python@v5
128+
129+
- name: Install cibuildwheel
130+
run: python -m pip install cibuildwheel==2.18.1
131+
132+
- name: build wheel on macos-13
133+
if: matrix.os == 'macos-13'
134+
run: |
135+
export PATH="/usr/local/opt/llvm/bin:$PATH"
136+
python -m cibuildwheel --output-dir wheelhouse
137+
env:
138+
CIBW_ARCHS: native
139+
140+
- name: build wheel on macos-14
141+
if: matrix.os == 'macos-14'
142+
run: |
143+
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
144+
python -m cibuildwheel --output-dir wheelhouse
145+
env:
146+
CIBW_ARCHS: native
147+
148+
- name: build wheel on windows-latest
149+
if: matrix.os == 'windows-latest'
150+
shell: msys2 {0}
151+
run: |
152+
python -m cibuildwheel --output-dir wheelhouse
153+
env:
154+
CIBW_ARCHS: native
126155

127156
- name: build wheel
128-
uses: pypa/cibuildwheel@v2.17
157+
if: matrix.os == 'ubuntu-latest'
158+
run: |
159+
python -m cibuildwheel --output-dir wheelhouse
129160
env:
130161
CIBW_ARCHS: native
131162

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,12 @@
1717
/.idea/
1818
/nfsim/
1919
/all_solvers/*
20+
/.venv/
21+
/venv/
2022

2123
.DS_Store
24+
/dist/
25+
26+
tests/__pycache__/
27+
28+
*.whl

CMakeLists.txt

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ option(OPTION_TARGET_PYTHON_BINDING "build Python bindings" ON)
33
option(OPTION_TARGET_MESSAGING "Messaging (requires libcurl)" off)
44
option(OPTION_TARGET_DOCS "Generate Doxygen documentation" off)
55
option(OPTION_TARGET_FV_SOLVER on)
6+
option(OPTION_TARGET_TESTS "Build tests" off)
67
option(OPTION_VCELL "Compile Smoldyn for VCell" ON)
78
option(OPTION_NSV "Compile Smoldyn with NextSubvolume functionality" OFF)
89
option(OPTION_USE_OPENGL "Build with OpenGL support" OFF)
@@ -217,7 +218,7 @@ if (OPTION_TARGET_PYTHON_BINDING)
217218
find_package(pybind11 CONFIG REQUIRED)
218219

219220
# Add a library using FindPython's tooling (pybind11 also provides a helper like this)
220-
python_add_library(_core MODULE src/main.cpp src/SolverMain.cpp src/SolverMain.h WITH_SOABI)
221+
python_add_library(_core MODULE src/main.cpp WITH_SOABI)
221222
target_link_libraries(_core PRIVATE vcell pybind11::headers)
222223

223224
# This is passing in the version as a define just as an example
@@ -226,35 +227,4 @@ if (OPTION_TARGET_PYTHON_BINDING)
226227
# The install directory is the output (wheel) directory
227228
install(TARGETS _core DESTINATION pyvcell_fvsolver)
228229

229-
else(OPTION_TARGET_PYTHON_BINDING)
230-
231-
include(FetchContent)
232-
FetchContent_Declare(
233-
googletest
234-
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
235-
)
236-
if (WINDOWS)
237-
# For Windows: Prevent overriding the parent project's compiler/linker settings
238-
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
239-
endif()
240-
241-
FetchContent_MakeAvailable(googletest)
242-
enable_testing()
243-
244-
get_cmake_property(_variableNames VARIABLES)
245-
list (SORT _variableNames)
246-
foreach (_variableName ${_variableNames})
247-
message(STATUS "${_variableName}=${${_variableName}}")
248-
endforeach()
249-
250-
include(CMakePrintHelpers)
251-
cmake_print_variables(OPTION_TARGET_MESSAGING
252-
OPTION_TARGET_DOCS
253-
OPTION_TARGET_FV_SOLVER
254-
OPTION_TARGET_LIBSMOLDYN OPTION_TARGET_VCELL OPTION_TARGET_NSV )
255-
cmake_print_variables(CMAKE_CXX_FLAGS CMAKE_C_FLAGS CMAKE_Fortran_FLAGS)
256-
cmake_print_variables(CMAKE_SYSTEM_NAME WINDOWS WIN32 MINGW APPLE ARCH_64bit ARCH_32bit)
257-
cmake_print_variables(CMAKE_CPP_COMPILER CMAKE_C_COMPILER CMAKE_CXX_COMPILER CMAKE_Fortran_COMPILER)
258-
cmake_print_variables(HAVE_ZLIB)
259-
260230
endif (OPTION_TARGET_PYTHON_BINDING)

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
![CI](https://github.com/virtualcell/vcell-solvers/actions/workflows/cd.yml/badge.svg)
99

1010
# vcell-fvsolver
11-
Virtual Cell solvers [virtualcell/vcell-solvers](https://github.com/virtualcell/vcell-solvers) is a collection of numerical simulation codes used in the Virtual Cell framework [virtualcell/vcell](https://github.com/virtualcell/vcell)).
11+
Virtual Cell Finite Volume solver [virtualcell/vcell-fvsolver](https://github.com/virtualcell/vcell-fvsolver)
12+
is a reaction-diffusion-advection PDE solver for computational cell biology.
13+
This solver is used within the Virtual Cell modeling and simulation application [virtualcell/vcell](https://github.com/virtualcell/vcell)
14+
and as a component in the Virtual Cell Python API [virtualcell/pyvcell](https://github.com/virtualcell/pyvcell) (coming soon).
1215

13-
1416
## The Virtual Cell Project
1517
The Virtual Cell is a modeling and simulation framework for computational biology. For details see http://vcell.org and http://github.com/virtualcell.
1618

@@ -27,4 +29,4 @@ and generates the output files (.log, .zip, .mesh, .meshmetrics, .hdf5). The
2729
.functions file is not used by the solver, but is helpful for interpreting the
2830
results in the context of the original model.
2931

30-
This package is intented to be used by the Virtual Cell Python API, pyvcell (coming soon).
32+
This package is intended to be used by the Virtual Cell Python API [virtualcell/pyvcell](https://github.com/virtualcell/pyvcell) (coming soon).

0 commit comments

Comments
 (0)