-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathpyproject.toml
More file actions
190 lines (163 loc) · 9.56 KB
/
pyproject.toml
File metadata and controls
190 lines (163 loc) · 9.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
[build-system]
requires = [
"scikit-build-core>=0.10.0",
"numpy",
"mypy",
"packaging>=24.0"
]
build-backend = "scikit_build_core.build"
[project]
name = "pyopensim"
# Version is dynamically extracted from OpenSim's CMakeLists.txt during build
# Format: <MAJOR>.<MINOR>.<PATCH>.<BUILD> (e.g., 4.5.2.0 or 4.5.2.1)
# Set BUILD_NUMBER env var for Python binding-specific fixes (defaults to 0)
dynamic = ["version"]
description="PyOpenSim: Portable Python bindings for OpenSim"
readme = "README.md"
authors = [ { name = "Senthur Ayyappan", email = "senthurayyappan@umich.edu" } ]
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Physics",
]
dependencies = [
"numpy",
]
[project.optional-dependencies]
test = ["pytest"]
build = ["cibuildwheel"]
[tool.scikit-build]
# Enable experimental features for custom metadata provider plugin
experimental = true
wheel.expand-macos-universal-tags = true
# Don't specify wheel.packages - let CMake handle the installation
# Include stub files in the wheel for PEP 561 compliance
wheel.packages = ["pyopensim", "pyopensim-stubs"]
# Build configuration for faster, more verbose builds
build.verbose = true
logging.level = "INFO"
# Parallel build configuration (adjust based on available cores)
build.tool-args = []
# Dynamic version metadata - extract from OpenSim CMakeLists.txt
# Uses custom hook to support BUILD_NUMBER env var for binding fixes
metadata.version.provider = "pyopensim._build_version"
metadata.version.provider-path = "scripts/python"
[tool.cibuildwheel]
# Target Python versions
build = ["cp310-*", "cp311-*", "cp312-*"]
skip = "*musllinux*"
build-verbosity = 3 # Maximum verbosity to help diagnose issues and prevent timeout detection
# Test configuration
test-command = "pytest {project}/tests"
test-extras = ["test"]
test-skip = ["*universal2:arm64"]
[tool.cibuildwheel.linux]
archs = ["x86_64"]
# Use manylinux_2_28 for broader compatibility while still having modern tooling
manylinux-x86_64-image = "manylinux_2_28"
manylinux-i686-image = "manylinux_2_28"
manylinux-aarch64-image = "manylinux_2_28"
manylinux-ppc64le-image = "manylinux_2_28"
manylinux-s390x-image = "manylinux_2_28"
before-build = """
# Check if OpenSim is already built (from workflow cache)
if [ ! -d "/host$(pwd)/opensim-cache/linux-$(uname -m)/opensim-install" ]; then
echo "=== OpenSim not found in cache, building now ==="
chmod +x scripts/ci/build_opensim.sh
CACHE_DIR="/host$(pwd)/opensim-cache/linux-$(uname -m)"
scripts/ci/build_opensim.sh --platform linux --cache-dir "$CACHE_DIR"
else
echo "=== OpenSim already built in workflow, using cached version ==="
fi
"""
before-test = """
echo "=== Installing OpenBLAS for tests ===" &&
dnf install -y openblas || yum install -y openblas || (apt-get update && apt-get install -y libopenblas0)
"""
environment = { PATH = "/host$(pwd)/opensim-cache/linux-$(uname -m)/cmake/bin:/host$(pwd)/opensim-cache/linux-$(uname -m)/swig/bin:$PATH", OPENSIM_INSTALL_DIR = "/host$(pwd)/opensim-cache/linux-$(uname -m)/opensim-install" }
repair-wheel-command = """
echo "=== Repairing Linux wheel ===" &&
OPENSIM_INSTALL="/host$(pwd)/opensim-cache/linux-$(uname -m)/opensim-install" &&
DEPS_INSTALL="/host$(pwd)/opensim-cache/linux-$(uname -m)/dependencies-install" &&
echo "Library paths for auditwheel:" &&
echo " $OPENSIM_INSTALL/sdk/lib:$OPENSIM_INSTALL/sdk/Simbody/lib64:$OPENSIM_INSTALL/sdk/Simbody/lib:$DEPS_INSTALL/simbody/lib64:$DEPS_INSTALL/simbody/lib:$DEPS_INSTALL/ezc3d/lib64:$DEPS_INSTALL/ezc3d/lib:$DEPS_INSTALL/lib64:$DEPS_INSTALL/lib" &&
LD_LIBRARY_PATH="$OPENSIM_INSTALL/sdk/lib:$OPENSIM_INSTALL/sdk/Simbody/lib64:$OPENSIM_INSTALL/sdk/Simbody/lib:$DEPS_INSTALL/simbody/lib64:$DEPS_INSTALL/simbody/lib:$DEPS_INSTALL/ezc3d/lib64:$DEPS_INSTALL/ezc3d/lib:$DEPS_INSTALL/lib64:$DEPS_INSTALL/lib:$LD_LIBRARY_PATH" auditwheel repair --exclude libSimTKcommon.so.3.8 --exclude libSimTKmath.so.3.8 --exclude libSimTKsimbody.so.3.8 --exclude libopenblas.so.0 -w {dest_dir} {wheel}
"""
[tool.cibuildwheel.macos]
archs = ["universal2"]
before-build = """
echo "=== Building OpenSim for macOS ===" &&
PROJECT_ROOT="$(pwd)" &&
CACHE_DIR="$PROJECT_ROOT/opensim-cache/macos-universal2" &&
OPENSIM_INSTALL="$CACHE_DIR/opensim-install" &&
if [ -d "$OPENSIM_INSTALL" ] && [ -f "$OPENSIM_INSTALL/.build_complete" ]; then
echo "✓ Using cached OpenSim build from $OPENSIM_INSTALL";
else
echo "Building OpenSim from scratch..." &&
echo "=== Installing CMake 3.28.3 to avoid spdlog compatibility issues ===" &&
brew unlink cmake || true &&
curl -L "https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-macos-universal.tar.gz" -o /tmp/cmake.tar.gz &&
sudo tar -xzf /tmp/cmake.tar.gz -C /Applications &&
sudo rm -rf /Applications/CMake.app &&
sudo mv /Applications/cmake-3.28.3-macos-universal/CMake.app /Applications/ &&
sudo ln -sf /Applications/CMake.app/Contents/bin/cmake /usr/local/bin/cmake &&
rm /tmp/cmake.tar.gz &&
cmake --version &&
brew install autoconf automake libtool pkgconfig &&
mkdir -p "$CACHE_DIR" &&
cd "$CACHE_DIR" &&
curl -L https://github.com/swig/swig/archive/v4.1.1.tar.gz | tar xz &&
cd swig-4.1.1 &&
./autogen.sh &&
./configure --prefix="$CACHE_DIR/swig" &&
make -j$(sysctl -n hw.ncpu) &&
make install &&
cd .. &&
rm -rf swig-4.1.1 &&
export PATH="$CACHE_DIR/swig/bin:$PATH" &&
mkdir -p dependencies-build &&
cd dependencies-build &&
cmake "$PROJECT_ROOT/src/opensim-core/dependencies" -DCMAKE_INSTALL_PREFIX="$CACHE_DIR/dependencies-install" -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DSUPERBUILD_ezc3d=ON -DOPENSIM_WITH_CASADI=OFF -DOPENSIM_WITH_TROPTER=OFF -DOPENSIM_WITH_MOCO=OFF &&
cmake --build . --config Release -j$(sysctl -n hw.ncpu) &&
cd .. &&
mkdir -p opensim-build &&
cd opensim-build &&
cmake "$PROJECT_ROOT/src/opensim-core" -DCMAKE_INSTALL_PREFIX="$OPENSIM_INSTALL" -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DOPENSIM_DEPENDENCIES_DIR="$CACHE_DIR/dependencies-install" -DCMAKE_PREFIX_PATH="$CACHE_DIR/dependencies-install" -DBUILD_JAVA_WRAPPING=OFF -DBUILD_PYTHON_WRAPPING=OFF -DBUILD_TESTING=OFF -DBUILD_API_EXAMPLES=OFF -DOPENSIM_C3D_PARSER=ezc3d -DOPENSIM_WITH_CASADI=OFF -DOPENSIM_WITH_TROPTER=OFF -DOPENSIM_WITH_MOCO=OFF -DOPENSIM_INSTALL_UNIX_FHS=OFF -DSWIG_DIR="$CACHE_DIR/swig/share/swig" -DSWIG_EXECUTABLE="$CACHE_DIR/swig/bin/swig" &&
cmake --build . --config Release -j$(sysctl -n hw.ncpu) &&
cmake --install . &&
touch "$OPENSIM_INSTALL/.build_complete" &&
echo "✓ OpenSim build complete";
fi &&
export PATH="$CACHE_DIR/swig/bin:$PATH" &&
export OPENSIM_INSTALL_DIR="$OPENSIM_INSTALL"
"""
environment = { MACOSX_DEPLOYMENT_TARGET = "11.0", CMAKE_OSX_ARCHITECTURES = "x86_64;arm64", OPENSIM_INSTALL_DIR = "$(pwd)/opensim-cache/macos-universal2/opensim-install" }
repair-wheel-command = """
echo "=== Repairing macOS wheel ===" &&
OPENSIM_INSTALL="$(pwd)/opensim-cache/macos-universal2/opensim-install" &&
DYLD_LIBRARY_PATH="$OPENSIM_INSTALL/sdk/lib:$OPENSIM_INSTALL/sdk/Simbody/lib" delocate-wheel -w {dest_dir} -v {wheel}
"""
[tool.cibuildwheel.windows]
archs = ["AMD64"]
# Install delvewheel for Windows wheel repair and consolidate DLLs
before-build = [
"pip install delvewheel",
# Always install SWIG 4.1.1 (required for Python bindings build, even with cached OpenSim)
"powershell -Command \"Write-Host '=== Installing SWIG 4.1.1 ==='; choco install swig --version 4.1.1 --yes --limit-output --allow-downgrade --force; if ($LASTEXITCODE -ne 0) { throw 'Failed to install SWIG 4.1.1' }; $swigCmd = Get-Command swig -ErrorAction SilentlyContinue; if (-not $swigCmd) { throw 'SWIG not found in PATH after installation' }; Write-Host \\\"SWIG installed at: $($swigCmd.Source)\\\"; & swig -version\"",
# Check if OpenSim is built, build if missing
"powershell -Command \"if (-not (Test-Path '{project}/opensim-cache/windows-AMD64/opensim-install')) { Write-Host '=== OpenSim not found in cache, building now ==='; powershell -ExecutionPolicy Bypass -File scripts/ci/build_opensim.ps1 -CacheDir '{project}/opensim-cache/windows-AMD64' -Jobs 4 } else { Write-Host '=== OpenSim already built in workflow, using cached version ===' }\"",
# Consolidate all DLLs into single directory for delvewheel (similar to pyvalhalla approach)
"powershell -Command \"Write-Host '=== Consolidating DLLs to lib/windows ==='; New-Item -ItemType Directory -Force -Path 'lib/windows' | Out-Null; Get-ChildItem -Path '{project}/opensim-cache/windows-AMD64' -Filter '*.dll' -Recurse -ErrorAction SilentlyContinue | Copy-Item -Destination 'lib/windows' -Force; $count = (Get-ChildItem 'lib/windows/*.dll' -ErrorAction SilentlyContinue | Measure-Object).Count; Write-Host \\\"Copied $count DLLs to lib/windows\\\"\""
]
# Don't set OPENSIM_INSTALL_DIR here - it's set by the workflow as an environment variable
# The workflow sets it at line 180 with a path like: D:\a\pyopensim\pyopensim/opensim-cache/...
# CMake detects it via the environment variable check in CMakeLists.txt:126-131
# Setting it here with $(pwd) would create Git Bash paths (/d/a/...) that cause issues
environment = {}
# Use delvewheel to repair the wheel and bundle DLL dependencies
# All DLLs consolidated into lib/windows by before-build (clean approach like pyvalhalla)
repair-wheel-command = "delvewheel repair -w {dest_dir} {wheel} --add-path lib/windows"