Skip to content

Commit d70ca8c

Browse files
committed
Fix CI: simplify workflow, fix Ubuntu/macOS test failures
- Build once per OS (not OS x python-version) since cibuildwheel handles all Python versions internally - Remove rigid wheel-suffix matching (used exact manylinux tag that may not match actual output); use flexible cp{ver}-*.whl glob - Fix macOS OMP duplicate library error: set KMP_DUPLICATE_LIB_OK=TRUE - Remove inspect steps that failed on missing wheels - Artifact names simplified: wheels-{os} instead of wheels-{os}-{pyver}
1 parent d3a3a75 commit d70ca8c

1 file changed

Lines changed: 37 additions & 87 deletions

File tree

.github/workflows/build_wheels.yml

Lines changed: 37 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,14 @@ jobs:
2222
steps:
2323
- uses: actions/checkout@v4
2424
with:
25-
fetch-depth: 0 # This ensures all tags are fetched
25+
fetch-depth: 0
2626

2727
- id: check
2828
run: |
29-
# Check if this is a tag push
3029
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
3130
echo "is_tag=true" >> $GITHUB_OUTPUT
3231
echo "should_run=true" >> $GITHUB_OUTPUT
33-
# Check if this is a branch push that's not associated with a tag creation
3432
elif [[ "${{ github.ref }}" == refs/heads/* ]] && [[ "${{ github.event_name }}" == "push" ]]; then
35-
# If this commit has a tag pointing to it, skip branch-based run
3633
if git tag --points-at HEAD | grep -q "^v"; then
3734
echo "should_run=false" >> $GITHUB_OUTPUT
3835
else
@@ -44,6 +41,7 @@ jobs:
4441
echo "is_tag=false" >> $GITHUB_OUTPUT
4542
fi
4643
44+
# Build wheels - one job per OS (cibuildwheel handles all Python versions)
4745
build_wheels:
4846
needs: check_duplicate
4947
if: ${{ needs.check_duplicate.outputs.should_run == 'true' }}
@@ -53,15 +51,14 @@ jobs:
5351
fail-fast: false
5452
matrix:
5553
os: [ubuntu-latest, macos-15-intel, windows-latest]
56-
python-version: ['3.9', '3.10', '3.11', '3.12']
5754

5855
steps:
5956
- uses: actions/checkout@v4
6057

6158
- name: Set up Python
6259
uses: actions/setup-python@v5
6360
with:
64-
python-version: ${{ matrix.python-version }}
61+
python-version: '3.11'
6562

6663
- name: Install dependencies
6764
run: |
@@ -75,54 +72,42 @@ jobs:
7572
run: |
7673
sudo apt-get update
7774
sudo apt-get install -y libsuitesparse-dev libopenblas-dev libsuperlu-dev
78-
# Check where SuperLU headers are located
7975
echo "SuperLU header locations:"
8076
sudo find /usr -name "slu_ddefs.h" | grep superlu
81-
# Create symlinks if necessary
8277
SUPERLU_HEADER=$(sudo find /usr -name "slu_ddefs.h" | grep superlu | head -n 1)
8378
if [ -n "$SUPERLU_HEADER" ]; then
8479
SUPERLU_DIR=$(dirname "$SUPERLU_HEADER")
8580
echo "Found SuperLU headers at: $SUPERLU_DIR"
8681
if [ ! -d "/usr/include/superlu" ]; then
8782
sudo mkdir -p /usr/include/superlu
8883
sudo cp "$SUPERLU_DIR"/*.h /usr/include/superlu/
89-
echo "Created SuperLU header symlinks in /usr/include/superlu/"
9084
fi
9185
fi
9286
93-
# Windows specific setup - uses vendor libraries checked into the repo
87+
# Windows specific setup
9488
- name: Install Windows dependencies
9589
if: runner.os == 'Windows'
9690
shell: bash
9791
run: |
98-
# MinGW-w64 is pre-installed on windows-latest runner
9992
echo "Checking MinGW..."
10093
gcc --version || (echo "MinGW not found, installing..." && choco install mingw -y --no-progress)
101-
# Find MinGW bin directory and add to PATH
10294
MINGW_BIN=$(dirname "$(which gcc)")
10395
echo "MinGW bin: $MINGW_BIN"
10496
echo "$MINGW_BIN" >> $GITHUB_PATH
105-
# Verify vendor libraries exist (these are checked into the repo)
10697
echo "Checking vendor libraries..."
10798
ls -la vendor/superlu/lib/ || echo "WARNING: SuperLU libs not found"
10899
ls -la vendor/superlu/bin/ || echo "WARNING: SuperLU bin not found"
109100
ls -la vendor/openblas/bin/ || echo "WARNING: OpenBLAS bin not found"
110-
ls -la vendor/superlu/include/ || echo "WARNING: SuperLU headers not found"
111101
112102
# macOS specific setup
113103
- name: Install macOS dependencies
114104
if: runner.os == 'macOS'
115105
run: |
116106
brew install suite-sparse superlu openblas
117-
# Debug: Check the openblas library location
118107
export OPENBLAS_PREFIX=$(brew --prefix openblas)
119108
echo "OpenBLAS prefix: $OPENBLAS_PREFIX"
120-
echo "OpenBLAS library paths:"
121-
find $OPENBLAS_PREFIX -name "*.dylib"
122-
# Use the home directory for temporary symlinks (avoid permission issues)
123109
mkdir -p $HOME/homebrew_libs/openblas/lib
124110
ln -sf $OPENBLAS_PREFIX/lib/libopenblas.dylib $HOME/homebrew_libs/openblas/lib/
125-
echo "Created symlink in $HOME/homebrew_libs/openblas/lib/"
126111
echo "OPENBLAS_PREFIX=$OPENBLAS_PREFIX" >> $GITHUB_ENV
127112
echo "HOME_LIBS=$HOME/homebrew_libs" >> $GITHUB_ENV
128113
@@ -131,46 +116,35 @@ jobs:
131116
env:
132117
CIBW_BUILD: 'cp39-* cp310-* cp311-* cp312-*'
133118
CIBW_SKIP: '*-musllinux*'
134-
# Add this to ensure extensions are built
135119
CIBW_BEFORE_BUILD: >
136120
pip install numpy cython
137-
# Make compilation more verbose to see errors
138121
CIBW_BUILD_VERBOSITY: 1
139-
CIBW_ARCHS_MACOS: 'x86_64' # Just x86_64 for CI builds
122+
CIBW_ARCHS_MACOS: 'x86_64'
140123
CIBW_ARCHS_LINUX: 'x86_64'
141-
# Set CI flag for setup.py
142124
CIBW_ENVIRONMENT: >
143125
CI=true
144126
GITHUB_ACTIONS=true
145127
CFLAGS='-O3'
146128
CXXFLAGS='-O3'
147-
# macOS specific environment variables
148129
CIBW_ENVIRONMENT_MACOS: >
149130
CI=true
150131
GITHUB_ACTIONS=true
151132
CFLAGS='-O3'
152133
CXXFLAGS='-O3'
153134
MACOSX_DEPLOYMENT_TARGET=15.0
154-
# manylinux configuration - install required packages
155135
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
156136
CIBW_BEFORE_ALL_LINUX: |
157137
yum install -y epel-release || true
158138
yum install -y openblas-devel SuperLU-devel suitesparse-devel ||
159139
yum install -y openblas-devel superlu-devel suitesparse-devel ||
160140
(apt-get update && apt-get install -y libsuitesparse-dev libsuperlu-dev libopenblas-dev)
161-
162-
# Check SuperLU header location
163141
find /usr -name "slu_ddefs.h" || echo "SuperLU headers not found"
164-
165-
# If header is found, create a symlink in a standard location
166142
HEADER_PATH=$(find /usr -name "slu_ddefs.h" | head -1)
167143
if [ -n "$HEADER_PATH" ]; then
168144
HEADER_DIR=$(dirname "$HEADER_PATH")
169145
mkdir -p /tmp/superlu_include
170-
# Use a conditional copy to avoid errors when no headers match
171146
if [ -f "$HEADER_DIR/slu_ddefs.h" ]; then
172147
cp "$HEADER_DIR"/*.h /tmp/superlu_include/ 2>/dev/null || true
173-
echo "Copied SuperLU headers to /tmp/superlu_include/"
174148
fi
175149
fi
176150
CIBW_BEFORE_ALL_MACOS: >
@@ -180,7 +154,6 @@ jobs:
180154
mkdir -p $HOME/homebrew_libs/openblas/lib;
181155
ln -sf $OPENBLAS_PREFIX/lib/libopenblas.dylib $HOME/homebrew_libs/openblas/lib/;
182156
echo "Created symlink in $HOME/homebrew_libs/openblas/lib/"
183-
# Windows configuration - use vendor libraries from the repo with MinGW
184157
CIBW_ARCHS_WINDOWS: 'AMD64'
185158
CIBW_ENVIRONMENT_WINDOWS: >
186159
CI=true
@@ -195,15 +168,22 @@ jobs:
195168
run: |
196169
python -m cibuildwheel --output-dir wheelhouse
197170
198-
# Store the built wheels
171+
# List built wheels for debugging
172+
- name: List built wheels
173+
shell: bash
174+
run: |
175+
echo "Built wheels:"
176+
ls -la wheelhouse/
177+
178+
# Store the built wheels (one artifact per OS, containing all Python versions)
199179
- name: Upload wheels as artifacts
200180
uses: actions/upload-artifact@v4
201181
with:
202-
name: wheels-${{ matrix.os }}-${{ matrix.python-version }}
182+
name: wheels-${{ matrix.os }}
203183
path: |
204184
./wheelhouse/*.whl
205185
206-
# Test job that runs after the wheels are built
186+
# Test job - test each Python version per OS
207187
test_installation:
208188
needs: [check_duplicate, build_wheels]
209189
if: ${{ needs.check_duplicate.outputs.should_run == 'true' }}
@@ -215,42 +195,30 @@ jobs:
215195
# Linux x86_64
216196
- os: ubuntu-latest
217197
python-version: '3.9'
218-
wheel-suffix: 'manylinux_2_17_x86_64.manylinux2014_x86_64'
219198
- os: ubuntu-latest
220199
python-version: '3.10'
221-
wheel-suffix: 'manylinux_2_17_x86_64.manylinux2014_x86_64'
222200
- os: ubuntu-latest
223201
python-version: '3.11'
224-
wheel-suffix: 'manylinux_2_17_x86_64.manylinux2014_x86_64'
225202
- os: ubuntu-latest
226203
python-version: '3.12'
227-
wheel-suffix: 'manylinux_2_17_x86_64.manylinux2014_x86_64'
228204
# macOS x86_64 (Intel)
229205
- os: macos-15-intel
230206
python-version: '3.9'
231-
wheel-suffix: 'macosx_15_0_x86_64'
232207
- os: macos-15-intel
233208
python-version: '3.10'
234-
wheel-suffix: 'macosx_15_0_x86_64'
235209
- os: macos-15-intel
236210
python-version: '3.11'
237-
wheel-suffix: 'macosx_15_0_x86_64'
238211
- os: macos-15-intel
239212
python-version: '3.12'
240-
wheel-suffix: 'macosx_15_0_x86_64'
241213
# Windows x86_64
242214
- os: windows-latest
243215
python-version: '3.9'
244-
wheel-suffix: 'win_amd64'
245216
- os: windows-latest
246217
python-version: '3.10'
247-
wheel-suffix: 'win_amd64'
248218
- os: windows-latest
249219
python-version: '3.11'
250-
wheel-suffix: 'win_amd64'
251220
- os: windows-latest
252221
python-version: '3.12'
253-
wheel-suffix: 'win_amd64'
254222

255223
steps:
256224
- uses: actions/checkout@v4
@@ -263,9 +231,15 @@ jobs:
263231
- name: Download wheel artifacts
264232
uses: actions/download-artifact@v4
265233
with:
266-
name: wheels-${{ matrix.os }}-${{ matrix.python-version }}
234+
name: wheels-${{ matrix.os }}
267235
path: ./wheelhouse
268236

237+
- name: List available wheels
238+
shell: bash
239+
run: |
240+
echo "Available wheels:"
241+
ls -la wheelhouse/
242+
269243
- name: Install Linux dependencies
270244
if: runner.os == 'Linux'
271245
run: |
@@ -277,90 +251,64 @@ jobs:
277251
run: |
278252
brew install suite-sparse superlu openblas
279253
280-
- name: Inspect linux wheel contents
281-
if: runner.os == 'Linux'
282-
run: |
283-
python -m pip install wheel-inspect
284-
PYTHON_VERSION_NO_DOT=$(echo ${{ matrix.python-version }} | tr -d '.')
285-
WHEEL_FILE=$(ls wheelhouse/sparse_numba-*-cp${PYTHON_VERSION_NO_DOT}-*-${{ matrix.wheel-suffix }}.whl | head -n 1)
286-
python -m wheel_inspect $WHEEL_FILE
287-
unzip -l $WHEEL_FILE | grep "cy_.*wrapper"
288-
289-
- name: Inspect macOS wheel contents
290-
if: runner.os == 'macOS'
291-
run: |
292-
python -m pip install wheel-inspect
293-
PYTHON_VERSION_NO_DOT=$(echo ${{ matrix.python-version }} | tr -d '.')
294-
WHEEL_FILE=$(ls wheelhouse/sparse_numba-*-cp${PYTHON_VERSION_NO_DOT}-*-${{ matrix.wheel-suffix }}.whl | head -n 1)
295-
unzip -l $WHEEL_FILE | grep "cy_.*wrapper"
296-
297254
- name: Install the wheel (Unix)
298255
if: runner.os != 'Windows'
299256
run: |
300257
python -m pip install --upgrade pip
301258
python -m pip install numpy numba
302-
# List available wheels to debug
303-
echo "Available wheels:"
304-
ls -la wheelhouse/
305-
# Install the specific wheel for this platform/Python combination
259+
# Find matching wheel using pip directly (handles platform tags automatically)
306260
PYTHON_VERSION_NO_DOT=$(echo ${{ matrix.python-version }} | tr -d '.')
307-
WHEEL_FILE=$(ls wheelhouse/sparse_numba-*-cp${PYTHON_VERSION_NO_DOT}-*-${{ matrix.wheel-suffix }}.whl | head -n 1)
308-
261+
WHEEL_FILE=$(ls wheelhouse/sparse_numba-*-cp${PYTHON_VERSION_NO_DOT}-*.whl | head -n 1)
309262
if [ -z "$WHEEL_FILE" ]; then
310-
echo "Error: No matching wheel found for Python ${{ matrix.python-version }} and suffix ${{ matrix.wheel-suffix }}"
263+
echo "Error: No matching wheel found for Python ${{ matrix.python-version }}"
264+
echo "Available wheels:"
265+
ls wheelhouse/*.whl
311266
exit 1
312267
fi
313268
echo "Installing wheel: $WHEEL_FILE"
314-
python -m pip install $WHEEL_FILE --verbose
269+
python -m pip install "$WHEEL_FILE" --verbose
315270
316271
- name: Install the wheel (Windows)
317272
if: runner.os == 'Windows'
318273
shell: pwsh
319274
run: |
320275
python -m pip install --upgrade pip
321276
python -m pip install numpy numba
322-
# List available wheels
323-
Write-Host "Available wheels:"
324-
Get-ChildItem wheelhouse/ -Filter *.whl
325-
# Find and install the matching wheel
326277
$pyver = "${{ matrix.python-version }}" -replace '\.', ''
327-
$wheel = Get-ChildItem wheelhouse/sparse_numba-*-cp${pyver}-*-${{ matrix.wheel-suffix }}.whl | Select-Object -First 1
278+
$wheel = Get-ChildItem wheelhouse/sparse_numba-*-cp${pyver}-*.whl | Select-Object -First 1
328279
if (-not $wheel) {
329280
Write-Error "No matching wheel found"
281+
Get-ChildItem wheelhouse/*.whl
330282
exit 1
331283
}
332284
Write-Host "Installing wheel: $($wheel.FullName)"
333285
python -m pip install $wheel.FullName --verbose
334286
335287
- name: Run tests (Unix)
336288
if: runner.os != 'Windows'
289+
env:
290+
KMP_DUPLICATE_LIB_OK: 'TRUE'
337291
run: |
338-
# Create a clean virtual environment
339292
python -m venv test_venv
340293
source test_venv/bin/activate
341294
python -m pip install --upgrade pip
342295
python -m pip install numpy numba
343-
# Install wheel
344296
PYTHON_VERSION_NO_DOT=$(echo ${{ matrix.python-version }} | tr -d '.')
345-
pip install wheelhouse/sparse_numba-*-cp${PYTHON_VERSION_NO_DOT}-*-*.whl
346-
# Copy the test script to a new location
297+
pip install wheelhouse/sparse_numba-*-cp${PYTHON_VERSION_NO_DOT}-*.whl
347298
mkdir -p /tmp/test_dir
348299
cp run_tests.py /tmp/test_dir/
349-
# Change to the new directory and run tests
350300
cd /tmp/test_dir
351-
python run_tests.py
301+
KMP_DUPLICATE_LIB_OK=TRUE python run_tests.py
352302
353303
- name: Run tests (Windows)
354304
if: runner.os == 'Windows'
355305
shell: pwsh
356306
run: |
357-
# Install directly (no venv needed for isolation in CI)
358307
python -m pip install --upgrade pip
359308
python -m pip install numpy numba
360309
$pyver = "${{ matrix.python-version }}" -replace '\.', ''
361-
$wheel = Get-ChildItem wheelhouse/sparse_numba-*-cp${pyver}-*-*.whl | Select-Object -First 1
310+
$wheel = Get-ChildItem wheelhouse/sparse_numba-*-cp${pyver}-*.whl | Select-Object -First 1
362311
python -m pip install $wheel.FullName
363-
# Copy test script to temp dir and run from there
364312
$testDir = Join-Path $env:RUNNER_TEMP "test_dir"
365313
New-Item -ItemType Directory -Force -Path $testDir
366314
Copy-Item run_tests.py $testDir/
@@ -435,6 +383,8 @@ jobs:
435383
mkdir -p final_dist
436384
cp wheelhouse/*.whl final_dist/
437385
cp dist/*.tar.gz final_dist/
386+
echo "Files to upload:"
387+
ls -la final_dist/
438388
439389
- name: Publish to PyPI
440390
uses: pypa/gh-action-pypi-publish@release/v1

0 commit comments

Comments
 (0)