33extern crate build_common;
44
55use build_common:: { find_rust_lld_dir, generate_and_configure_header} ;
6- use std:: { env, fmt:: Display , path:: PathBuf , process:: Command } ;
7-
8- #[ derive( Debug , Eq , PartialEq , Ord , PartialOrd ) ]
9- struct LldVersion {
10- major : u32 ,
11- minor : u32 ,
12- }
13-
14- impl Display for LldVersion {
15- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
16- write ! ( f, "{}.{}" , self . major, self . minor)
17- }
18- }
19-
20- /// Parse the major and minor version from `ld.lld --version` output.
21- ///
22- /// Typical formats:
23- /// "LLD 18.1.3 (compatible with GNU linkers)"
24- /// "LLD 19.1.0"
25- fn system_lld_version ( ) -> Option < LldVersion > {
26- let output = Command :: new ( "ld.lld" ) . arg ( "--version" ) . output ( ) . ok ( ) ?;
27- if !output. status . success ( ) {
28- return None ;
29- }
30- String :: from_utf8_lossy ( & output. stdout )
31- . split_whitespace ( )
32- . find_map ( |tok| {
33- let mut splitted = tok. split ( '.' ) ;
34- let major = splitted. next ( ) ?. parse :: < u32 > ( ) . ok ( ) ?;
35- let minor = splitted. next ( ) ?. parse :: < u32 > ( ) . ok ( ) ?;
36-
37- Some ( LldVersion { major, minor } )
38- } )
39- }
40-
41- /// TLSDESC is supported in LLD from version 18.1.
42- const MIN_LLD_VERSION_FOR_TLSDESC : LldVersion = LldVersion {
43- major : 18 ,
44- minor : 1 ,
45- } ;
46-
47- /// Validate that a suitable LLD is available for cross-language LTO.
48- ///
49- /// Returns the rust-lld `gcc-ld/` directory if found; `None` means the system
50- /// `ld.lld` will be used instead. Panics with a clear message when the
51- /// requirements are not met.
52- fn resolve_lld_for_inline ( target_arch : & str ) -> Option < PathBuf > {
53- if let Some ( dir) = find_rust_lld_dir ( ) {
54- return Some ( dir) ;
55- }
56-
57- match system_lld_version ( ) {
58- Some ( v) if target_arch != "x86_64" || v >= MIN_LLD_VERSION_FOR_TLSDESC => None ,
59- Some ( v) => panic ! (
60- "LIBDD_OTEL_THREAD_CTX_INLINE requires LLD >= {MIN_LLD_VERSION_FOR_TLSDESC} on \
61- x86-64 (for -mllvm -enable-tlsdesc), but system ld.lld is version {v}. \
62- Install a newer LLD or use a Rust toolchain that bundles rust-lld."
63- ) ,
64- None => panic ! (
65- "LIBDD_OTEL_THREAD_CTX_INLINE requires LLD for cross-language LTO, but neither \
66- rust-lld nor a system ld.lld was found."
67- ) ,
68- }
69- }
6+ use std:: env;
707
718fn main ( ) {
729 generate_and_configure_header ( "otel-thread-ctx.h" ) ;
@@ -76,11 +13,7 @@ fn main() {
7613 return ;
7714 }
7815
79- println ! ( "cargo:rerun-if-env-changed=LIBDD_OTEL_THREAD_CTX_INLINE" ) ;
80-
81- let inline_mode = env:: var ( "LIBDD_OTEL_THREAD_CTX_INLINE" ) . is_ok_and ( |v| v == "1" ) ;
8216 let manifest_dir = env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) ;
83- let target_arch = env:: var ( "CARGO_CFG_TARGET_ARCH" ) . unwrap ( ) ;
8417
8518 // Export the TLSDESC thread-local variable to the dynamic symbol table so external readers
8619 // (e.g. the eBPF profiler) can discover it. Rust's cdylib linker applies a version script with
@@ -93,32 +26,10 @@ fn main() {
9326 // Merging multiple version scripts is not supported by GNU ld, so we need lld. We prefer the
9427 // toolchain's bundled rust-lld (LLD 19+ since Rust 1.84) over the system lld (if it even
9528 // exists). If rust-lld is not found we fall back to whatever `lld` the system provides.
96-
97- // If `LIBDD_OTEL_THREAD_CTX_INLINE` is set to `1`, we try to inline the C shim. See the README
98- // for more details.
99- if inline_mode {
100- let rust_lld_dir = resolve_lld_for_inline ( & target_arch) ;
101-
102- // Emit link args for ALL link types (not just cdylib) so that test binaries also link
103- // correctly when RUSTFLAGS sets clang as the linker (in practice we should only build/care
104- // about the shared object file in inline mode).
105- if let Some ( dir) = rust_lld_dir {
106- println ! ( "cargo:rustc-link-arg=-B{}" , dir. display( ) ) ;
107- }
108- println ! ( "cargo:rustc-link-arg=-fuse-ld=lld" ) ;
109-
110- // On x86-64, tell the LLVM backend to use TLSDESC during LTO codegen.
111- // On aarch64 TLSDESC is the default and the only model.
112- if target_arch == "x86_64" {
113- println ! ( "cargo:rustc-link-arg=-Wl,-mllvm,-enable-tlsdesc" ) ;
114- }
115- } else {
116- // Default mode: only the cdylib needs lld (for the version script).
117- if let Some ( gcc_ld_dir) = find_rust_lld_dir ( ) {
118- println ! ( "cargo:rustc-cdylib-link-arg=-B{}" , gcc_ld_dir. display( ) ) ;
119- }
120- println ! ( "cargo:rustc-cdylib-link-arg=-fuse-ld=lld" ) ;
29+ if let Some ( gcc_ld_dir) = find_rust_lld_dir ( ) {
30+ println ! ( "cargo:rustc-cdylib-link-arg=-B{}" , gcc_ld_dir. display( ) ) ;
12131 }
32+ println ! ( "cargo:rustc-cdylib-link-arg=-fuse-ld=lld" ) ;
12233
12334 println ! (
12435 "cargo:rustc-cdylib-link-arg=-Wl,--version-script={manifest_dir}/tls-dynamic-list.txt"
0 commit comments