rewrite symbol-visibility to rmake
This commit is contained in:
parent
595316b400
commit
689bb118ce
@ -117,6 +117,7 @@
|
||||
"ignore-watchos",
|
||||
"ignore-windows",
|
||||
"ignore-windows-gnu",
|
||||
"ignore-windows-msvc",
|
||||
"ignore-x32",
|
||||
"ignore-x86",
|
||||
"ignore-x86_64",
|
||||
|
@ -163,11 +163,13 @@ pub struct CompletedProcess {
|
||||
|
||||
impl CompletedProcess {
|
||||
#[must_use]
|
||||
#[track_caller]
|
||||
pub fn stdout_utf8(&self) -> String {
|
||||
String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[track_caller]
|
||||
pub fn stderr_utf8(&self) -> String {
|
||||
String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
|
||||
}
|
||||
|
@ -52,7 +52,6 @@ run-make/split-debuginfo/Makefile
|
||||
run-make/stable-symbol-names/Makefile
|
||||
run-make/staticlib-dylib-linkage/Makefile
|
||||
run-make/symbol-mangling-hashed/Makefile
|
||||
run-make/symbol-visibility/Makefile
|
||||
run-make/sysroot-crates-are-unstable/Makefile
|
||||
run-make/thumb-none-cortex-m/Makefile
|
||||
run-make/thumb-none-qemu/Makefile
|
||||
|
@ -1,123 +0,0 @@
|
||||
# ignore-cross-compile
|
||||
include ../tools.mk
|
||||
|
||||
# ignore-windows-msvc
|
||||
|
||||
NM=nm -D
|
||||
CDYLIB_NAME=liba_cdylib.so
|
||||
RDYLIB_NAME=liba_rust_dylib.so
|
||||
PROC_MACRO_NAME=liba_proc_macro.so
|
||||
EXE_NAME=an_executable
|
||||
COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.so
|
||||
|
||||
ifeq ($(UNAME),Darwin)
|
||||
NM=nm -gU
|
||||
CDYLIB_NAME=liba_cdylib.dylib
|
||||
RDYLIB_NAME=liba_rust_dylib.dylib
|
||||
PROC_MACRO_NAME=liba_proc_macro.dylib
|
||||
EXE_NAME=an_executable
|
||||
COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dylib
|
||||
endif
|
||||
|
||||
ifdef IS_WINDOWS
|
||||
NM=nm -g
|
||||
CDYLIB_NAME=liba_cdylib.dll.a
|
||||
RDYLIB_NAME=liba_rust_dylib.dll.a
|
||||
PROC_MACRO_NAME=liba_proc_macro.dll
|
||||
EXE_NAME=an_executable.exe
|
||||
COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dll.a
|
||||
endif
|
||||
|
||||
# `grep` regex for symbols produced by either `legacy` or `v0` mangling
|
||||
RE_ANY_RUST_SYMBOL="_ZN.*h.*E\|_R[a-zA-Z0-9_]+"
|
||||
|
||||
all:
|
||||
$(RUSTC) -Zshare-generics=no an_rlib.rs
|
||||
$(RUSTC) -Zshare-generics=no a_cdylib.rs
|
||||
$(RUSTC) -Zshare-generics=no a_rust_dylib.rs
|
||||
$(RUSTC) -Zshare-generics=no a_proc_macro.rs
|
||||
$(RUSTC) -Zshare-generics=no an_executable.rs
|
||||
$(RUSTC) -Zshare-generics=no a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib
|
||||
|
||||
# Check that a cdylib exports its public #[no_mangle] functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
|
||||
# Check that a cdylib exports the public #[no_mangle] functions of dependencies
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
|
||||
# Check that a cdylib DOES NOT export any public Rust functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
|
||||
|
||||
# Check that a Rust dylib exports its monomorphic functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ]
|
||||
# Check that a Rust dylib does not export generics if -Zshare-generics=no
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rust_dylib)" -eq "0" ]
|
||||
|
||||
|
||||
# Check that a Rust dylib exports the monomorphic functions from its dependencies
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ]
|
||||
# Check that a Rust dylib does not export generics if -Zshare-generics=no
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "0" ]
|
||||
|
||||
# Check that a proc macro exports its public #[no_mangle] functions
|
||||
# FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
|
||||
# Check that a proc macro exports the public #[no_mangle] functions of dependencies
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
|
||||
# Check that a proc macro DOES NOT export any public Rust functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
|
||||
|
||||
# FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
|
||||
ifndef IS_WINDOWS
|
||||
# Check that an executable does not export any dynamic symbols
|
||||
[ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_rust_function_from_exe)" -eq "0" ]
|
||||
endif
|
||||
|
||||
|
||||
# Check the combined case, where we generate a cdylib and an rlib in the same
|
||||
# compilation session:
|
||||
# Check that a cdylib exports its public #[no_mangle] functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
|
||||
# Check that a cdylib exports the public #[no_mangle] functions of dependencies
|
||||
[ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
|
||||
# Check that a cdylib DOES NOT export any public Rust functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
|
||||
|
||||
|
||||
$(RUSTC) -Zshare-generics=yes an_rlib.rs
|
||||
$(RUSTC) -Zshare-generics=yes a_cdylib.rs
|
||||
$(RUSTC) -Zshare-generics=yes a_rust_dylib.rs
|
||||
$(RUSTC) -Zshare-generics=yes a_proc_macro.rs
|
||||
$(RUSTC) -Zshare-generics=yes an_executable.rs
|
||||
|
||||
# Check that a cdylib exports its public #[no_mangle] functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
|
||||
# Check that a cdylib exports the public #[no_mangle] functions of dependencies
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
|
||||
# Check that a cdylib DOES NOT export any public Rust functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
|
||||
|
||||
# Check that a Rust dylib exports its monomorphic functions, including generics this time
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rust_dylib)" -eq "1" ]
|
||||
|
||||
# Check that a Rust dylib exports the monomorphic functions from its dependencies
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "1" ]
|
||||
|
||||
# Check that a proc macro exports its public #[no_mangle] functions
|
||||
# FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
|
||||
# Check that a proc macro exports the public #[no_mangle] functions of dependencies
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
|
||||
# Check that a proc macro DOES NOT export any public Rust functions
|
||||
[ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
|
||||
|
||||
ifndef IS_WINDOWS
|
||||
# Check that an executable does not export any dynamic symbols
|
||||
[ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_rust_function_from_exe)" -eq "0" ]
|
||||
endif
|
168
tests/run-make/symbol-visibility/rmake.rs
Normal file
168
tests/run-make/symbol-visibility/rmake.rs
Normal file
@ -0,0 +1,168 @@
|
||||
// Dynamic libraries on Rust used to export a very high amount of symbols,
|
||||
// going as far as filling the output with mangled names and generic function
|
||||
// names. After the rework of #38117, this test checks that no mangled Rust symbols
|
||||
// are exported, and that generics are only shown if explicitely requested.
|
||||
// See https://github.com/rust-lang/rust/issues/37530
|
||||
|
||||
//@ ignore-windows-msvc
|
||||
|
||||
use run_make_support::{bin_name, dynamic_lib_name, is_windows, llvm_readobj, regex, rustc};
|
||||
|
||||
fn main() {
|
||||
let mut cdylib_name = dynamic_lib_name("a_cdylib");
|
||||
let mut rdylib_name = dynamic_lib_name("a_rust_dylib");
|
||||
let exe_name = bin_name("an_executable");
|
||||
let mut combined_cdylib_name = dynamic_lib_name("combined_rlib_dylib");
|
||||
rustc().arg("-Zshare-generics=no").input("an_rlib.rs").run();
|
||||
rustc().arg("-Zshare-generics=no").input("a_cdylib.rs").run();
|
||||
rustc().arg("-Zshare-generics=no").input("a_rust_dylib.rs").run();
|
||||
rustc().arg("-Zshare-generics=no").input("a_proc_macro.rs").run();
|
||||
rustc().arg("-Zshare-generics=no").input("an_executable.rs").run();
|
||||
rustc()
|
||||
.arg("-Zshare-generics=no")
|
||||
.input("a_cdylib.rs")
|
||||
.crate_name("combined_rlib_dylib")
|
||||
.crate_type("rlib,cdylib")
|
||||
.run();
|
||||
|
||||
// Check that a cdylib exports its public #[no_mangle] functions
|
||||
symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true);
|
||||
// Check that a cdylib exports the public #[no_mangle] functions of dependencies
|
||||
symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
|
||||
// Check that a cdylib DOES NOT export any public Rust functions
|
||||
symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false);
|
||||
|
||||
// Check that a Rust dylib exports its monomorphic functions
|
||||
symbols_check(
|
||||
&rdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"),
|
||||
true,
|
||||
);
|
||||
symbols_check(
|
||||
&rdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"),
|
||||
true,
|
||||
);
|
||||
// Check that a Rust dylib does not export generics if -Zshare-generics=no
|
||||
symbols_check(
|
||||
&rdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"),
|
||||
false,
|
||||
);
|
||||
|
||||
// Check that a Rust dylib exports the monomorphic functions from its dependencies
|
||||
symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
|
||||
symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), true);
|
||||
// Check that a Rust dylib does not export generics if -Zshare-generics=no
|
||||
symbols_check(
|
||||
&rdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_generic_function_from_rlib"),
|
||||
false,
|
||||
);
|
||||
|
||||
// FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
|
||||
// if is_windows() {
|
||||
// // Check that an executable does not export any dynamic symbols
|
||||
// symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib")
|
||||
//, false);
|
||||
// symbols_check(
|
||||
// &exe_name,
|
||||
// SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
|
||||
// false,
|
||||
// );
|
||||
// }
|
||||
|
||||
// Check the combined case, where we generate a cdylib and an rlib in the same
|
||||
// compilation session:
|
||||
// Check that a cdylib exports its public //[no_mangle] functions
|
||||
symbols_check(
|
||||
&combined_cdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_c_function_from_cdylib"),
|
||||
true,
|
||||
);
|
||||
// Check that a cdylib exports the public //[no_mangle] functions of dependencies
|
||||
symbols_check(
|
||||
&combined_cdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_c_function_from_rlib"),
|
||||
true,
|
||||
);
|
||||
// Check that a cdylib DOES NOT export any public Rust functions
|
||||
symbols_check(&combined_cdylib_name, SymbolCheckType::AnyRustSymbol, false);
|
||||
|
||||
rustc().arg("-Zshare-generics=yes").input("an_rlib.rs").run();
|
||||
rustc().arg("-Zshare-generics=yes").input("a_cdylib.rs").run();
|
||||
rustc().arg("-Zshare-generics=yes").input("a_rust_dylib.rs").run();
|
||||
rustc().arg("-Zshare-generics=yes").input("an_executable.rs").run();
|
||||
|
||||
// Check that a cdylib exports its public //[no_mangle] functions
|
||||
symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true);
|
||||
// Check that a cdylib exports the public //[no_mangle] functions of dependencies
|
||||
symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
|
||||
// Check that a cdylib DOES NOT export any public Rust functions
|
||||
symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false);
|
||||
|
||||
// Check that a Rust dylib exports its monomorphic functions, including generics this time
|
||||
symbols_check(
|
||||
&rdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"),
|
||||
true,
|
||||
);
|
||||
symbols_check(
|
||||
&rdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"),
|
||||
true,
|
||||
);
|
||||
symbols_check(
|
||||
&rdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"),
|
||||
true,
|
||||
);
|
||||
|
||||
// Check that a Rust dylib exports the monomorphic functions from its dependencies
|
||||
symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
|
||||
symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), true);
|
||||
symbols_check(
|
||||
&rdylib_name,
|
||||
SymbolCheckType::StrSymbol("public_generic_function_from_rlib"),
|
||||
true,
|
||||
);
|
||||
|
||||
// FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
|
||||
// if is_windows() {
|
||||
// // Check that an executable does not export any dynamic symbols
|
||||
// symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib")
|
||||
//, false);
|
||||
// symbols_check(
|
||||
// &exe_name,
|
||||
// SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
|
||||
// false,
|
||||
// );
|
||||
// }
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) {
|
||||
let out = llvm_readobj().arg("--dyn-symbols").input(path).run().stdout_utf8();
|
||||
assert_eq!(
|
||||
out.lines()
|
||||
.filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type))
|
||||
.count()
|
||||
== 1,
|
||||
exists_once
|
||||
);
|
||||
}
|
||||
|
||||
fn has_symbol(line: &str, symbol_check_type: SymbolCheckType) -> bool {
|
||||
if let SymbolCheckType::StrSymbol(expected) = symbol_check_type {
|
||||
line.contains(expected)
|
||||
} else {
|
||||
let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap();
|
||||
regex.is_match(line)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum SymbolCheckType {
|
||||
StrSymbol(&'static str),
|
||||
AnyRustSymbol,
|
||||
}
|
Loading…
Reference in New Issue
Block a user