Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions ci-targets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,26 @@ linux:
minimum-python-version: "3.13"
run: true

aarch64-unknown-linux-musl:
arch: aarch64
libc: musl
python_versions:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
build_options:
# TODO: Static support is current blocked by some compiler-rt linking issues
# - debug+static
# - noopt+static
# - lto+static
- debug
- noopt
- lto
run: true

windows:
i686-pc-windows-msvc:
arch: x86
Expand Down
5 changes: 5 additions & 0 deletions cpython-unix/build-cpython-host.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ case "${BUILD_TRIPLE}" in
EXTRA_HOST_CPPFLAGS="${EXTRA_HOST_CPPFLAGS} -I/usr/include/x86_64-linux-gnu"
EXTRA_HOST_LDFLAGS="${EXTRA_HOST_LDFLAGS} -L/usr/lib/x86_64-linux-gnu"
;;
aarch64-unknown-linux-gnu)
EXTRA_HOST_CFLAGS="${EXTRA_HOST_CFLAGS} -I/usr/include/aarch64-linux-gnu"
EXTRA_HOST_CPPFLAGS="${EXTRA_HOST_CPPFLAGS} -I/usr/include/aarch64-linux-gnu"
EXTRA_HOST_LDFLAGS="${EXTRA_HOST_LDFLAGS} -L/usr/lib/aarch64-linux-gnu"
;;
*)
;;
esac
Expand Down
10 changes: 8 additions & 2 deletions cpython-unix/build-cpython.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1077,8 +1077,14 @@ touch "${LIB_DYNLOAD}/.empty"

# Symlink libpython so we don't have 2 copies.
case "${TARGET_TRIPLE}" in
aarch64-unknown-linux-gnu)
PYTHON_ARCH="aarch64-linux-gnu"
aarch64-unknown-linux-*)
# In Python 3.13+, the musl target is identified in cross compiles and the output directory
# is named accordingly.
if [[ "${CC}" = "musl-clang" && -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then
PYTHON_ARCH="aarch64-linux-musl"
else
PYTHON_ARCH="aarch64-linux-gnu"
fi
;;
# This is too aggressive. But we don't have patches in place for
# setting the platform name properly on non-Darwin.
Expand Down
34 changes: 28 additions & 6 deletions cpython-unix/build-zstd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ tar -xf zstd-${ZSTD_VERSION}.tar.gz
pushd cpython-source-deps-zstd-${ZSTD_VERSION}/lib

if [ "${CC}" = "musl-clang" ]; then
# In order to build the library with SSE2, BMI, and AVX2 intrinstics, we need musl-clang to find
# In order to build the library with intrinsics, we need musl-clang to find
# headers that provide access to the intrinsics, as they are not provided by musl. These are
# part of the include files that are part of clang. But musl-clang eliminates them from the
# default include path. So copy them into place.
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
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
filename=$(basename "$h")
if [ -e "${TOOLS_PATH}/host/include/${filename}" ]; then
echo "warning: ${filename} already exists"
if [ -f "$h" ]; then
if [ -e "${TOOLS_PATH}/host/include/${filename}" ]; then
echo "warning: ${filename} already exists"
fi
cp "$h" ${TOOLS_PATH}/host/include/
else
echo "warning: ${filename} not found (skipping)"
fi
cp "$h" ${TOOLS_PATH}/host/include/
done
EXTRA_TARGET_CFLAGS="${EXTRA_TARGET_CFLAGS} -I${TOOLS_PATH}/host/include/"

Expand All @@ -33,7 +37,7 @@ if [ "${CC}" = "musl-clang" ]; then
# `qsort_r` is actually available so we patch it to include a check for glibc.
patch -p1 <<EOF
diff --git a/dictBuilder/cover.c b/dictBuilder/cover.c
index 5e6e8bc..6ca72a1 100644
index 2ef33c7..078e2ee 100644
--- a/dictBuilder/cover.c
+++ b/dictBuilder/cover.c
@@ -241,7 +241,7 @@ typedef struct {
Expand All @@ -45,6 +49,24 @@ index 5e6e8bc..6ca72a1 100644
/* C90 only offers qsort() that needs a global context. */
static COVER_ctx_t *g_coverCtx = NULL;
#endif
@@ -290,7 +290,7 @@ static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) {
*/
#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__)
static int WIN_CDECL COVER_strict_cmp(void* g_coverCtx, const void* lp, const void* rp) {
-#elif defined(_GNU_SOURCE)
+#elif defined(_GNU_SOURCE) && defined(__GLIBC__)
static int COVER_strict_cmp(const void *lp, const void *rp, void *g_coverCtx) {
#else /* C90 fallback.*/
static int COVER_strict_cmp(const void *lp, const void *rp) {
@@ -306,7 +306,7 @@ static int COVER_strict_cmp(const void *lp, const void *rp) {
*/
#if (defined(_WIN32) && defined(_MSC_VER)) || defined(__APPLE__)
static int WIN_CDECL COVER_strict_cmp8(void* g_coverCtx, const void* lp, const void* rp) {
-#elif defined(_GNU_SOURCE)
+#elif defined(_GNU_SOURCE) && defined(__GLIBC__)
static int COVER_strict_cmp8(const void *lp, const void *rp, void *g_coverCtx) {
#else /* C90 fallback.*/
static int COVER_strict_cmp8(const void *lp, const void *rp) {
@@ -328,7 +328,7 @@ static void stableSort(COVER_ctx_t *ctx) {
qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32),
ctx,
Expand Down
5 changes: 5 additions & 0 deletions cpython-unix/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ def add_target_env(env, build_platform, target_triple, build_env):
extra_host_cflags = []
extra_host_ldflags = []

# Add compiler-rt for aarch64-musl to resolve missing builtins
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I don't understand why we need to be explicit about this.

Without this, the bzip2 and openssl builds fail with missing symbols (it's possible more do too, I didn't play whackamole for long).

if target_triple == "aarch64-unknown-linux-musl":
extra_target_cflags.append("--rtlib=compiler-rt")
extra_target_ldflags.append("--rtlib=compiler-rt")

if build_platform.startswith("linux_"):
machine = platform.machine()

Expand Down
47 changes: 47 additions & 0 deletions cpython-unix/targets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1131,3 +1131,50 @@ x86_64_v4-unknown-linux-musl:
- zlib
- zstd
openssl_target: linux-x86_64

aarch64-unknown-linux-musl:
host_platforms:
- linux_x86_64
- linux_aarch64
pythons_supported:
- '3.9'
- '3.10'
- '3.11'
- '3.12'
- '3.13'
- '3.14'
needs_toolchain: true
docker_image_suffix: .debian9
needs_toolchain: true
host_cc: clang
host_cxx: clang++
target_cc: musl-clang
target_cxx: clang++
target_cflags:
- '-fvisibility=hidden'
needs:
- autoconf
- bdb
- binutils
- bzip2
- expat
- libedit
- libffi-3.3
- libX11
- libXau
- libxcb
- m4
- mpdecimal
- musl
- ncurses
- openssl-3.0
- patchelf
- sqlite
- tcl
- tk
- uuid
- xorgproto
- xz
- zlib
- zstd
openssl_target: linux-aarch64
12 changes: 12 additions & 0 deletions src/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,18 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
}],
},
);
h.insert(
"aarch64-unknown-linux-musl",
TripleRelease {
suffixes: vec!["debug", "lto", "noopt"],
install_only_suffix: "lto",
python_version_requirement: None,
conditional_suffixes: vec![ConditionalSuffixes {
python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
suffixes: linux_suffixes_musl_freethreaded.clone(),
}],
},
);

h
});
Expand Down
7 changes: 7 additions & 0 deletions src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const RECOGNIZED_TRIPLES: &[&str] = &[
"aarch64-apple-ios",
"aarch64-pc-windows-msvc",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"armv7-unknown-linux-gnueabi",
"armv7-unknown-linux-gnueabihf",
"arm64-apple-tvos",
Expand Down Expand Up @@ -211,6 +212,10 @@ static GLIBC_MAX_VERSION_BY_TRIPLE: Lazy<HashMap<&'static str, version_compare::
);

// musl shouldn't link against glibc.
versions.insert(
"aarch64-unknown-linux-musl",
version_compare::Version::from("1").unwrap(),
);
versions.insert(
"x86_64-unknown-linux-musl",
version_compare::Version::from("1").unwrap(),
Expand Down Expand Up @@ -549,6 +554,7 @@ static PLATFORM_TAG_BY_TRIPLE: Lazy<HashMap<&'static str, &'static str>> = Lazy:
("aarch64-apple-ios", "iOS-aarch64"),
("aarch64-pc-windows-msvc", "win-arm64"),
("aarch64-unknown-linux-gnu", "linux-aarch64"),
("aarch64-unknown-linux-musl", "linux-aarch64"),
("armv7-unknown-linux-gnueabi", "linux-arm"),
("armv7-unknown-linux-gnueabihf", "linux-arm"),
("i686-pc-windows-msvc", "win32"),
Expand Down Expand Up @@ -949,6 +955,7 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(

let wanted_cpu_type = match target_triple {
"aarch64-unknown-linux-gnu" => object::elf::EM_AARCH64,
"aarch64-unknown-linux-musl" => object::elf::EM_AARCH64,
"armv7-unknown-linux-gnueabi" => object::elf::EM_ARM,
"armv7-unknown-linux-gnueabihf" => object::elf::EM_ARM,
"i686-unknown-linux-gnu" => object::elf::EM_386,
Expand Down
Loading