Skip to content

Commit 5cd16b7

Browse files
committed
Auto merge of rust-lang#135458 - jieyouxu:migrate-extern-fn-reachable, r=lqd
tests: Port `extern-fn-reachable` to rmake.rs Part of rust-lang#121876. ## Summary This PR ports `tests/run-make/extern-fn-reachable` to use `rmake.rs`. Notable changes: - We now use the `object` crate and look at the exported symbols specifically. - This test's coverage regressed against windows-msvc back in [replace dynamic library module with libloading rust-lang#90716](rust-lang#90716), but since we use `object` now, we're able to claw the test coverage back. - The checks are now stricter: 1. It no longer looks for substring symbol matches in `nm` textual outputs, it inspects the symbol names precisely. 2. We now also explicitly check for the presence of leading underscore in exported symbol names on apple vs non-apple targets. - Added another case of `#[no_mangle] fn fun6() {}` (note the lack of `pub`) to check that Rust nameres visibility is orthogonal to symbol visibility in dylib. ## History - Test was initially introduced as a run-pass[^run-pass] test as part of [Don't mark reachable extern fns as internal rust-lang#10539](rust-lang#10539). - Test re-introduced as a run-make test in rust-lang#13741. - Later, the test coverage regressed in rust-lang#90716. [^run-pass]: no longer a thing nowadays Supersedes rust-lang#128314. Co-authored with `@lolbinarycat.` try-job: x86_64-msvc try-job: i686-msvc try-job: i686-mingw try-job: x86_64-mingw-1 try-job: x86_64-apple-1 try-job: aarch64-apple try-job: test-various
2 parents 6fc8a27 + 98f673e commit 5cd16b7

File tree

4 files changed

+61
-27
lines changed

4 files changed

+61
-27
lines changed

src/tools/tidy/src/allowed_run_make_makefiles.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
run-make/cat-and-grep-sanity-check/Makefile
2-
run-make/extern-fn-reachable/Makefile
32
run-make/jobserver-error/Makefile
43
run-make/split-debuginfo/Makefile
54
run-make/symbol-mangling-hashed/Makefile

tests/run-make/extern-fn-reachable/Makefile

-26
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,34 @@
11
#![crate_type = "dylib"]
22
#![allow(dead_code)]
33

4+
// `pub` extern fn here is a Rust nameres visibility concept, and should not affect symbol
5+
// visibility in the dylib.
46
#[no_mangle]
57
pub extern "C" fn fun1() {}
8+
9+
// (Lack of) `pub` for the extern fn here is a Rust nameres visibility concept, and should not
10+
// affect symbol visibility in the dylib.
611
#[no_mangle]
712
extern "C" fn fun2() {}
813

14+
// Modules are a Rust nameres concept, and should not affect symbol visibility in the dylib if the
15+
// extern fn is nested inside a module.
916
mod foo {
1017
#[no_mangle]
1118
pub extern "C" fn fun3() {}
1219
}
20+
21+
// Similarly, the Rust visibility of the containing module is a Rust nameres concept, and should not
22+
// affect symbol visibility in the dylib.
1323
pub mod bar {
1424
#[no_mangle]
1525
pub extern "C" fn fun4() {}
1626
}
1727

28+
// Non-extern `#[no_mangle]` fn should induce a symbol visible in the dylib.
1829
#[no_mangle]
1930
pub fn fun5() {}
31+
32+
// The Rust visibility of the fn should not affect is symbol visibility in the dylib.
33+
#[no_mangle]
34+
fn fun6() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//! Smoke test to check that that symbols of `extern "C"` functions and `#[no_mangle]` rust
2+
//! functions:
3+
//!
4+
//! 1. Are externally visible in the dylib produced.
5+
//! 2. That the symbol visibility is orthogonal to the Rust nameres visibility of the functions
6+
//! involved.
7+
8+
//@ ignore-cross-compile
9+
10+
use std::collections::BTreeSet;
11+
12+
use run_make_support::object::{self, Object};
13+
use run_make_support::{dynamic_lib_name, is_darwin, path, rfs, rustc};
14+
15+
fn main() {
16+
let dylib = dynamic_lib_name("dylib");
17+
rustc().input("dylib.rs").output(&dylib).arg("-Cprefer-dynamic").run();
18+
19+
let expected_symbols = if is_darwin() {
20+
// Mach-O states that all exported symbols should have an underscore as prefix. At the
21+
// same time dlsym will implicitly add it, so outside of compilers, linkers and people
22+
// writing assembly, nobody needs to be aware of this.
23+
BTreeSet::from(["_fun1", "_fun2", "_fun3", "_fun4", "_fun5", "_fun6"])
24+
} else {
25+
BTreeSet::from(["fun1", "fun2", "fun3", "fun4", "fun5", "fun6"])
26+
};
27+
28+
let mut found_symbols = BTreeSet::new();
29+
30+
let blob = rfs::read(path(dylib));
31+
let file = object::File::parse(&*blob).unwrap();
32+
for export in file.exports().unwrap() {
33+
let sym_name = export.name();
34+
let sym_name = std::str::from_utf8(sym_name).unwrap();
35+
found_symbols.insert(sym_name);
36+
}
37+
38+
println!("expected_symbols = {:?}", expected_symbols);
39+
println!("found_symbols = {:?}", found_symbols);
40+
if !found_symbols.is_superset(&expected_symbols) {
41+
for diff in expected_symbols.difference(&found_symbols) {
42+
eprintln!("missing symbol: {}", diff);
43+
}
44+
panic!("missing expected symbols");
45+
}
46+
}

0 commit comments

Comments
 (0)