about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt1
-rw-r--r--tests/run-make/extern-fn-reachable/Makefile26
-rw-r--r--tests/run-make/extern-fn-reachable/dylib.rs15
-rw-r--r--tests/run-make/extern-fn-reachable/rmake.rs46
4 files changed, 61 insertions, 27 deletions
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index b20d8678d0e..575716eb6dd 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,5 +1,4 @@
 run-make/cat-and-grep-sanity-check/Makefile
-run-make/extern-fn-reachable/Makefile
 run-make/jobserver-error/Makefile
 run-make/split-debuginfo/Makefile
 run-make/symbol-mangling-hashed/Makefile
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");
+    }
+}