diff --git a/cpython-unix/build-cpython-host.sh b/cpython-unix/build-cpython-host.sh index ff7c3a45..93fdea7c 100755 --- a/cpython-unix/build-cpython-host.sh +++ b/cpython-unix/build-cpython-host.sh @@ -37,17 +37,12 @@ pushd "Python-${PYTHON_VERSION}" # Clang 13 actually prints something with --print-multiarch, confusing CPython's # configure. This is reported as https://bugs.python.org/issue45405. We nerf the # check since we know what we're doing. -if [ "${CC}" = "clang" ]; then +if [[ "${CC}" = "clang" || "${CC}" = "musl-clang" ]]; then if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch else patch -p1 -i ${ROOT}/patch-disable-multiarch.patch fi -elif [ "${CC}" = "musl-clang" ]; then - # Similarly, this is a problem for musl Clang on Python 3.13+ - if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then - patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch - fi fi autoconf diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh index 8b8933de..e58f5eff 100755 --- a/cpython-unix/build-cpython.sh +++ b/cpython-unix/build-cpython.sh @@ -115,6 +115,14 @@ if [ -n "${CROSS_COMPILING}" ]; then fi fi +# CPython <=3.10 doesn't properly detect musl. CPython <=3.12 tries, but fails +# in our environment because of an autoconf bug. CPython >=3.13 is fine. +if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_10}" ]; then + patch -p1 -i ${ROOT}/patch-cpython-configure-target-triple-musl-3.10.patch +elif [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_12}" ]; then + patch -p1 -i ${ROOT}/patch-cpython-configure-target-triple-musl-3.12.patch +fi + # Clang 13 actually prints something with --print-multiarch, confusing CPython's # configure. This is reported as https://bugs.python.org/issue45405. We nerf the # check since we know what we're doing. @@ -1133,11 +1141,10 @@ mkdir -p "${LIB_DYNLOAD}" touch "${LIB_DYNLOAD}/.empty" # Symlink libpython so we don't have 2 copies. +# TODO(geofft): Surely we can get PYTHON_ARCH out of the build? case "${TARGET_TRIPLE}" in 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 + if [[ "${CC}" = "musl-clang" ]]; then PYTHON_ARCH="aarch64-linux-musl" else PYTHON_ARCH="aarch64-linux-gnu" @@ -1176,9 +1183,7 @@ s390x-unknown-linux-gnu) PYTHON_ARCH="s390x-linux-gnu" ;; x86_64-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 + if [[ "${CC}" = "musl-clang" ]]; then PYTHON_ARCH="x86_64-linux-musl" else PYTHON_ARCH="x86_64-linux-gnu" diff --git a/cpython-unix/patch-cpython-configure-target-triple-musl-3.10.patch b/cpython-unix/patch-cpython-configure-target-triple-musl-3.10.patch new file mode 100644 index 00000000..a391278b --- /dev/null +++ b/cpython-unix/patch-cpython-configure-target-triple-musl-3.10.patch @@ -0,0 +1,31 @@ +From d7a70fe9ffa0e4e173bae545cdcba62dc7a2a1f1 Mon Sep 17 00:00:00 2001 +From: Geoffrey Thomas +Date: Sat, 25 Oct 2025 18:49:45 -0400 +Subject: [PATCH 1/1] LOCAL: configure.ac: Fix musl detection +Forwarded: not-needed + +Newer versions of Python rework this code significantly, so this does +not need to be upstreamed. +--- + configure.ac | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/configure.ac b/configure.ac +index ac3be3850a9..9c7c02ea6de 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -866,6 +866,11 @@ EOF + + if $CPP $CPPFLAGS conftest.c >conftest.out 2>/dev/null; then + PLATFORM_TRIPLET=`grep -v '^#' conftest.out | grep -v '^ *$' | tr -d ' '` ++ case "$CC" in ++ musl-*) ++ PLATFORM_TRIPLET=`echo "$PLATFORM_TRIPLET" | sed 's/linux-gnu/linux-musl/'` ++ ;; ++ esac + AC_MSG_RESULT([$PLATFORM_TRIPLET]) + else + AC_MSG_RESULT([none]) +-- +2.39.5 (Apple Git-154) + diff --git a/cpython-unix/patch-cpython-configure-target-triple-musl-3.12.patch b/cpython-unix/patch-cpython-configure-target-triple-musl-3.12.patch new file mode 100644 index 00000000..145f536a --- /dev/null +++ b/cpython-unix/patch-cpython-configure-target-triple-musl-3.12.patch @@ -0,0 +1,36 @@ +From 851c49bafb1fe11c02eafe4850e952cafec548b7 Mon Sep 17 00:00:00 2001 +From: Geoffrey Thomas +Date: Sat, 25 Oct 2025 18:49:45 -0400 +Subject: [PATCH 1/1] LOCAL: configure.ac: Fix musl detection +Forwarded: not-needed + +We set HOST_CC to regular (glibc) clang and CC to musl-clang. +AC_CANONICAL_HOST sets build_os based on the output of config.guess, +which looks at HOST_CC in preference to CC, and therefore misreports the +target triple as gnu. Directly checking CC works for us. + +Newer versions of Python rework this code significantly to not rely on +build_os and do musl detection internally, so this does not need to be +upstreamed. +--- + configure.ac | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 1a02d19f1b2..ee743c11aa5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1108,8 +1108,8 @@ EOF + + if $CPP $CPPFLAGS conftest.c >conftest.out 2>/dev/null; then + PLATFORM_TRIPLET=`grep -v '^#' conftest.out | grep -v '^ *$' | tr -d ' '` +- case "$build_os" in +- linux-musl*) ++ case "$CC" in ++ musl-*) + PLATFORM_TRIPLET=`echo "$PLATFORM_TRIPLET" | sed 's/linux-gnu/linux-musl/'` + ;; + esac +-- +2.39.5 (Apple Git-154) + diff --git a/src/verify_distribution.py b/src/verify_distribution.py index 41382cdd..e7cf4d7d 100644 --- a/src/verify_distribution.py +++ b/src/verify_distribution.py @@ -2,6 +2,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. +import importlib.machinery import os import struct import sys @@ -255,6 +256,17 @@ def test_hash_algorithm(self): msg=f"{sys.hash_info.algorithm=!r} is not siphash", ) + def test_libc_identity(self): + def assertLibc(value): + for libc in ("-gnu", "-musl"): + if os.environ["TARGET_TRIPLE"].endswith(libc): + self.assertIn(libc, value) + else: + self.assertNotIn(libc, value) + + assertLibc(sys.implementation._multiarch) + assertLibc(importlib.machinery.EXTENSION_SUFFIXES[0]) + if __name__ == "__main__": unittest.main()