Skip to content

Commit 8c593c8

Browse files
committed
Detect LLVM triple and handle NDK sysroot
1 parent cb43e5b commit 8c593c8

5 files changed

Lines changed: 96 additions & 19 deletions

File tree

‎Makefile.pre.in‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ CARGO_PROFILE=@CARGO_PROFILE@
6464
CARGO_TARGET=@CARGO_TARGET@
6565
CARGO_TARGET_LINKER_ENV=@CARGO_TARGET_LINKER_ENV@
6666
CARGO_DYLIB_SUFFIX=@CARGO_DYLIB_SUFFIX@
67+
LLVM_TARGET=@LLVM_TARGET@
6768
RUST_STATICLIB_DEP=@RUST_STATICLIB_DEP@
6869

6970
GNULD= @GNULD@
@@ -3378,7 +3379,7 @@ Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h
33783379
# Module dependencies and platform-specific files
33793380

33803381
cpython-sys: Modules/cpython-sys/Cargo.toml Modules/cpython-sys/build.rs Modules/cpython-sys/wrapper.h Modules/cpython-sys/parser.h
3381-
CARGO_TARGET_DIR=$(abs_builddir)/target PYTHON_BUILD_DIR=$(abs_builddir) PY_CPPFLAGS="$(CPPFLAGS)" $(CARGO_HOME)/bin/cargo build --lib --locked --package cpython-sys --profile $(CARGO_PROFILE) $(if $(CARGO_TARGET),--target=$(CARGO_TARGET)) --manifest-path $(srcdir)/Cargo.toml
3382+
CARGO_TARGET_DIR=$(abs_builddir)/target PYTHON_BUILD_DIR=$(abs_builddir) PY_CC="$(CC)" PY_CPPFLAGS="$(CPPFLAGS)" LLVM_TARGET="$(LLVM_TARGET)" $(CARGO_HOME)/bin/cargo build --lib --locked --package cpython-sys --profile $(CARGO_PROFILE) $(if $(CARGO_TARGET),--target=$(CARGO_TARGET)) --manifest-path $(srcdir)/Cargo.toml
33823383

33833384
RUST_STATICLIB_A= target/$(if $(CARGO_TARGET),$(CARGO_TARGET)/$(CARGO_TARGET_DIR),$(CARGO_TARGET_DIR))/libcpython_rust_staticlib.a
33843385

‎Misc/platform_triplet.c‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
*
44
* Also detects the closest Rust target triple for cargo/rustc:
55
* cc -E Misc/platform_triplet.c | grep '^RUST_TARGET=' | tr -d ' '
6+
*
7+
* And the LLVM/clang target triple (for bindgen), only when it differs
8+
* from RUST_TARGET:
9+
* cc -E Misc/platform_triplet.c | grep '^LLVM_TARGET=' | tr -d ' '
610
*/
711
#undef bfin
812
#undef cris
@@ -145,6 +149,7 @@ RUST_TARGET=arm-linux-androideabi
145149
# elif defined(_ABI64) && _MIPS_SIM == _ABI64
146150
# define LIBC_MIPS musl
147151
# define RUST_LIBC_MIPS muslabi64
152+
# define LLVM_LIBC_MIPS musl
148153
# else
149154
# error unknown mips sim value
150155
# endif
@@ -242,12 +247,18 @@ RUST_TARGET=mipsisa32r6-unknown-linux-RUST_LIBC_MIPS
242247
# if defined(_MIPSEL) && defined(__mips64)
243248
PLATFORM_TRIPLET=mips64el-linux-LIBC_MIPS
244249
RUST_TARGET=mips64el-unknown-linux-RUST_LIBC_MIPS
250+
# ifdef LLVM_LIBC_MIPS
251+
LLVM_TARGET=mips64el-unknown-linux-LLVM_LIBC_MIPS
252+
# endif
245253
# elif defined(_MIPSEL)
246254
PLATFORM_TRIPLET=mipsel-linux-LIBC_MIPS
247255
RUST_TARGET=mipsel-unknown-linux-RUST_LIBC_MIPS
248256
# elif defined(__mips64)
249257
PLATFORM_TRIPLET=mips64-linux-LIBC_MIPS
250258
RUST_TARGET=mips64-unknown-linux-RUST_LIBC_MIPS
259+
# ifdef LLVM_LIBC_MIPS
260+
LLVM_TARGET=mips64-unknown-linux-LLVM_LIBC_MIPS
261+
# endif
251262
# else
252263
PLATFORM_TRIPLET=mips-linux-LIBC_MIPS
253264
RUST_TARGET=mips-unknown-linux-RUST_LIBC_MIPS
@@ -286,9 +297,11 @@ RUST_TARGET=sparc-unknown-linux-RUST_LIBC
286297
# if __riscv_xlen == 32
287298
PLATFORM_TRIPLET=riscv32-linux-LIBC
288299
RUST_TARGET=riscv32gc-unknown-linux-RUST_LIBC
300+
LLVM_TARGET=riscv32-unknown-linux-RUST_LIBC
289301
# elif __riscv_xlen == 64
290302
PLATFORM_TRIPLET=riscv64-linux-LIBC
291303
RUST_TARGET=riscv64gc-unknown-linux-RUST_LIBC
304+
LLVM_TARGET=riscv64-unknown-linux-RUST_LIBC
292305
# else
293306
# error unknown platform triplet
294307
# endif
@@ -326,21 +339,26 @@ RUST_TARGET=i686-unknown-hurd-gnu
326339
# if __x86_64__
327340
PLATFORM_TRIPLET=x86_64-iphonesimulator
328341
RUST_TARGET=x86_64-apple-ios
342+
LLVM_TARGET=x86_64-apple-ios-simulator
329343
# else
330344
PLATFORM_TRIPLET=arm64-iphonesimulator
331345
RUST_TARGET=aarch64-apple-ios-sim
346+
LLVM_TARGET=arm64-apple-ios-simulator
332347
# endif
333348
# else
334349
PLATFORM_TRIPLET=arm64-iphoneos
335350
RUST_TARGET=aarch64-apple-ios
351+
LLVM_TARGET=arm64-apple-ios
336352
# endif
337353
// Older macOS SDKs do not define TARGET_OS_OSX
338354
# elif !defined(TARGET_OS_OSX) || TARGET_OS_OSX
339355
PLATFORM_TRIPLET=darwin
340356
# if defined(__x86_64__)
341357
RUST_TARGET=x86_64-apple-darwin
358+
LLVM_TARGET=x86_64-apple-macosx
342359
# elif defined(__aarch64__)
343360
RUST_TARGET=aarch64-apple-darwin
361+
LLVM_TARGET=arm64-apple-macosx
344362
# else
345363
RUST_TARGET=unknown
346364
# endif
@@ -358,6 +376,7 @@ RUST_TARGET=wasm32-unknown-emscripten
358376
# if defined(_REENTRANT)
359377
PLATFORM_TRIPLET=wasm32-wasi-threads
360378
RUST_TARGET=wasm32-wasip1-threads
379+
LLVM_TARGET=wasm32-wasi
361380
# else
362381
PLATFORM_TRIPLET=wasm32-wasi
363382
RUST_TARGET=wasm32-wasip1

‎Modules/cpython-sys/build.rs‎

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,27 +40,70 @@ fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Pat
4040
builder = builder.clang_arg("-w");
4141

4242
// Tell clang the correct target triple for cross-compilation.
43-
// Without this, bindgen uses the host target which causes errors like
44-
// "thread-local storage is not supported" on iOS or missing headers
45-
// on Android/WASI.
46-
if let Ok(target) = env::var("TARGET") {
43+
// LLVM_TARGET is the clang/LLVM triple which may differ from the Rust
44+
// target (e.g. arm64-apple-macosx vs aarch64-apple-darwin, or
45+
// riscv64-unknown-linux-gnu vs riscv64gc-unknown-linux-gnu).
46+
// Falls back to Cargo's TARGET if LLVM_TARGET is not set.
47+
let target = env::var("LLVM_TARGET")
48+
.or_else(|_| env::var("TARGET"))
49+
.unwrap_or_default();
50+
if !target.is_empty() {
4751
builder = builder.clang_arg(format!("--target={}", target));
4852
}
4953

50-
// Forward cross-compilation flags (include paths, defines, sysroot)
51-
// from CPython's CPPFLAGS. These are needed so bindgen's clang can
52-
// find system headers (e.g. assert.h) when cross-compiling for
53-
// Android NDK, WASI, etc.
54-
if let Ok(cppflags) = env::var("PY_CPPFLAGS") {
55-
if let Some(flags) = shlex::split(&cppflags) {
56-
for flag in &flags {
57-
if flag.starts_with("-I")
58-
|| flag.starts_with("-D")
59-
|| flag.starts_with("--sysroot")
60-
|| flag.starts_with("-isysroot")
61-
|| flag.starts_with("-isystem")
62-
{
63-
builder = builder.clang_arg(flag);
54+
// Extract cross-compilation flags from the C compiler command (PY_CC)
55+
// and preprocessor flags (PY_CPPFLAGS). These provide the sysroot and
56+
// include paths that bindgen's clang needs to find system headers when
57+
// cross-compiling.
58+
//
59+
// - WASI: the sysroot is embedded in CC ("clang --sysroot=...")
60+
// - iOS: -isysroot in CPPFLAGS points to the SDK
61+
let mut have_sysroot = false;
62+
for env_name in ["PY_CC", "PY_CPPFLAGS"] {
63+
if let Ok(value) = env::var(env_name) {
64+
if let Some(flags) = shlex::split(&value) {
65+
let mut iter = flags.iter().peekable();
66+
while let Some(flag) = iter.next() {
67+
if flag.starts_with("--sysroot")
68+
|| flag.starts_with("-isysroot")
69+
{
70+
builder = builder.clang_arg(flag);
71+
have_sysroot = true;
72+
// Handle "-isysroot <path>" (space-separated)
73+
if flag == "-isysroot" || flag == "--sysroot" {
74+
if let Some(path) = iter.next() {
75+
builder = builder.clang_arg(path);
76+
}
77+
}
78+
} else if flag.starts_with("-I")
79+
|| flag.starts_with("-D")
80+
|| flag.starts_with("-isystem")
81+
{
82+
builder = builder.clang_arg(flag);
83+
}
84+
}
85+
}
86+
}
87+
}
88+
89+
// Android NDK: the cross-compiler binary knows its own sysroot
90+
// implicitly, but bindgen's libclang does not. The NDK sysroot is
91+
// at .../toolchains/llvm/prebuilt/<host>/sysroot, which is a sibling
92+
// of the bin/ directory containing the compiler.
93+
if !have_sysroot && target.contains("android") {
94+
if let Ok(cc) = env::var("PY_CC") {
95+
if let Some(parts) = shlex::split(&cc) {
96+
if let Some(binary) = parts.first() {
97+
let cc_path = Path::new(binary);
98+
if let Some(bin_dir) = cc_path.parent() {
99+
let sysroot = bin_dir.with_file_name("sysroot");
100+
if sysroot.is_dir() {
101+
builder = builder.clang_arg(format!(
102+
"--sysroot={}",
103+
sysroot.display()
104+
));
105+
}
106+
}
64107
}
65108
}
66109
}

‎configure‎

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎configure.ac‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,12 @@ if $CPP $CPPFLAGS $srcdir/Misc/platform_triplet.c >conftest.out 2>/dev/null; the
11561156
PLATFORM_TRIPLET="${PLATFORM_TRIPLET@%:@PLATFORM_TRIPLET=}"
11571157
RUST_TARGET=`grep '^RUST_TARGET=' conftest.out | tr -d ' '`
11581158
RUST_TARGET="${RUST_TARGET@%:@RUST_TARGET=}"
1159+
dnl LLVM_TARGET is only emitted when it differs from RUST_TARGET
1160+
LLVM_TARGET=`grep '^LLVM_TARGET=' conftest.out | tr -d ' '`
1161+
LLVM_TARGET="${LLVM_TARGET@%:@LLVM_TARGET=}"
1162+
if test -z "$LLVM_TARGET"; then
1163+
LLVM_TARGET="$RUST_TARGET"
1164+
fi
11591165
AC_MSG_RESULT([$PLATFORM_TRIPLET])
11601166
else
11611167
AC_MSG_RESULT([none])
@@ -4372,6 +4378,7 @@ AC_SUBST([CARGO_PROFILE])
43724378
AC_SUBST([CARGO_TARGET])
43734379
AC_SUBST([CARGO_TARGET_LINKER_ENV])
43744380
AC_SUBST([CARGO_DYLIB_SUFFIX])
4381+
AC_SUBST([LLVM_TARGET])
43754382

43764383

43774384
dnl detect sqlite3 from Emscripten emport

0 commit comments

Comments
 (0)