Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/build/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ export interface LinkOpts {
*/
implicitInputs?: string[];
/** Output linker map to this path (for debugging symbol bloat). */
linkerMapOutput?: string;
linkerMapOutput?: string | undefined;
}

/**
Expand Down
5 changes: 4 additions & 1 deletion scripts/build/deps/webkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,10 @@
// PIC codegen here is pure overhead (GOT indirections + ~550 KB of
// RW-segment vtables that would otherwise be shared RO). Android stays
// PIC because bionic mandates PIE.
if (cfg.unix && cfg.abi !== "android") optFlags.push("-fno-pic", "-fno-pie");
// -no-pie rides along in CMAKE_C_FLAGS so try_compile() probes link on
// PIE-default distros — without it the driver still passes -pie and the
// -fno-pic probe object fails R_X86_64_32S relocation, killing FindThreads.
if (cfg.unix && cfg.abi !== "android") optFlags.push("-fno-pic", "-fno-pie", "-no-pie");

Check failure on line 238 in scripts/build/deps/webkit.ts

View check run for this annotation

Claude / Claude Code Review

-no-pie passed on darwin via cfg.unix gate

`cfg.unix` includes darwin (config.ts:596: `unix = linux || darwin || freebsd`), so this now passes `-no-pie` to the WebKit cmake on macOS. Everywhere else in the codebase the link-time `-no-pie` is deliberately gated to linux/freebsd only (flags.ts:943-944, flags.ts:1046-1047, source.ts:1210-1212) — on arm64 darwin, clang's Darwin driver forwards this to ld64 as `-no_pie`, which ld64 rejects with "-no_pie cannot be used with arm64", so every `try_compile()` probe fails — the exact regression th

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 cfg.unix includes darwin (config.ts:596: unix = linux || darwin || freebsd), so this now passes -no-pie to the WebKit cmake on macOS. Everywhere else in the codebase the link-time -no-pie is deliberately gated to linux/freebsd only (flags.ts:943-944, flags.ts:1046-1047, source.ts:1210-1212) — on arm64 darwin, clang's Darwin driver forwards this to ld64 as -no_pie, which ld64 rejects with "-no_pie cannot be used with arm64", so every try_compile() probe fails — the exact regression this PR is fixing on Linux. Gate the -no-pie push on (cfg.linux || cfg.freebsd) (or !cfg.darwin) to match flags.ts; the R_X86_64_32S rationale is ELF-specific and doesn't apply to Mach-O anyway.

Extended reasoning...

What the bug is

The new -no-pie flag is pushed under cfg.unix && cfg.abi !== "android". Per config.ts:596, const unix = linux || darwin || freebsd, so this gate includes darwin. The flag therefore lands in CMAKE_C_FLAGS / CMAKE_CXX_FLAGS for local-WebKit builds on macOS, where it was never passed before.

This diverges from the codebase's established pattern: the link-time -no-pie is gated on c.linux && c.abi !== "android" at flags.ts:943-944 and on c.freebsd at flags.ts:1046-1047. Darwin only ever gets the compile-mode -fno-pic -fno-pie (flags.ts:533-534, source.ts:1210-1212, source.ts:1494-1495) — never the link-mode -no-pie. The pre-PR webkit.ts line matched that pattern exactly.

Why it manifests

On darwin, cfg.ld is empty (config.ts:184: "May be empty on darwin (clang invokes ld)"), and source.ts:1135 only sets CMAKE_EXE_LINKER_FLAGS=--ld-path=... when cfg.linux. So WebKit's nested-cmake try_compile() probes on macOS link via clang's Darwin driver → Apple ld64, not lld.

CMake's try_compile() includes CMAKE_C_FLAGS in the <FLAGS> slot for both the compile and the link of the probe executable. When clang's Darwin driver sees -no-pie on a link line, it translates it to ld64's spelling -no_pie. On arm64, ld64 hard-errors with "-no_pie cannot be used with arm64" (arm64 macOS mandates PIE). The -Qunused-arguments that WebKit prepends only suppresses clang's unused-argument compile warning; it does not stop the driver from forwarding -no_pie to the linker.

Nothing filters this out on the way to cmake: source.ts:1225-1227 appends spec.args (which carries webkit's CMAKE_C_FLAGS=optFlagStr) last, so it overrides the global CMAKE_C_FLAGS and the -no-pie definitely reaches darwin's configure.

Step-by-step proof

  1. Apple Silicon dev runs bun run build:local --target=configure-WebKit (or any local-WebKit build). cfg.darwin = true, so cfg.unix = true, cfg.abi !== "android" → optFlags gets -fno-pic -fno-pie -no-pie.
  2. args.CMAKE_C_FLAGS = optFlagStr is passed to the nested cmake (source.ts appends spec.args last, so it sticks).
  3. CMake runs FindThreads → try_compile() compiles a probe with -fno-pic -fno-pie -no-pie -c probe.c -o probe.o (fine), then links with clang ... -fno-pic -fno-pie -no-pie probe.o -o probe.
  4. clang's Darwin toolchain forwards -no-pie → -no_pie to ld64.
  5. ld64 on arm64: ld: -no_pie cannot be used with arm64 → link fails → Threads_FOUND = FALSE.
  6. FindThreads is REQUIRED → CMake Error ... FindThreads → configure aborts.

This is exactly the regression class the PR is fixing on Linux, transplanted onto macOS. CI won't catch it because the prebuilt path returns {kind: "none"} before optFlags is built; only local-mode developers on Apple Silicon hit it.

Why the flag is unnecessary on darwin anyway

The PR's stated rationale — driver-default -pie + -fno-pic object → R_X86_64_32S relocation failure — is ELF-specific. macOS uses Mach-O, Apple clang does not default-link try_compile probes as PIE in a way that conflicts with -fno-pic, and there is no equivalent failure mode. So even setting aside the ld64 error, -no-pie provides zero benefit on darwin while creating risk.

Fix

Match the rest of the codebase by gating the link-mode flag separately:

if (cfg.unix && cfg.abi !== "android") optFlags.push("-fno-pic", "-fno-pie");
if ((cfg.linux || cfg.freebsd) && cfg.abi !== "android") optFlags.push("-no-pie");

(or equivalently keep one line and add -no-pie under !cfg.darwin). This mirrors flags.ts:943-944 / flags.ts:1046-1047 and keeps the Linux fix intact.

if (cfg.lto) optFlags.push("-flto=full");
if (cfg.pgoGenerate) optFlags.push(`-fprofile-generate=${cfg.pgoGenerate}`);
if (cfg.pgoUse) {
Expand Down
Loading