Skip to content

Commit 712caea

Browse files
committed
Prefer a newer libclang if available...
1 parent 8979e99 commit 712caea

2 files changed

Lines changed: 34 additions & 52 deletions

File tree

Modules/cpython-sys/bindgen-fallback/stdatomic.h

Lines changed: 0 additions & 44 deletions
This file was deleted.

Modules/cpython-sys/build.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ fn main() {
1010
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
1111
let builddir = env::var("PYTHON_BUILD_DIR").ok();
1212
emit_rerun_instructions(builddir.as_deref());
13+
prefer_newest_libclang();
1314
if gil_disabled(srcdir, builddir.as_deref()) {
1415
println!("cargo:rustc-cfg=py_gil_disabled");
1516
}
@@ -40,6 +41,39 @@ fn emit_rerun_instructions(builddir: Option<&str>) {
4041
}
4142
}
4243

44+
/// When LIBCLANG_PATH is not already set, scan /usr/lib/llvm-*/lib for the
45+
/// newest available libclang and point bindgen at it. Ubuntu 24.04 ships
46+
/// libclang-18 by default, which has broken headers (stdatomic.h, mmintrin.h).
47+
/// CI jobs that install a newer LLVM (e.g. clang-20) also get a working
48+
/// libclang in /usr/lib/llvm-20/lib -- we just need to tell bindgen about it.
49+
fn prefer_newest_libclang() {
50+
if env::var_os("LIBCLANG_PATH").is_some() {
51+
return;
52+
}
53+
let base = Path::new("/usr/lib");
54+
let mut best: Option<(u32, PathBuf)> = None;
55+
if let Ok(entries) = std::fs::read_dir(base) {
56+
for entry in entries.flatten() {
57+
let name = entry.file_name();
58+
let name = name.to_string_lossy();
59+
if let Some(ver_str) = name.strip_prefix("llvm-") {
60+
if let Ok(ver) = ver_str.parse::<u32>() {
61+
let lib_dir = entry.path().join("lib");
62+
if lib_dir.is_dir() {
63+
if best.as_ref().map_or(true, |(v, _)| ver > *v) {
64+
best = Some((ver, lib_dir));
65+
}
66+
}
67+
}
68+
}
69+
}
70+
}
71+
if let Some((ver, lib_dir)) = best {
72+
eprintln!("cpython-sys: using libclang from llvm-{ver}");
73+
env::set_var("LIBCLANG_PATH", &lib_dir);
74+
}
75+
}
76+
4377
fn gil_disabled(srcdir: &Path, builddir: Option<&str>) -> bool {
4478
let mut candidates = Vec::new();
4579
if let Some(build) = builddir {
@@ -151,14 +185,6 @@ fn generate_c_api_bindings(srcdir: &Path, builddir: Option<&str>, out_path: &Pat
151185
builder = builder.clang_arg(format!("-I{}", dir.display()));
152186
}
153187

154-
// Provide a fallback <stdatomic.h> for libclang versions that ship a
155-
// broken one (e.g. libclang-18 on Ubuntu 24.04). Using -isystem places
156-
// it after -I paths but before the default system headers, so it only
157-
// takes effect when the real <stdatomic.h> is unusable.
158-
let fallback_dir =
159-
PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("bindgen-fallback");
160-
builder = builder.clang_arg(format!("-isystem{}", fallback_dir.display()));
161-
162188
builder = add_target_clang_args(builder, builddir);
163189

164190
let bindings = builder

0 commit comments

Comments
 (0)