rustc: Stop passing `--allow-undefined` on wasm targets
This commit updates how the linker is invoked on WebAssembly targets (all of them) to avoid passing the `--allow-undefined` flag to the linker. Historically, if I remember this correctly, when `wasm-ld` was first integrated this was practically required because at the time it was otherwise impossible to import a function from the host into a wasm binary. Or, at least, I'm pretty sure that was why this was added.
At the time, as the documentation around this option indicates, it was known that this was going to be a hazard. This doesn't match behavior on native, for example, and can easily paper over what should be a linker error with some sort of other obscure runtime error. An example is that this program currently compiles and links, it just prints null:
unsafe extern "C" {
static nonexistent: u8;
}
fn main() {
println!("{:?}", &raw const nonexistent);
}
This can easily lead to mistakes like rust-lang/libc#4880 and defer what should be a compile-time link error to weird or unusual behavior at link time. Additionally, in the intervening time since `wasm-ld` was first introduced here, lots has changed and notably this program works as expected:
#[link(wasm_import_module = "host")]
unsafe extern "C" {
fn foo();
}
fn main() {
unsafe {
foo();
}
}
This continues to compile without error and the final wasm binary indeed has an imported function from the host. This program:
unsafe extern "C" {
fn foo();
}
fn main() {
unsafe {
foo();
}
}
this currently compiles successfully and emits an import from the `env` module. After this change, however, this will fail to compile with a link error stating that the `foo` symbol is not defined.
The run-make test suite
The run-make test suite contains tests which are the most flexible out of all the rust-lang/rust test suites. run-make tests can basically contain arbitrary code, and are supported by the run_make_support library.
Infrastructure
A run-make test is a test recipe source file rmake.rs accompanied by its parent directory (e.g. tests/run-make/foo/rmake.rs is the foo run-make test).
The implementation for collecting and building the rmake.rs recipes are in src/tools/compiletest/src/runtest.rs, in run_rmake_test.
The setup for the rmake.rs can be summarized as a 3-stage process:
-
First, we build the
run_make_supportlibrary in bootstrap as a tool lib. -
Then, we compile the
rmake.rs"recipe" linking the support library and its dependencies in, and provide a bunch of env vars. We setup a directory structure withinbuild/<target>/test/run-make/<test-name>/ rmake.exe # recipe binary rmake_out/ # sources from test sources copied overand copy non-
rmake.rsinput support files over tormake_out/. The support library is made available as an extern prelude. -
Finally, we run the recipe binary and set
rmake_out/as the working directory.