diff options
| author | bors <bors@rust-lang.org> | 2025-01-16 02:31:22 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-01-16 02:31:22 +0000 |
| commit | 5cd16b7f2bc3624f2d658aa87151279878d2652a (patch) | |
| tree | 6180a5f11979ce30f0495a64c57ca6d265a4f670 /tests/run-make | |
| parent | 6fc8a27931b3806d38143c518c91c7f97b4cfb83 (diff) | |
| parent | 98f673e93a47b33a451f6b2cd99e5d5b03b57563 (diff) | |
| download | rust-5cd16b7f2bc3624f2d658aa87151279878d2652a.tar.gz rust-5cd16b7f2bc3624f2d658aa87151279878d2652a.zip | |
Auto merge of #135458 - jieyouxu:migrate-extern-fn-reachable, r=lqd
tests: Port `extern-fn-reachable` to rmake.rs
Part of #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 #90716](https://github.com/rust-lang/rust/pull/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 #10539](https://github.com/rust-lang/rust/pull/10539).
- Test re-introduced as a run-make test in https://github.com/rust-lang/rust/pull/13741.
- Later, the test coverage regressed in https://github.com/rust-lang/rust/pull/90716.
[^run-pass]: no longer a thing nowadays
Supersedes #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
Diffstat (limited to 'tests/run-make')
| -rw-r--r-- | tests/run-make/extern-fn-reachable/Makefile | 26 | ||||
| -rw-r--r-- | tests/run-make/extern-fn-reachable/dylib.rs | 15 | ||||
| -rw-r--r-- | tests/run-make/extern-fn-reachable/rmake.rs | 46 |
3 files changed, 61 insertions, 26 deletions
diff --git a/tests/run-make/extern-fn-reachable/Makefile b/tests/run-make/extern-fn-reachable/Makefile deleted file mode 100644 index 3297251bfd1..00000000000 --- a/tests/run-make/extern-fn-reachable/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-windows-msvc - -NM=nm -D - -ifeq ($(UNAME),Darwin) -NM=nm -gU -endif - -ifdef IS_WINDOWS -NM=nm -g -endif - -# This overrides the LD_LIBRARY_PATH for RUN -TARGET_RPATH_DIR:=$(TARGET_RPATH_DIR):$(TMPDIR) - -all: - $(RUSTC) dylib.rs -o $(TMPDIR)/libdylib.so -C prefer-dynamic - - [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun1)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun2)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun3)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun4)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/libdylib.so | grep -v __imp_ | grep -c fun5)" -eq "1" ] diff --git a/tests/run-make/extern-fn-reachable/dylib.rs b/tests/run-make/extern-fn-reachable/dylib.rs index fe0c7023b27..42b8270b214 100644 --- a/tests/run-make/extern-fn-reachable/dylib.rs +++ b/tests/run-make/extern-fn-reachable/dylib.rs @@ -1,19 +1,34 @@ #![crate_type = "dylib"] #![allow(dead_code)] +// `pub` extern fn here is a Rust nameres visibility concept, and should not affect symbol +// visibility in the dylib. #[no_mangle] pub extern "C" fn fun1() {} + +// (Lack of) `pub` for the extern fn here is a Rust nameres visibility concept, and should not +// affect symbol visibility in the dylib. #[no_mangle] extern "C" fn fun2() {} +// Modules are a Rust nameres concept, and should not affect symbol visibility in the dylib if the +// extern fn is nested inside a module. mod foo { #[no_mangle] pub extern "C" fn fun3() {} } + +// Similarly, the Rust visibility of the containing module is a Rust nameres concept, and should not +// affect symbol visibility in the dylib. pub mod bar { #[no_mangle] pub extern "C" fn fun4() {} } +// Non-extern `#[no_mangle]` fn should induce a symbol visible in the dylib. #[no_mangle] pub fn fun5() {} + +// The Rust visibility of the fn should not affect is symbol visibility in the dylib. +#[no_mangle] +fn fun6() {} diff --git a/tests/run-make/extern-fn-reachable/rmake.rs b/tests/run-make/extern-fn-reachable/rmake.rs new file mode 100644 index 00000000000..2fc992b14eb --- /dev/null +++ b/tests/run-make/extern-fn-reachable/rmake.rs @@ -0,0 +1,46 @@ +//! Smoke test to check that that symbols of `extern "C"` functions and `#[no_mangle]` rust +//! functions: +//! +//! 1. Are externally visible in the dylib produced. +//! 2. That the symbol visibility is orthogonal to the Rust nameres visibility of the functions +//! involved. + +//@ ignore-cross-compile + +use std::collections::BTreeSet; + +use run_make_support::object::{self, Object}; +use run_make_support::{dynamic_lib_name, is_darwin, path, rfs, rustc}; + +fn main() { + let dylib = dynamic_lib_name("dylib"); + rustc().input("dylib.rs").output(&dylib).arg("-Cprefer-dynamic").run(); + + let expected_symbols = if is_darwin() { + // Mach-O states that all exported symbols should have an underscore as prefix. At the + // same time dlsym will implicitly add it, so outside of compilers, linkers and people + // writing assembly, nobody needs to be aware of this. + BTreeSet::from(["_fun1", "_fun2", "_fun3", "_fun4", "_fun5", "_fun6"]) + } else { + BTreeSet::from(["fun1", "fun2", "fun3", "fun4", "fun5", "fun6"]) + }; + + let mut found_symbols = BTreeSet::new(); + + let blob = rfs::read(path(dylib)); + let file = object::File::parse(&*blob).unwrap(); + for export in file.exports().unwrap() { + let sym_name = export.name(); + let sym_name = std::str::from_utf8(sym_name).unwrap(); + found_symbols.insert(sym_name); + } + + println!("expected_symbols = {:?}", expected_symbols); + println!("found_symbols = {:?}", found_symbols); + if !found_symbols.is_superset(&expected_symbols) { + for diff in expected_symbols.difference(&found_symbols) { + eprintln!("missing symbol: {}", diff); + } + panic!("missing expected symbols"); + } +} |
