Downstream cross-aarch64 recipes with a C++ Python extension (e.g. numba-cuda, libnvshmem) started failing at link time after python-feedstock's aarch64 build was flipped from cross to native. The compiler stack and the recipe-side sed are both unchanged; what changed is what CPython's own configure step emits into the sysconfigdata.
When it landed
The "go native for arm builds" change removed linux_aarch64: linux_64 from conda-forge.yml, landing on 2026-06-11 to 2026-06-12 across every currently-live branch except 3.12:
Each PR bundled the flip with an unrelated main change (version bump or openssl backport); the flip itself is a one-liner in conda-forge.yml.
Symptom (downstream cross-aarch64 link step)
$PREFIX/compiler_compat/ld: $BUILD_PREFIX/bin/../libexec/gcc/aarch64-conda-linux-gnu/14.3.0/liblto_plugin.so: error loading plugin: ... cannot open shared object file: No such file or directory
Misleading error — the actual issue is the aarch64 ld shim in $PREFIX/compiler_compat/ being handed an x86_64 LTO plugin path via --plugin.
Bisect (numba-cuda-feedstock main, last-green vs first-fail)
- gcc_impl_linux-aarch64 / binutils_impl_linux-aarch64 / ld_impl_linux-aarch64: identical (14.3.0=h77f067d_19 / 2.45.1=default_hc5fa074_102 / 2.45.1=default_h27e1c4c_102)
- python (linux-aarch64): 3.10.20=h28be5d3_0_cpython → 3.10.20=h4f76b5d_1_cpython
Extracting _sysconfigdata_aarch64_conda_linux_gnu.py (the "raw configure" variant, saved before the recipe-side sed) from each package:
- h28be5d3_0 (cross-built): 'CXX': 'aarch64-conda-linux-gnu-c++'
- h4f76b5d_1 (native-built): 'CXX': 'aarch64-conda-linux-gnu-c++ -pthread'
LDCXXSHARED = "$(CXX) -shared", so it picks up the same -pthread on native. Then recipe/build_base.sh#L453-L456:
sed -i.bak "s@-pthread@-pthread -B $PREFIX/compiler_compat@g" sysconfigfile
turns the default sysconfigdata's LDCXXSHARED into 'g++ -pthread -B $PREFIX/compiler_compat -shared'. Setuptools uses LDCXXSHARED verbatim for C++ extension links, so -B $PREFIX/compiler_compat reaches the cross-toolchain link line and routes ld through the aarch64 shim. On a linux-64 build host driving an x86_64 GCC, the aarch64 ld can't handle the x86_64 LTO plugin GCC hands it via --plugin, and the link fails.
Why C-only cross-builds haven't been failing the same way
LDSHARED has always had -B $PREFIX/compiler_compat in it too, but patch 0019-Fix-LDSHARED-when-CC-is-overriden-on-Linux-too.patch makes distutils' customize_compiler strip the sysconfig CC prefix off LDSHARED and replace it with os.environ['CC']. Since LDSHARED starts with exactly the sysconfig CC string ('gcc -pthread -B $PREFIX/compiler_compat'), the entire -pthread -B compiler_compat chunk is consumed along with gcc, leaving only -shared -Wl,... in the resulting command. No equivalent exists for LDCXXSHARED, so it's used as-is.
Why 3.12 isn't affected
The 3.12 branch of this feedstock still has linux_aarch64: linux_64 in conda-forge.yml — it wasn't included in the "go native" flip. Correspondingly, only linux_aarch64_python3.12 passes in numba-cuda-feedstock run 28638905979; all other Python versions fail on aarch64.
Confirmed affected feedstocks
Suggested fixes
- Extend patch 0019 to also strip the sysconfig CXX prefix off LDCXXSHARED — symmetric with the C side. Preserves the sed's intent for native/system-gcc users.
- Or scope the sed itself away from CXX/LDCXXSHARED so -pthread -B compiler_compat never enters those vars.
Happy to test either against numba-cuda-feedstock's CI once a rebuild is available.
Downstream cross-aarch64 recipes with a C++ Python extension (e.g. numba-cuda, libnvshmem) started failing at link time after python-feedstock's aarch64 build was flipped from cross to native. The compiler stack and the recipe-side sed are both unchanged; what changed is what CPython's own configure step emits into the sysconfigdata.
When it landed
The "go native for arm builds" change removed linux_aarch64: linux_64 from conda-forge.yml, landing on 2026-06-11 to 2026-06-12 across every currently-live branch except 3.12:
Each PR bundled the flip with an unrelated main change (version bump or openssl backport); the flip itself is a one-liner in conda-forge.yml.
Symptom (downstream cross-aarch64 link step)
Misleading error — the actual issue is the aarch64 ld shim in $PREFIX/compiler_compat/ being handed an x86_64 LTO plugin path via --plugin.
Bisect (numba-cuda-feedstock main, last-green vs first-fail)
Extracting _sysconfigdata_aarch64_conda_linux_gnu.py (the "raw configure" variant, saved before the recipe-side sed) from each package:
LDCXXSHARED = "$(CXX) -shared", so it picks up the same -pthread on native. Then recipe/build_base.sh#L453-L456:
sed -i.bak "s@-pthread@-pthread -B $PREFIX/compiler_compat@g" sysconfigfileturns the default sysconfigdata's LDCXXSHARED into 'g++ -pthread -B $PREFIX/compiler_compat -shared'. Setuptools uses LDCXXSHARED verbatim for C++ extension links, so -B $PREFIX/compiler_compat reaches the cross-toolchain link line and routes ld through the aarch64 shim. On a linux-64 build host driving an x86_64 GCC, the aarch64 ld can't handle the x86_64 LTO plugin GCC hands it via --plugin, and the link fails.
Why C-only cross-builds haven't been failing the same way
LDSHARED has always had -B $PREFIX/compiler_compat in it too, but patch 0019-Fix-LDSHARED-when-CC-is-overriden-on-Linux-too.patch makes distutils' customize_compiler strip the sysconfig CC prefix off LDSHARED and replace it with os.environ['CC']. Since LDSHARED starts with exactly the sysconfig CC string ('gcc -pthread -B $PREFIX/compiler_compat'), the entire -pthread -B compiler_compat chunk is consumed along with gcc, leaving only -shared -Wl,... in the resulting command. No equivalent exists for LDCXXSHARED, so it's used as-is.
Why 3.12 isn't affected
The 3.12 branch of this feedstock still has linux_aarch64: linux_64 in conda-forge.yml — it wasn't included in the "go native" flip. Correspondingly, only linux_aarch64_python3.12 passes in numba-cuda-feedstock run 28638905979; all other Python versions fail on aarch64.
Confirmed affected feedstocks
Suggested fixes
Happy to test either against numba-cuda-feedstock's CI once a rebuild is available.