diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 3b70b5f8..04bd2d0e 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -59,6 +59,7 @@ jobs: - build - build.cross - build.cross-riscv64 + - build.cross-loongarch64 - gcc name: ${{ matrix.image }} runs-on: depot-ubuntu-22.04 diff --git a/ci-targets.yaml b/ci-targets.yaml index 70078e87..7fe1b5c8 100644 --- a/ci-targets.yaml +++ b/ci-targets.yaml @@ -101,6 +101,27 @@ linux: - freethreaded+lto minimum-python-version: "3.13" + loongarch64-unknown-linux-gnu: + arch: loongarch64 + libc: gnu + python_versions: + - "3.9" + - "3.10" + - "3.11" + - "3.12" + - "3.13" + - "3.14" + build_options: + - debug + - noopt + - lto + build_options_conditional: + - options: + - freethreaded+debug + - freethreaded+noopt + - freethreaded+lto + minimum-python-version: "3.13" + s390x-unknown-linux-gnu: arch: s390x libc: gnu diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh index 820b6a2d..046763ef 100755 --- a/cpython-unix/build-cpython.sh +++ b/cpython-unix/build-cpython.sh @@ -69,6 +69,15 @@ if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then fi fi +# configure doesn't support cross-compiling on LoongArch. Teach it. +if [ "${PYBUILD_PLATFORM}" != "macos" ]; then + case "${PYTHON_MAJMIN_VERSION}" in + 3.9|3.10|3.11) + patch -p1 -i ${ROOT}/patch-configure-add-loongarch-triplet.patch + ;; + esac +fi + # disable readelf check when cross-compiling on older Python versions if [ -n "${CROSS_COMPILING}" ]; then if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_11}" ]; then @@ -1089,6 +1098,9 @@ armv7-unknown-linux-gnueabi) armv7-unknown-linux-gnueabihf) PYTHON_ARCH="arm-linux-gnueabihf" ;; +loongarch64-unknown-linux-gnu) + PYTHON_ARCH="loongarch64-linux-gnu" + ;; mips-unknown-linux-gnu) PYTHON_ARCH="mips-linux-gnu" ;; @@ -1246,7 +1258,8 @@ if [ -d "${TOOLS_PATH}/deps/lib/tcl8" ]; then cp -av $source ${ROOT}/out/python/install/lib/ done - if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then + # Tix doesn't support macOS and loongarch64, so we don't copy it there. + if [[ "${PYBUILD_PLATFORM}" != macos* ]] && [[ "${TARGET_TRIPLE}" != loongarch64* ]]; then cp -av ${TOOLS_PATH}/deps/lib/Tix8.4.3 ${ROOT}/out/python/install/lib/ fi fi diff --git a/cpython-unix/build-libX11.sh b/cpython-unix/build-libX11.sh index bb45028b..0b1d96b1 100755 --- a/cpython-unix/build-libX11.sh +++ b/cpython-unix/build-libX11.sh @@ -54,6 +54,9 @@ if [ -n "${CROSS_COMPILING}" ]; then armv7-unknown-linux-gnueabihf) EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull" ;; + loongarch64-unknown-linux-gnu) + EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull" + ;; mips-unknown-linux-gnu) EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull" ;; @@ -78,6 +81,9 @@ if [ -n "${CROSS_COMPILING}" ]; then aarch64-unknown-linux-musl) EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull" ;; + loongarch64-unknown-linux-musl) + EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull" + ;; mips-unknown-linux-musl) EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull" ;; diff --git a/cpython-unix/build-libxcb.sh b/cpython-unix/build-libxcb.sh index 0b6cb911..07117a20 100755 --- a/cpython-unix/build-libxcb.sh +++ b/cpython-unix/build-libxcb.sh @@ -13,6 +13,12 @@ export PKG_CONFIG_PATH=/tools/deps/share/pkgconfig:/tools/deps/lib/pkgconfig tar -xf libxcb-${LIBXCB_VERSION}.tar.gz pushd libxcb-${LIBXCB_VERSION} +if [[ "${TARGET_TRIPLE}" = loongarch64* ]]; then + rm -f build-aux/config.guess build-aux/config.sub + curl -sSL -o build-aux/config.guess https://github.com/cgitmirror/config/raw/refs/heads/master/config.guess + curl -sSL -o build-aux/config.sub https://github.com/cgitmirror/config/raw/refs/heads/master/config.sub +fi + if [ "${CC}" = "musl-clang" ]; then EXTRA_FLAGS="--disable-shared" fi diff --git a/cpython-unix/build-main.py b/cpython-unix/build-main.py index a353daf2..cbe5d353 100755 --- a/cpython-unix/build-main.py +++ b/cpython-unix/build-main.py @@ -95,10 +95,8 @@ def main(): "toolchain-image-build", "toolchain-image-build.cross", "toolchain-image-build.cross-riscv64", + "toolchain-image-build.cross-loongarch64", "toolchain-image-gcc", - "toolchain-image-xcb", - "toolchain-image-xcb.cross", - "toolchain-image-xcb.cross-riscv64", }, default="default", help="The make target to evaluate", diff --git a/cpython-unix/build-ncurses.sh b/cpython-unix/build-ncurses.sh index 25df7e22..cedeb702 100755 --- a/cpython-unix/build-ncurses.sh +++ b/cpython-unix/build-ncurses.sh @@ -109,6 +109,8 @@ else " fi +mkdir -p ${ROOT}/out/usr/lib + CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS} make -j ${NUM_CPUS} make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out diff --git a/cpython-unix/build-xorgproto.sh b/cpython-unix/build-xorgproto.sh index 97c1aa4f..7d5d28f4 100755 --- a/cpython-unix/build-xorgproto.sh +++ b/cpython-unix/build-xorgproto.sh @@ -15,6 +15,12 @@ export PKG_CONFIG_PATH=/tools/deps/share/pkgconfig tar -xf xorgproto-${XORGPROTO_VERSION}.tar.gz pushd xorgproto-${XORGPROTO_VERSION} +if [[ "${TARGET_TRIPLE}" = loongarch64* ]]; then + rm -f config.guess.sub config.sub + curl -sSL -o config.guess https://github.com/cgitmirror/config/raw/refs/heads/master/config.guess + curl -sSL -o config.sub https://github.com/cgitmirror/config/raw/refs/heads/master/config.sub +fi + CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \ --build=${BUILD_TRIPLE} \ --host=${TARGET_TRIPLE} \ diff --git a/cpython-unix/build.Dockerfile b/cpython-unix/build.Dockerfile index e44d0a2e..5a5dcad8 100644 --- a/cpython-unix/build.Dockerfile +++ b/cpython-unix/build.Dockerfile @@ -9,6 +9,8 @@ # Various other build tools are needed for various building. RUN ulimit -n 10000 && apt-get install \ bzip2 \ + ca-certificates \ + curl \ file \ libc6-dev \ libffi-dev \ diff --git a/cpython-unix/build.cross-loongarch64.Dockerfile b/cpython-unix/build.cross-loongarch64.Dockerfile new file mode 100644 index 00000000..85b282c6 --- /dev/null +++ b/cpython-unix/build.cross-loongarch64.Dockerfile @@ -0,0 +1,64 @@ +# Debian Trixie. +FROM debian@sha256:653dfb9f86c3782e8369d5f7d29bb8faba1f4bff9025db46e807fa4c22903671 +MAINTAINER Gregory Szorc + +RUN groupadd -g 1000 build && \ + useradd -u 1000 -g 1000 -d /build -s /bin/bash -m build && \ + mkdir /tools && \ + chown -R build:build /build /tools + +ENV HOME=/build \ + SHELL=/bin/bash \ + USER=build \ + LOGNAME=build \ + HOSTNAME=builder \ + DEBIAN_FRONTEND=noninteractive + +CMD ["/bin/bash", "--login"] +WORKDIR '/build' + +RUN for s in debian_trixie debian_trixie-updates; do \ + echo "deb http://snapshot.debian.org/archive/${s%_*}/20250515T202920Z/ ${s#*_} main"; \ + done > /etc/apt/sources.list && \ + for s in debian-security_trixie-security/updates; do \ + echo "deb http://snapshot.debian.org/archive/${s%_*}/20250515T175729Z/ ${s#*_} main"; \ + done >> /etc/apt/sources.list && \ + ( echo 'quiet "true";'; \ + echo 'APT::Get::Assume-Yes "true";'; \ + echo 'APT::Install-Recommends "false";'; \ + echo 'Acquire::Check-Valid-Until "false";'; \ + echo 'Acquire::Retries "5";'; \ + ) > /etc/apt/apt.conf.d/99cpython-portable && \ + rm -f /etc/apt/sources.list.d/* + +RUN apt-get update + +# Host building. +RUN apt-get install \ + bzip2 \ + ca-certificates \ + curl \ + gcc \ + g++ \ + libc6-dev \ + libffi-dev \ + make \ + patch \ + perl \ + pkg-config \ + tar \ + xz-utils \ + unzip \ + zip \ + zlib1g-dev + +RUN apt-get install \ + gcc-loongarch64-linux-gnu \ + libc6-dev-loong64-cross + +RUN cd /tmp && \ + curl -LO https://snapshot.debian.org/archive/debian-ports/20250515T194251Z/pool-loong64/main/libx/libxcrypt/libcrypt-dev_4.4.38-1_loong64.deb && \ + curl -LO https://snapshot.debian.org/archive/debian-ports/20250515T194251Z/pool-loong64/main/libx/libxcrypt/libcrypt1_4.4.38-1_loong64.deb && \ + dpkg -x libcrypt-dev_4.4.38-1_loong64.deb / && \ + dpkg -x libcrypt1_4.4.38-1_loong64.deb / && \ + rm -f /tmp/*.deb diff --git a/cpython-unix/build.py b/cpython-unix/build.py index 6f98e990..1ce804da 100755 --- a/cpython-unix/build.py +++ b/cpython-unix/build.py @@ -930,7 +930,7 @@ def build_cpython( "tk8.6", ] - if "-apple" not in target_triple: + if not all(s in target_triple for s in ("-apple", "loongarch64-")): python_info["tcl_library_paths"].append("Tix8.4.3") if "-apple" in target_triple: diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml index 3d69f049..e020a5ac 100644 --- a/cpython-unix/extension-modules.yml +++ b/cpython-unix/extension-modules.yml @@ -257,6 +257,7 @@ _decimal: - define: CONFIG_64=1 targets: - aarch64-.* + - loongarch64-unknown-linux.* - ppc64le-unknown-linux.* - riscv64-unknown-linux.* - s390x-unknown-linux-.* diff --git a/cpython-unix/patch-configure-add-loongarch-triplet.patch b/cpython-unix/patch-configure-add-loongarch-triplet.patch new file mode 100644 index 00000000..30b9e5a0 --- /dev/null +++ b/cpython-unix/patch-configure-add-loongarch-triplet.patch @@ -0,0 +1,50 @@ +diff --git a/configure b/configure +index b7be60e..d799415 100755 +--- a/configure ++++ b/configure +@@ -5261,6 +5261,20 @@ cat >> conftest.c <=6) && defined(_MIPSEL) +diff --git a/configure.ac b/configure.ac +index aa515da..b5bad6e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -779,6 +779,20 @@ cat >> conftest.c <=6) && defined(_MIPSEL) diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml index 1b47dba4..8720c27a 100644 --- a/cpython-unix/targets.yml +++ b/cpython-unix/targets.yml @@ -318,6 +318,46 @@ armv7-unknown-linux-gnueabihf: - zlib openssl_target: linux-armv4 +loongarch64-unknown-linux-gnu: + host_platforms: + - linux_x86_64 + pythons_supported: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + - '3.13' + - '3.14' + docker_image_suffix: .cross-loongarch64 + host_cc: /usr/bin/x86_64-linux-gnu-gcc + host_cxx: /usr/bin/x86_64-linux-gnu-g++ + target_cc: /usr/bin/loongarch64-linux-gnu-gcc + target_cxx: /usr/bin/loongarch64-linux-gnu-g++ + needs: + - autoconf + - bdb + - binutils + - bzip2 + - expat + - libedit + - libffi + - libX11 + - libXau + - libxcb + - m4 + - mpdecimal + - ncurses + - openssl-3.0 + - patchelf + - sqlite + - tcl + - tk + - uuid + - xorgproto + - xz + - zlib + openssl_target: linux64-loongarch64 + mips-unknown-linux-gnu: host_platforms: - linux_x86_64 diff --git a/docs/building.rst b/docs/building.rst index c6a07e25..eaad66c4 100644 --- a/docs/building.rst +++ b/docs/building.rst @@ -39,6 +39,7 @@ As are various other targets:: $ ./build-linux.py --target aarch64-unknown-linux-gnu $ ./build-linux.py --target armv7-unknown-linux-gnueabi $ ./build-linux.py --target armv7-unknown-linux-gnueabihf + $ ./build-linux.py --target loongarch64-unknown-linux-gnu $ ./build-linux.py --target mips-unknown-linux-gnu $ ./build-linux.py --target mipsel-unknown-linux-gnu $ ./build-linux.py --target ppc64le-unknown-linux-gnu diff --git a/src/release.rs b/src/release.rs index 60e46c99..c90a7a9c 100644 --- a/src/release.rs +++ b/src/release.rs @@ -166,6 +166,19 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: }, ); + h.insert( + "loongarch64-unknown-linux-gnu", + TripleRelease { + suffixes: linux_suffixes_nopgo.clone(), + install_only_suffix: "lto", + python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), + conditional_suffixes: vec![ConditionalSuffixes { + python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), + suffixes: linux_suffixes_nopgo_freethreaded.clone(), + }], + }, + ); + h.insert( "ppc64le-unknown-linux-gnu", TripleRelease { diff --git a/src/validation.rs b/src/validation.rs index 19aace00..f12e27ca 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -41,6 +41,7 @@ const RECOGNIZED_TRIPLES: &[&str] = &[ "i686-unknown-linux-gnu", // Note there's build support for mips* targets but they are not tested // See https://github.com/astral-sh/python-build-standalone/issues/412 + "loongarch64-unknown-linux-gnu", "mips-unknown-linux-gnu", "mipsel-unknown-linux-gnu", "mips64el-unknown-linux-gnuabi64", @@ -160,6 +161,10 @@ static GLIBC_MAX_VERSION_BY_TRIPLE: Lazy> = Lazy: ("armv7-unknown-linux-gnueabihf", "linux-arm"), ("i686-pc-windows-msvc", "win32"), ("i686-unknown-linux-gnu", "linux-i686"), + ("loongarch64-unknown-linux-gnu", "linux-loongarch64"), ("mips-unknown-linux-gnu", "linux-mips"), ("mipsel-unknown-linux-gnu", "linux-mipsel"), ("mips64el-unknown-linux-gnuabi64", "todo"), @@ -888,6 +895,7 @@ fn validate_elf>( "armv7-unknown-linux-gnueabi" => object::elf::EM_ARM, "armv7-unknown-linux-gnueabihf" => object::elf::EM_ARM, "i686-unknown-linux-gnu" => object::elf::EM_386, + "loongarch64-unknown-linux-gnu" => object::elf::EM_LOONGARCH, "mips-unknown-linux-gnu" => object::elf::EM_MIPS, "mipsel-unknown-linux-gnu" => object::elf::EM_MIPS, "mips64el-unknown-linux-gnuabi64" => 0,