Skip to content

Commit 9e52070

Browse files
authored
fix: shared-library-safe V8 TLS on Linux via v8_monolithic_for_shared_library (#2008)
On Linux, V8's default "local-exec" TLS model emits R_X86_64_TPOFF32 relocations against thread-locals such as g_current_isolate_. lld refuses to place those in a -shared object, so downstream crates that link the rusty_v8 static archive into a cdylib fail to link. The previous attempt injected `extra_cflags=["-DV8_TLS_USED_IN_LIBRARY"]`, but `extra_cflags` is not a declared GN build arg in the chromium_build fork, so the define never reached V8's compilation and the archive still carried TPOFF32 relocations. Instead set the V8-sanctioned `v8_monolithic_for_shared_library=true` GN arg, which routes the V8_TLS_USED_IN_LIBRARY define into both internal_config and the features config — covering V8's own sources and rusty_v8's bindings alike — switching to the local-dynamic TLS model with an out-of-line accessor.
1 parent 7e2d4a2 commit 9e52070

1 file changed

Lines changed: 18 additions & 26 deletions

File tree

build.rs

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -353,33 +353,25 @@ fn build_v8(is_asan: bool) {
353353
println!("cargo:warning=Not using sccache or ccache");
354354
}
355355

356-
// Use the shared-library-safe TLS mode by default on Linux so downstream
357-
// cdylibs can link rusty_v8 archives. Skip injection when GN_ARGS already
358-
// sets V8_TLS_USED_IN_LIBRARY.
359-
let needs_tls_define = target_os == "linux";
360-
let mut tls_define_injected = false;
361-
if let Ok(raw_gn_args) = env::var("GN_ARGS")
362-
&& !raw_gn_args.trim().is_empty()
363-
{
364-
if raw_gn_args.contains("V8_TLS_USED_IN_LIBRARY") {
365-
tls_define_injected = true;
366-
gn_args.push(raw_gn_args);
367-
} else if needs_tls_define && raw_gn_args.contains("extra_cflags=[") {
368-
// Prepend our define into the existing extra_cflags array so we don't
369-
// silently override the user's flags with a second assignment.
370-
let modified = raw_gn_args.replacen(
371-
"extra_cflags=[",
372-
r#"extra_cflags=["-DV8_TLS_USED_IN_LIBRARY","#,
373-
1,
374-
);
375-
tls_define_injected = true;
376-
gn_args.push(modified);
377-
} else {
378-
gn_args.push(raw_gn_args);
379-
}
356+
// Forward caller-provided GN args verbatim.
357+
let gn_args_env = env::var("GN_ARGS").unwrap_or_default();
358+
if !gn_args_env.trim().is_empty() {
359+
gn_args.push(gn_args_env.clone());
380360
}
381-
if needs_tls_define && !tls_define_injected {
382-
gn_args.push(r#"extra_cflags=["-DV8_TLS_USED_IN_LIBRARY"]"#.to_string());
361+
362+
// rusty_v8 ships a single static archive that downstream crates may link
363+
// into a shared library (cdylib). On Linux, V8's default "local-exec" TLS
364+
// model emits R_X86_64_TPOFF32 relocations against thread-locals such as
365+
// `g_current_isolate_`, which lld refuses to place in a `-shared` object,
366+
// so any cdylib that links the archive fails to link. Enabling this V8 GN
367+
// arg routes the `V8_TLS_USED_IN_LIBRARY` define into both `internal_config`
368+
// and the `features` config, switching V8 to the shared-library-safe TLS
369+
// path (local-dynamic model + out-of-line accessor) uniformly across V8's
370+
// own sources and rusty_v8's bindings.
371+
if target_os == "linux"
372+
&& !gn_args_env.contains("v8_monolithic_for_shared_library")
373+
{
374+
gn_args.push("v8_monolithic_for_shared_library=true".to_string());
383375
}
384376
// cross-compilation setup
385377
if target_arch == "aarch64" {

0 commit comments

Comments
 (0)