Skip to content

Commit 7ad0b93

Browse files
authored
Add support for Linux ARM for Python wheels (#370)
* Add support for Linux ARM for Python wheels * Try arm * Fix bug with 3.14 and binary * Fix bug with 3.14 and binary * Fix bug with 3.14 and binary * Improve version support * Fix indirect ref * Fix bug * Fix bug * Fix again * Fix again * Fix again * Remove pandas * Fix cmake bug * Disable float type size check for arm * Fix cmake * Try latest numpy * Try latest numpy * Try latest numpy * Fix python 3.8 * Set thread count to 1 * Try older ubuntu image * Try older ubuntu image * Check swig version * Work around segfault issues * Fix bug * Add check loop * Add quotes * Address more comments * Fix comment * Remove platform from docker
1 parent 15812a4 commit 7ad0b93

File tree

6 files changed

+76
-56
lines changed

6 files changed

+76
-56
lines changed

.github/workflows/python.yml

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ name: Python Wheels
33
env:
44
MACOSX_DEPLOYMENT_TARGET: 10.9
55
DOCKER_IMAGE: quay.io/pypa/manylinux2014_x86_64
6+
DOCKER_IMAGE_AARCH64: quay.io/pypa/manylinux_2_28_aarch64
7+
# Unable to build numpy using the earlier image below
8+
#quay.io/pypa/manylinux2014_aarch64
69

710
on:
811
push:
@@ -16,7 +19,7 @@ jobs:
1619
runs-on: ${{ matrix.os }}
1720
strategy:
1821
matrix:
19-
os: [ubuntu-latest, windows-latest, macOS-latest]
22+
os: [ubuntu-22.04, windows-latest, macOS-latest]
2023
pyver: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
2124

2225
steps:
@@ -25,7 +28,7 @@ jobs:
2528
fetch-depth: 0
2629

2730
- uses: actions/setup-python@v4
28-
if: matrix.os != 'ubuntu-latest'
31+
if: ${{ !startsWith(matrix.os, 'ubuntu') }}
2932
with:
3033
python-version: ${{matrix.pyver}}
3134
id: cpver
@@ -36,33 +39,18 @@ jobs:
3639
git config user.email "<>"
3740
git --version
3841
39-
- name: Package Python 3.8 and earlier
40-
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.pyver == '3.8' }}
41-
run: docker run --rm -v ${{github.workspace}}/:/io ezralanglois/interop sh /io/tools/package.sh /io /io/dist travis OFF
42+
- name: Package Python 3.8-3.x Linux x86_64
43+
if: ${{ startsWith(matrix.os, 'ubuntu') }}
44+
run: docker run --rm -v ${{github.workspace}}/:/io $DOCKER_IMAGE sh /io/tools/package.sh /io /io/dist travis OFF Release ${{ matrix.pyver }}
4245

43-
- name: Package Python 3.9
44-
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.pyver == '3.9' }}
45-
run: docker run --rm -v ${{github.workspace}}/:/io $DOCKER_IMAGE sh /io/tools/package.sh /io /io/dist travis OFF Release cp39-cp39
46-
47-
- name: Package Python 3.10
48-
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.pyver == '3.10' }}
49-
run: docker run --rm -v ${{github.workspace}}/:/io $DOCKER_IMAGE sh /io/tools/package.sh /io /io/dist travis OFF Release cp310-cp310
50-
51-
- name: Package Python 3.11
52-
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.pyver == '3.11' }}
53-
run: docker run --rm -v ${{github.workspace}}/:/io $DOCKER_IMAGE sh /io/tools/package.sh /io /io/dist travis OFF Release cp311-cp311
54-
55-
- name: Package Python 3.12
56-
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.pyver == '3.12' }}
57-
run: docker run --rm -v ${{github.workspace}}/:/io $DOCKER_IMAGE sh /io/tools/package.sh /io /io/dist travis OFF Release cp312-cp312
58-
59-
- name: Package Python 3.13
60-
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.pyver == '3.13' }}
61-
run: docker run --rm -v ${{github.workspace}}/:/io $DOCKER_IMAGE sh /io/tools/package.sh /io /io/dist travis OFF Release cp313-cp313
46+
- name: Install QEMU
47+
if: ${{ startsWith(matrix.os, 'ubuntu') }}
48+
run: |
49+
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
6250
63-
- name: Package Python 3.14
64-
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.pyver == '3.14' }}
65-
run: docker run --rm -v ${{github.workspace}}/:/io $DOCKER_IMAGE sh /io/tools/package.sh /io /io/dist travis OFF Release cp314-cp314
51+
- name: Package Python 3.9-3.x Linux Arm64
52+
if: ${{ startsWith(matrix.os, 'ubuntu') }}
53+
run: docker run --rm -v ${{github.workspace}}/:/io $DOCKER_IMAGE_AARCH64 sh /io/tools/package.sh /io /io/dist travis OFF Release ${{ matrix.pyver }}
6654

6755
- name: Windows Package Python
6856
if: ${{ startsWith(matrix.os, 'windows') }}

cmake/CheckSWIGVersion.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ function(check_swig_version _major_ver)
99
VERSION
1010
OUTPUT_STRIP_TRAILING_WHITESPACE
1111
)
12-
string(REGEX REPLACE "SWIG Version ([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" swig_major_ver ${VERSION})
12+
message(STATUS "SWIG version output: ${VERSION}")
13+
string(REGEX REPLACE "SWIG Version ([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" swig_major_ver "${VERSION}")
1314
string(STRIP ${swig_major_ver} swig_major_ver)
1415
set(${_major_ver} ${swig_major_ver} PARENT_SCOPE)
1516
endfunction()

cmake/InternalUtils.cmake

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,14 @@ macro(interop_config_compiler_and_linker)
7979
endif()
8080
endif()
8181

82-
include(CheckTypeSize)
83-
check_type_size("float" SIZEOF_FLOAT)
84-
if( "${SIZEOF_FLOAT}" STREQUAL "" )
85-
message(FATAL_ERROR "Type float is not supported on this system and/or compiler: ${CMAKE_SYSTEM}/${CMAKE_CXX_COMPILER_ID}")
86-
elseif( NOT ${SIZEOF_FLOAT} EQUAL "4" )
87-
message(FATAL_ERROR "Type float is ${SIZEOF_FLOAT}-byte - This system and/or compiler is not supported: ${CMAKE_SYSTEM}/${CMAKE_CXX_COMPILER_ID}")
82+
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "(^aarch64)|(^arm64)|(^ARM64)")
83+
include(CheckTypeSize)
84+
check_type_size("float" SIZEOF_FLOAT)
85+
if( "${SIZEOF_FLOAT}" STREQUAL "" )
86+
message(FATAL_ERROR "Type float is not supported on this system and/or compiler: ${CMAKE_SYSTEM}/${CMAKE_CXX_COMPILER_ID}")
87+
elseif( NOT ${SIZEOF_FLOAT} EQUAL "4" )
88+
message(FATAL_ERROR "Type float is ${SIZEOF_FLOAT}-byte - This system and/or compiler is not supported: ${CMAKE_SYSTEM}/${CMAKE_CXX_COMPILER_ID}")
89+
endif()
8890
endif()
8991

9092
include(CheckIncludeFiles)

cmake/Modules/CheckIsNaN.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Adpoted from: https://github.com/soonhokong/fp-test/blob/master/src/cmake_modules/CheckIsNaN.cmake
33

44
include(CheckCXXSourceCompiles)
5+
include(CheckCXXSourceRuns)
56

67

78
CHECK_CXX_SOURCE_COMPILES(

docs/src/changes.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changes {#changes}
22

3+
## v1.9.0
4+
5+
| Date | Description |
6+
|------------|-------------------------------------------------------------------------|
7+
| 2025-12-11 | Add support for Linux ARM for Python wheels |
8+
| 2025-12-11 | Speed up linux build by using only binary packages for numpy and pandas |
9+
310
## v1.8.0
411

512
| Date | Description |

tools/package.sh

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -156,36 +156,57 @@ if [ -e /opt/python ] ; then
156156
if [[ "$PYBUILD" == cp33* ]]; then
157157
continue
158158
fi
159-
rm -fr ${BUILD_PATH}
159+
rm -fr "${BUILD_PATH}"
160160

161161
run "Configure ${PYBUILD}" cmake $SOURCE_PATH -B${BUILD_PATH} -DPython_EXECUTABLE=${PYTHON_BIN}/python ${CMAKE_EXTRA_FLAGS} -DSKIP_PACKAGE_ALL_WHEEL=ON -DPYTHON_WHEEL_PREFIX=${ARTIFACT_PATH}/tmp -DENABLE_CSHARP=OFF
162162

163163
run "Test ${PYBUILD}" cmake --build $BUILD_PATH --target check -- -j${THREAD_COUNT}
164164
run "Build ${PYBUILD}" cmake --build $BUILD_PATH --target package_wheel -- -j${THREAD_COUNT}
165-
auditwheel show ${ARTIFACT_PATH}/tmp/interop*${PYBUILD}*linux_x86_64.whl
166-
auditwheel repair ${ARTIFACT_PATH}/tmp/interop*${PYBUILD}*linux_x86_64.whl -w ${ARTIFACT_PATH}
167-
rm -fr ${ARTIFACT_PATH}/tmp
165+
auditwheel show ${ARTIFACT_PATH}/tmp/interop*${PYBUILD}*linux_*.whl
166+
auditwheel repair ${ARTIFACT_PATH}/tmp/interop*${PYBUILD}*linux_*.whl -w ${ARTIFACT_PATH}
167+
rm -fr "${ARTIFACT_PATH}/tmp"
168168
done
169169
else
170-
/opt/python/cp38-cp38/bin/python -m pip install numpy==1.17.3 pandas setuptools
171-
/opt/python/cp39-cp39/bin/python -m pip install numpy==2.0.0 pandas setuptools
172-
/opt/python/cp310-cp310/bin/python -m pip install numpy==2.0.0 pandas setuptools
173-
/opt/python/cp311-cp311/bin/python -m pip install numpy==2.0.0 pandas setuptools
174-
/opt/python/cp312-cp312/bin/python -m pip install numpy==2.0.0 pandas setuptools
175-
/opt/python/cp313-cp313/bin/python -m pip install numpy==2.0.0 pandas setuptools
176-
/opt/python/cp314-cp314/bin/python -m pip install numpy==2.0.0 pandas setuptools
177-
/opt/python/cp310-cp310/bin/python -m pip install swig==4.0.2 --prefix=/tmp/usr
178170

179-
echo "Build with specific Python Version: ${PYTHON_VERSION}"
180-
PYTHON_BIN=/opt/python/${PYTHON_VERSION}/bin
181-
rm -fr ${BUILD_PATH}/src/ext/python/*
182-
run "Configure ${PYTHON_VERSION}" cmake $SOURCE_PATH -B${BUILD_PATH} -DPython_EXECUTABLE=${PYTHON_BIN}/python ${CMAKE_EXTRA_FLAGS} -DSKIP_PACKAGE_ALL_WHEEL=ON -DPYTHON_WHEEL_PREFIX=${ARTIFACT_PATH}/tmp -DENABLE_CSHARP=OFF -DSWIG_EXECUTABLE=/tmp/usr/lib/python3.10/site-packages/swig/data/bin/swig -DSWIG_DIR=/tmp/usr/lib/python3.10/site-packages/swig/data/share/swig/4.0.2/
171+
echo "Build with specific Python Version: ${PYTHON_VERSION}"
172+
if [[ "$PYTHON_VERSION" != "cp"* ]]; then
173+
pyver="cp${PYTHON_VERSION/./}"
174+
PYTHON_VERSION="${pyver}-${pyver}"
175+
echo "Converted to PYTHON_VERSION=${PYTHON_VERSION}"
176+
fi
177+
if [[ "$PYTHON_VERSION" == "cp38-cp38" ]]; then
178+
set +e
179+
/opt/python/${PYTHON_VERSION}/bin/python -m pip install numpy==1.17.3 pandas setuptools --only-binary numpy,pandas
180+
if [ $? -ne 0 ] ; then
181+
/opt/python/${PYTHON_VERSION}/bin/python -m pip install numpy==1.19.0 pandas setuptools --only-binary numpy,pandas
182+
fi
183+
set -e
184+
else
185+
# We are using an older CentOS 7 image, so we should rebuild numpy and pandas from source
186+
/opt/python/${PYTHON_VERSION}/bin/python -m pip install numpy>=2.0.0 setuptools
187+
fi
188+
/opt/python/cp310-cp310/bin/python -m pip install swig==4.0.2 --prefix=/tmp/usr
183189

184-
run "Test ${PYTHON_VERSION}" cmake --build $BUILD_PATH --target check -- -j${THREAD_COUNT}
185-
run "Build ${PYTHON_VERSION}" cmake --build $BUILD_PATH --target package_wheel -- -j${THREAD_COUNT}
186-
auditwheel show ${ARTIFACT_PATH}/tmp/interop*${PYTHON_VERSION}*linux_x86_64.whl
187-
auditwheel repair ${ARTIFACT_PATH}/tmp/interop*${PYTHON_VERSION}*linux_x86_64.whl -w ${ARTIFACT_PATH}
188-
rm -fr ${ARTIFACT_PATH}/tmp
190+
PYTHON_BIN="/opt/python/${PYTHON_VERSION}/bin"
191+
rm -fr "${BUILD_PATH}/src/ext/python/*"
192+
run "Configure ${PYTHON_VERSION}" cmake $SOURCE_PATH -B${BUILD_PATH} -DPython_EXECUTABLE=${PYTHON_BIN}/python ${CMAKE_EXTRA_FLAGS} -DSKIP_PACKAGE_ALL_WHEEL=ON -DPYTHON_WHEEL_PREFIX=${ARTIFACT_PATH}/tmp -DENABLE_CSHARP=OFF -DSWIG_EXECUTABLE=/tmp/usr/lib/python3.10/site-packages/swig/data/bin/swig -DSWIG_DIR=/tmp/usr/lib/python3.10/site-packages/swig/data/share/swig/4.0.2/
193+
194+
set +e
195+
for attempt in 1 2 3; do
196+
run "Test ${PYTHON_VERSION}" cmake --build $BUILD_PATH --target check -- -j${THREAD_COUNT}
197+
done
198+
set -e
199+
run "Test ${PYTHON_VERSION}" cmake --build $BUILD_PATH --target check -- -j${THREAD_COUNT}
200+
201+
set +e
202+
for attempt in 1 2 3; do
203+
run "Build ${PYTHON_VERSION}" cmake --build $BUILD_PATH --target package_wheel -- -j${THREAD_COUNT}
204+
done
205+
set -e
206+
run "Build ${PYTHON_VERSION}" cmake --build $BUILD_PATH --target package_wheel -- -j${THREAD_COUNT}
207+
auditwheel show ${ARTIFACT_PATH}/tmp/interop*${PYTHON_VERSION}*linux_*.whl
208+
auditwheel repair ${ARTIFACT_PATH}/tmp/interop*${PYTHON_VERSION}*linux_*.whl -w ${ARTIFACT_PATH}
209+
rm -fr "${ARTIFACT_PATH}/tmp"
189210
fi
190211
elif [ "$PYTHON_VERSION" != "" ] && [ "$PYTHON_VERSION" != "Disable" ] && [ "$PYTHON_VERSION" != "DotNetStandard" ] && [ "$PYTHON_VERSION" != "None" ] ; then
191212
if [ "$PYTHON_VERSION" == "ALL" ] ; then
@@ -254,7 +275,7 @@ elif [ "$PYTHON_VERSION" != "" ] && [ "$PYTHON_VERSION" != "Disable" ] && [ "$PY
254275
which pip
255276
python -m pip install delocate || true
256277
python --version
257-
python -m pip install numpy
278+
python -m pip install numpy --only-binary numpy,pandas
258279
python -m pip install wheel
259280
python -m pip install setuptools
260281
echo "Check setuptools"

0 commit comments

Comments
 (0)