[clang] [lld] [lld][WebAssembly] Default to -Bdynamic in wasm-ld (PR #206185)
Sam Clegg via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 29 08:54:48 PDT 2026
https://github.com/sbc100 updated https://github.com/llvm/llvm-project/pull/206185
>From 4e4b71fc407ee76381a91392fce48cfcfcd42b5f Mon Sep 17 00:00:00 2001
From: Sam Clegg <sbc at chromium.org>
Date: Fri, 26 Jun 2026 14:09:33 -0700
Subject: [PATCH] [lld][WebAssembly] Default to -Bdynamic in wasm-ld
Match the behavior of other linkers (like ELF) by defaulting to -Bdynamic.
Previously, wasm-ld defaulted to static linking, requiring explicit
-Bdynamic or -pie/-shared to enable dynamic linking. Now it defaults to
dynamic linking, unless -Bstatic or -r (relocatable) is specified.
Update ReleaseNotes.rst to document this change, and also note that the
experimental warning for PIC/dynamic linking has been removed.
---
clang/lib/Driver/ToolChains/WebAssembly.cpp | 4 ++++
clang/test/Driver/wasm-toolchain.c | 3 ++-
lld/docs/ReleaseNotes.rst | 4 ++++
lld/test/wasm/libsearch.s | 6 +++++-
lld/wasm/Config.h | 5 +----
lld/wasm/Driver.cpp | 6 ++----
6 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 7dabefbee7f79..f05056435ef11 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -121,6 +121,10 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
+ // Default to static linking for WASI targets.
+ if (ToolChain.getTriple().isOSWASI())
+ CmdArgs.push_back("-Bstatic");
+
// On `wasip2` the default linker is `wasm-component-ld` which wraps the
// execution of `wasm-ld`. Find `wasm-ld` and pass it as an argument of where
// to find it to avoid it needing to hunt and rediscover or search `PATH` for
diff --git a/clang/test/Driver/wasm-toolchain.c b/clang/test/Driver/wasm-toolchain.c
index c02a102fab081..8575b7414e43e 100644
--- a/clang/test/Driver/wasm-toolchain.c
+++ b/clang/test/Driver/wasm-toolchain.c
@@ -18,6 +18,7 @@
// RUN: | FileCheck -check-prefix=LINK %s
// LINK: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
// LINK: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins.a" "-o" "a.out"
+// LINK-NOT: "-Bstatic"
// A basic C link command-line with optimization with unknown OS.
@@ -31,7 +32,7 @@
// RUN: %clang -### --target=wasm32-wasi --sysroot=/foo %s 2>&1 \
// RUN: | FileCheck -check-prefix=LINK_KNOWN %s
// LINK_KNOWN: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
-// LINK_KNOWN: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins.a" "-o" "a.out"
+// LINK_KNOWN: wasm-ld{{.*}}" "-m" "wasm32" "-Bstatic" {{.*}} "-L/foo/lib/wasm32-wasi" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins.a" "-o" "a.out"
// -shared should be passed through to `wasm-ld` and include crt1-reactor.o with a known OS.
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index 058173413e41a..38d127f19f754 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -84,5 +84,9 @@ MachO Improvements
WebAssembly Improvements
------------------------
+* ``wasm-ld`` now defaults to ``-Bdynamic``, matching the behavior of other linkers.
+
+* The experimental warning for PIC/dynamic linking has been removed.
+
Fixes
#####
diff --git a/lld/test/wasm/libsearch.s b/lld/test/wasm/libsearch.s
index f22d450242136..d8ce4b2ed3d6b 100644
--- a/lld/test/wasm/libsearch.s
+++ b/lld/test/wasm/libsearch.s
@@ -43,8 +43,12 @@
// DYNAMIC: Symbols [
// DYNAMIC-NOT: Name: _static
-// Should prefer static to dynamic when linking regular executable.
+// Should prefer dynamic to static when linking regular executable (default).
// RUN: wasm-ld --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+
+// Should prefer static to dynamic when linking regular executable with -Bstatic.
+// RUN: wasm-ld --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -Bstatic -lls
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
// Should prefer dynamic when linking PIE.
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index f2f1b895f5b69..1dd54a3034531 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -84,10 +84,7 @@ struct Config {
bool stripAll;
bool stripDebug;
bool stackFirst;
- // Static linking is currently the default under WebAssembly. This may
- // change as some point in the future if dynamic linking becomes more widely
- // used.
- bool isStatic = true;
+ bool isStatic = false;
bool thinLTOEmitImportsFiles;
bool thinLTOEmitIndexFiles;
bool thinLTOIndexOnly;
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 9a2e3a82a9279..f7150b38f2502 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -578,6 +578,8 @@ static void readConfigs(opt::InputArgList &args) {
ctx.arg.optimize = args::getInteger(args, OPT_O, 1);
ctx.arg.outputFile = args.getLastArgValue(OPT_o);
ctx.arg.relocatable = args.hasArg(OPT_relocatable);
+ if (ctx.arg.relocatable)
+ ctx.arg.isStatic = true;
ctx.arg.rpath = args::getStrings(args, OPT_rpath);
ctx.arg.gcSections =
args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !ctx.arg.relocatable);
@@ -643,10 +645,6 @@ static void readConfigs(opt::InputArgList &args) {
if (ctx.arg.pageSize != 1 && ctx.arg.pageSize != WasmDefaultPageSize)
error("--page_size=N must be either 1 or 65536");
- // -Bdynamic by default if -pie or -shared is specified.
- if (ctx.arg.pie || ctx.arg.shared)
- ctx.arg.isStatic = false;
-
if (ctx.arg.maxMemory != 0 && ctx.arg.noGrowableMemory) {
// Erroring out here is simpler than defining precedence rules.
error("--max-memory is incompatible with --no-growable-memory");
More information about the cfe-commits
mailing list