Skip to content

Commit fd9784e

Browse files
authored
Add support for aarch64 musl (#569)
Closes #87 Does not include the `+static` variant as I was having a hard time getting the bzip2 build passing. I'll open a new issue to track that. Related #484
1 parent 735ded8 commit fd9784e

File tree

8 files changed

+132
-8
lines changed

8 files changed

+132
-8
lines changed

ci-targets.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,26 @@ linux:
348348
minimum-python-version: "3.13"
349349
run: true
350350

351+
aarch64-unknown-linux-musl:
352+
arch: aarch64
353+
libc: musl
354+
python_versions:
355+
- "3.9"
356+
- "3.10"
357+
- "3.11"
358+
- "3.12"
359+
- "3.13"
360+
- "3.14"
361+
build_options:
362+
# TODO: Static support is current blocked by some compiler-rt linking issues
363+
# - debug+static
364+
# - noopt+static
365+
# - lto+static
366+
- debug
367+
- noopt
368+
- lto
369+
run: true
370+
351371
windows:
352372
i686-pc-windows-msvc:
353373
arch: x86

cpython-unix/build-cpython-host.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ case "${BUILD_TRIPLE}" in
7070
EXTRA_HOST_CPPFLAGS="${EXTRA_HOST_CPPFLAGS} -I/usr/include/x86_64-linux-gnu"
7171
EXTRA_HOST_LDFLAGS="${EXTRA_HOST_LDFLAGS} -L/usr/lib/x86_64-linux-gnu"
7272
;;
73+
aarch64-unknown-linux-gnu)
74+
EXTRA_HOST_CFLAGS="${EXTRA_HOST_CFLAGS} -I/usr/include/aarch64-linux-gnu"
75+
EXTRA_HOST_CPPFLAGS="${EXTRA_HOST_CPPFLAGS} -I/usr/include/aarch64-linux-gnu"
76+
EXTRA_HOST_LDFLAGS="${EXTRA_HOST_LDFLAGS} -L/usr/lib/aarch64-linux-gnu"
77+
;;
7378
*)
7479
;;
7580
esac

cpython-unix/build-cpython.sh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,8 +1077,14 @@ touch "${LIB_DYNLOAD}/.empty"
10771077

10781078
# Symlink libpython so we don't have 2 copies.
10791079
case "${TARGET_TRIPLE}" in
1080-
aarch64-unknown-linux-gnu)
1081-
PYTHON_ARCH="aarch64-linux-gnu"
1080+
aarch64-unknown-linux-*)
1081+
# In Python 3.13+, the musl target is identified in cross compiles and the output directory
1082+
# is named accordingly.
1083+
if [[ "${CC}" = "musl-clang" && -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then
1084+
PYTHON_ARCH="aarch64-linux-musl"
1085+
else
1086+
PYTHON_ARCH="aarch64-linux-gnu"
1087+
fi
10821088
;;
10831089
# This is too aggressive. But we don't have patches in place for
10841090
# setting the platform name properly on non-Darwin.

cpython-unix/build-zstd.sh

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@ tar -xf zstd-${ZSTD_VERSION}.tar.gz
1515
pushd cpython-source-deps-zstd-${ZSTD_VERSION}/lib
1616

1717
if [ "${CC}" = "musl-clang" ]; then
18-
# In order to build the library with SSE2, BMI, and AVX2 intrinstics, we need musl-clang to find
18+
# In order to build the library with intrinsics, we need musl-clang to find
1919
# headers that provide access to the intrinsics, as they are not provided by musl. These are
2020
# part of the include files that are part of clang. But musl-clang eliminates them from the
2121
# default include path. So copy them into place.
22-
for h in ${TOOLS_PATH}/${TOOLCHAIN}/lib/clang/*/include/*intrin.h ${TOOLS_PATH}/${TOOLCHAIN}/lib/clang/*/include/{__wmmintrin_aes.h,__wmmintrin_pclmul.h,emmintrin.h,immintrin.h,mm_malloc.h}; do
22+
for h in ${TOOLS_PATH}/${TOOLCHAIN}/lib/clang/*/include/*intrin.h ${TOOLS_PATH}/${TOOLCHAIN}/lib/clang/*/include/{__wmmintrin_aes.h,__wmmintrin_pclmul.h,emmintrin.h,immintrin.h,mm_malloc.h,arm_neon.h,arm_neon_sve_bridge.h,arm_bf16.h,arm_fp16.h,arm_acle.h,arm_vector_types.h}; do
2323
filename=$(basename "$h")
24-
if [ -e "${TOOLS_PATH}/host/include/${filename}" ]; then
25-
echo "warning: ${filename} already exists"
24+
if [ -f "$h" ]; then
25+
if [ -e "${TOOLS_PATH}/host/include/${filename}" ]; then
26+
echo "warning: ${filename} already exists"
27+
fi
28+
cp "$h" ${TOOLS_PATH}/host/include/
29+
else
30+
echo "warning: ${filename} not found (skipping)"
2631
fi
27-
cp "$h" ${TOOLS_PATH}/host/include/
2832
done
2933
EXTRA_TARGET_CFLAGS="${EXTRA_TARGET_CFLAGS} -I${TOOLS_PATH}/host/include/"
3034

@@ -33,7 +37,7 @@ if [ "${CC}" = "musl-clang" ]; then
3337
# `qsort_r` is actually available so we patch it to include a check for glibc.
3438
patch -p1 <<EOF
3539
diff --git a/dictBuilder/cover.c b/dictBuilder/cover.c
36-
index 5e6e8bc..6ca72a1 100644
40+
index 2ef33c7..078e2ee 100644
3741
--- a/dictBuilder/cover.c
3842
+++ b/dictBuilder/cover.c
3943
@@ -241,7 +241,7 @@ typedef struct {
@@ -45,6 +49,24 @@ index 5e6e8bc..6ca72a1 100644
4549
/* C90 only offers qsort() that needs a global context. */
4650
static COVER_ctx_t *g_coverCtx = NULL;
4751
#endif
52+
@@ -290,7 +290,7 @@ static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) {
53+
*/
54+
#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__)
55+
static int WIN_CDECL COVER_strict_cmp(void* g_coverCtx, const void* lp, const void* rp) {
56+
-#elif defined(_GNU_SOURCE)
57+
+#elif defined(_GNU_SOURCE) && defined(__GLIBC__)
58+
static int COVER_strict_cmp(const void *lp, const void *rp, void *g_coverCtx) {
59+
#else /* C90 fallback.*/
60+
static int COVER_strict_cmp(const void *lp, const void *rp) {
61+
@@ -306,7 +306,7 @@ static int COVER_strict_cmp(const void *lp, const void *rp) {
62+
*/
63+
#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__)
64+
static int WIN_CDECL COVER_strict_cmp8(void* g_coverCtx, const void* lp, const void* rp) {
65+
-#elif defined(_GNU_SOURCE)
66+
+#elif defined(_GNU_SOURCE) && defined(__GLIBC__)
67+
static int COVER_strict_cmp8(const void *lp, const void *rp, void *g_coverCtx) {
68+
#else /* C90 fallback.*/
69+
static int COVER_strict_cmp8(const void *lp, const void *rp) {
4870
@@ -328,7 +328,7 @@ static void stableSort(COVER_ctx_t *ctx) {
4971
qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32),
5072
ctx,

cpython-unix/build.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ def add_target_env(env, build_platform, target_triple, build_env):
8888
extra_host_cflags = []
8989
extra_host_ldflags = []
9090

91+
# Add compiler-rt for aarch64-musl to resolve missing builtins
92+
if target_triple == "aarch64-unknown-linux-musl":
93+
extra_target_cflags.append("--rtlib=compiler-rt")
94+
extra_target_ldflags.append("--rtlib=compiler-rt")
95+
9196
if build_platform.startswith("linux_"):
9297
machine = platform.machine()
9398

cpython-unix/targets.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,3 +1131,50 @@ x86_64_v4-unknown-linux-musl:
11311131
- zlib
11321132
- zstd
11331133
openssl_target: linux-x86_64
1134+
1135+
aarch64-unknown-linux-musl:
1136+
host_platforms:
1137+
- linux_x86_64
1138+
- linux_aarch64
1139+
pythons_supported:
1140+
- '3.9'
1141+
- '3.10'
1142+
- '3.11'
1143+
- '3.12'
1144+
- '3.13'
1145+
- '3.14'
1146+
needs_toolchain: true
1147+
docker_image_suffix: .debian9
1148+
needs_toolchain: true
1149+
host_cc: clang
1150+
host_cxx: clang++
1151+
target_cc: musl-clang
1152+
target_cxx: clang++
1153+
target_cflags:
1154+
- '-fvisibility=hidden'
1155+
needs:
1156+
- autoconf
1157+
- bdb
1158+
- binutils
1159+
- bzip2
1160+
- expat
1161+
- libedit
1162+
- libffi-3.3
1163+
- libX11
1164+
- libXau
1165+
- libxcb
1166+
- m4
1167+
- mpdecimal
1168+
- musl
1169+
- ncurses
1170+
- openssl-3.0
1171+
- patchelf
1172+
- sqlite
1173+
- tcl
1174+
- tk
1175+
- uuid
1176+
- xorgproto
1177+
- xz
1178+
- zlib
1179+
- zstd
1180+
openssl_target: linux-aarch64

src/release.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,18 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
339339
}],
340340
},
341341
);
342+
h.insert(
343+
"aarch64-unknown-linux-musl",
344+
TripleRelease {
345+
suffixes: vec!["debug", "lto", "noopt"],
346+
install_only_suffix: "lto",
347+
python_version_requirement: None,
348+
conditional_suffixes: vec![ConditionalSuffixes {
349+
python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
350+
suffixes: linux_suffixes_musl_freethreaded.clone(),
351+
}],
352+
},
353+
);
342354

343355
h
344356
});

src/validation.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const RECOGNIZED_TRIPLES: &[&str] = &[
3535
"aarch64-apple-ios",
3636
"aarch64-pc-windows-msvc",
3737
"aarch64-unknown-linux-gnu",
38+
"aarch64-unknown-linux-musl",
3839
"armv7-unknown-linux-gnueabi",
3940
"armv7-unknown-linux-gnueabihf",
4041
"arm64-apple-tvos",
@@ -211,6 +212,10 @@ static GLIBC_MAX_VERSION_BY_TRIPLE: Lazy<HashMap<&'static str, version_compare::
211212
);
212213

213214
// musl shouldn't link against glibc.
215+
versions.insert(
216+
"aarch64-unknown-linux-musl",
217+
version_compare::Version::from("1").unwrap(),
218+
);
214219
versions.insert(
215220
"x86_64-unknown-linux-musl",
216221
version_compare::Version::from("1").unwrap(),
@@ -549,6 +554,7 @@ static PLATFORM_TAG_BY_TRIPLE: Lazy<HashMap<&'static str, &'static str>> = Lazy:
549554
("aarch64-apple-ios", "iOS-aarch64"),
550555
("aarch64-pc-windows-msvc", "win-arm64"),
551556
("aarch64-unknown-linux-gnu", "linux-aarch64"),
557+
("aarch64-unknown-linux-musl", "linux-aarch64"),
552558
("armv7-unknown-linux-gnueabi", "linux-arm"),
553559
("armv7-unknown-linux-gnueabihf", "linux-arm"),
554560
("i686-pc-windows-msvc", "win32"),
@@ -949,6 +955,7 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
949955

950956
let wanted_cpu_type = match target_triple {
951957
"aarch64-unknown-linux-gnu" => object::elf::EM_AARCH64,
958+
"aarch64-unknown-linux-musl" => object::elf::EM_AARCH64,
952959
"armv7-unknown-linux-gnueabi" => object::elf::EM_ARM,
953960
"armv7-unknown-linux-gnueabihf" => object::elf::EM_ARM,
954961
"i686-unknown-linux-gnu" => object::elf::EM_386,

0 commit comments

Comments
 (0)