Skip to content

Commit

Permalink
rustc: Always handle exported symbols on the wasm target
Browse files Browse the repository at this point in the history
Currently when linking an artifact rustc will only conditionally call
the `Linker::export_symbols` function, but this causes issues on some
targets, like WebAssembly, where it means that executable outputs will
not have the same symbols exported that cdylib outputs have. This commit
sinks the conditional call to `export_symbols` inside the various
implementations of the function that still need it, and otherwise the
wasm linker is configured to always pass through symbol visibility
lists.
  • Loading branch information
alexcrichton committed May 3, 2019
1 parent 3af1bdc commit 884632c
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 8 deletions.
10 changes: 4 additions & 6 deletions src/librustc_codegen_ssa/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1017,12 +1017,10 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
}
}

// If we're building a dynamic library then some platforms need to make sure
// that all symbols are exported correctly from the dynamic library.
if crate_type != config::CrateType::Executable ||
sess.target.target.options.is_like_emscripten {
cmd.export_symbols(tmpdir, crate_type);
}
// If we're building something like a dynamic library then some platforms
// need to make sure that all symbols are exported correctly from the
// dynamic library.
cmd.export_symbols(tmpdir, crate_type);

// When linking a dynamic library, we put the metadata into a section of the
// executable. This metadata is in a separate object file from the main
Expand Down
10 changes: 10 additions & 0 deletions src/librustc_codegen_ssa/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,11 @@ impl<'a> Linker for GccLinker<'a> {
}

fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
// Symbol visibility in object files typically takes care of this.
if crate_type == CrateType::Executable {
return;
}

// If we're compiling a dylib, then we let symbol visibility in object
// files to take care of whether they're exported or not.
//
Expand Down Expand Up @@ -645,6 +650,11 @@ impl<'a> Linker for MsvcLinker<'a> {
fn export_symbols(&mut self,
tmpdir: &Path,
crate_type: CrateType) {
// Symbol visibility takes care of this typically
if crate_type == CrateType::Executable {
return;
}

let path = tmpdir.join("lib.def");
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
Expand Down
6 changes: 6 additions & 0 deletions src/test/run-make/wasm-export-all-symbols/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ all:
$(RUSTC) bar.rs --target wasm32-unknown-unknown
$(RUSTC) foo.rs --target wasm32-unknown-unknown
$(NODE) verify.js $(TMPDIR)/foo.wasm
$(RUSTC) main.rs --target wasm32-unknown-unknown
$(NODE) verify.js $(TMPDIR)/main.wasm
$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
$(NODE) verify.js $(TMPDIR)/foo.wasm
$(RUSTC) main.rs --target wasm32-unknown-unknown -O
$(NODE) verify.js $(TMPDIR)/main.wasm
$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
$(NODE) verify.js $(TMPDIR)/foo.wasm
$(RUSTC) main.rs --target wasm32-unknown-unknown -C lto
$(NODE) verify.js $(TMPDIR)/main.wasm
3 changes: 3 additions & 0 deletions src/test/run-make/wasm-export-all-symbols/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
extern crate bar;

fn main() {}
10 changes: 8 additions & 2 deletions src/test/run-make/wasm-export-all-symbols/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ for (const entry of list) {
nexports += 1;
}

if (nexports != 1)
throw new Error("should only have one function export");
if (my_exports.foo === undefined)
throw new Error("`foo` wasn't defined");

if (my_exports.main === undefined) {
if (nexports != 1)
throw new Error("should only have one function export");
} else {
if (nexports != 2)
throw new Error("should only have two function exports");
}

0 comments on commit 884632c

Please sign in to comment.