Skip to content

Commit d66121d

Browse files
authored
[WebAssembly] Change the default linker for wasm32-wasip2 (llvm#84569)
This commit changes the default linker in the WebAssembly toolchain for the `wasm32-wasip2` target. This target is being added to the WebAssembly/wasi-sdk and WebAssembly/wasi-libc projects to target the Component Model by default, in contrast with the preexisting `wasm32-wasi` target (in the process of being renamed to `wasm32-wasip1`) which outputs a core WebAssembly module by default. The `wasm-component-ld` project currently lives in my GitHub account at https://github.com/alexcrichton/wasm-component-ld and isn't necessarily "official" yet, but it's expected to continue to evolve as the `wasm32-wasip2` target continues to shape up and evolve.
1 parent 5373daa commit d66121d

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

clang/lib/Driver/ToolChains/WebAssembly.cpp

+25-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,15 @@ std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
4444
llvm::sys::fs::can_execute(UseLinker))
4545
return std::string(UseLinker);
4646

47-
// Accept 'lld', and 'ld' as aliases for the default linker
48-
if (UseLinker != "lld" && UseLinker != "ld")
47+
// Interpret 'lld' as explicitly requesting `wasm-ld`, so look for that
48+
// linker. Note that for `wasm32-wasip2` this overrides the default linker
49+
// of `wasm-component-ld`.
50+
if (UseLinker == "lld") {
51+
return ToolChain.GetProgramPath("wasm-ld");
52+
}
53+
54+
// Allow 'ld' as an alias for the default linker
55+
if (UseLinker != "ld")
4956
ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name)
5057
<< A->getAsString(Args);
5158
}
@@ -73,6 +80,16 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
7380
if (Args.hasArg(options::OPT_s))
7481
CmdArgs.push_back("--strip-all");
7582

83+
// On `wasip2` the default linker is `wasm-component-ld` which wraps the
84+
// execution of `wasm-ld`. Find `wasm-ld` and pass it as an argument of where
85+
// to find it to avoid it needing to hunt and rediscover or search `PATH` for
86+
// where it is.
87+
if (llvm::sys::path::stem(Linker).ends_with_insensitive(
88+
"wasm-component-ld")) {
89+
CmdArgs.push_back("--wasm-ld-path");
90+
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetProgramPath("wasm-ld")));
91+
}
92+
7693
Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
7794

7895
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
@@ -221,6 +238,12 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
221238
}
222239
}
223240

241+
const char *WebAssembly::getDefaultLinker() const {
242+
if (getOS() == "wasip2")
243+
return "wasm-component-ld";
244+
return "wasm-ld";
245+
}
246+
224247
bool WebAssembly::IsMathErrnoDefault() const { return false; }
225248

226249
bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; }

clang/lib/Driver/ToolChains/WebAssembly.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssembly final : public ToolChain {
6767
llvm::opt::ArgStringList &CmdArgs) const override;
6868
SanitizerMask getSupportedSanitizers() const override;
6969

70-
const char *getDefaultLinker() const override { return "wasm-ld"; }
70+
const char *getDefaultLinker() const override;
7171

7272
CXXStdlibType GetDefaultCXXStdlibType() const override {
7373
return ToolChain::CST_Libcxx;

clang/test/Driver/wasm-toolchain.c

+24
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,27 @@
197197
// RUN: not %clang -### %s --target=wasm32-unknown-unknown --sysroot=%s/no-sysroot-there -fPIC -mno-mutable-globals %s 2>&1 \
198198
// RUN: | FileCheck -check-prefix=PIC_NO_MUTABLE_GLOBALS %s
199199
// PIC_NO_MUTABLE_GLOBALS: error: invalid argument '-fPIC' not allowed with '-mno-mutable-globals'
200+
201+
// Test that `wasm32-wasip2` invokes the `wasm-component-ld` linker by default
202+
// instead of `wasm-ld`.
203+
204+
// RUN: %clang -### -O2 --target=wasm32-wasip2 %s --sysroot /foo 2>&1 \
205+
// RUN: | FileCheck -check-prefix=LINK_WASIP2 %s
206+
// LINK_WASIP2: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
207+
// LINK_WASIP2: wasm-component-ld{{.*}}" "-L/foo/lib/wasm32-wasip2" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out"
208+
209+
// Test that on `wasm32-wasip2` the `wasm-component-ld` programs is told where
210+
// to find `wasm-ld` by default.
211+
212+
// RUN: %clang -### -O2 --target=wasm32-wasip2 %s --sysroot /foo 2>&1 \
213+
// RUN: | FileCheck -check-prefix=LINK_WASIP2_FIND_WASMLD %s
214+
// LINK_WASIP2_FIND_WASMLD: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
215+
// LINK_WASIP2_FIND_WASMLD: wasm-component-ld{{.*}}" {{.*}} "--wasm-ld-path" "{{.*}}wasm-ld{{.*}}" {{.*}} "[[temp]]" {{.*}}
216+
217+
// If `wasm32-wasip2` is configured with `wasm-ld` as a linker then don't pass
218+
// the `--wasm-ld-path` flag.
219+
220+
// RUN: %clang -### -O2 --target=wasm32-wasip2 -fuse-ld=lld %s --sysroot /foo 2>&1 \
221+
// RUN: | FileCheck -check-prefix=LINK_WASIP2_USE_WASMLD %s
222+
// LINK_WASIP2_USE_WASMLD: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]"
223+
// LINK_WASIP2_USE_WASMLD: wasm-ld{{.*}}" "-m" "wasm32" {{.*}} "[[temp]]" {{.*}}

0 commit comments

Comments
 (0)