Auto merge of #127060 - Oneirical:testificate, r=jieyouxu
Migrate `symbol-visibility` `run-make` test to rmake Part of #121876 and the associated [Google Summer of Code project](https://blog.rust-lang.org/2024/05/01/gsoc-2024-selected-projects.html). Pretty scary! - The expected number of symbols on each check has been changed slightly to reflect the differences between `llvm_readobj` and `nm`, as I think the former will print hidden symbols once and visible symbols twice, while the latter will only print visible symbols. - The original test ran the same exact checks on `cdylib` twice, for seemingly no reason. I have removed it. - This may be possible to optimize some more? `llvm_readobj` could get called only once for each library type, and the regex could avoid being created repeatedly. I am not sure if these kinds of considerations are important for a `run-make` test. Demands a Windows try-job. try-job: x86_64-mingw
This commit is contained in:
commit
70591dc15d
@ -117,6 +117,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
|||||||
"ignore-watchos",
|
"ignore-watchos",
|
||||||
"ignore-windows",
|
"ignore-windows",
|
||||||
"ignore-windows-gnu",
|
"ignore-windows-gnu",
|
||||||
|
"ignore-windows-msvc",
|
||||||
"ignore-x32",
|
"ignore-x32",
|
||||||
"ignore-x86",
|
"ignore-x86",
|
||||||
"ignore-x86_64",
|
"ignore-x86_64",
|
||||||
|
@ -166,11 +166,19 @@ pub struct CompletedProcess {
|
|||||||
|
|
||||||
impl CompletedProcess {
|
impl CompletedProcess {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
#[track_caller]
|
||||||
pub fn stdout_utf8(&self) -> String {
|
pub fn stdout_utf8(&self) -> String {
|
||||||
String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
|
String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
#[track_caller]
|
||||||
|
pub fn invalid_stdout_utf8(&self) -> String {
|
||||||
|
String::from_utf8_lossy(&self.output.stdout.clone()).to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
#[track_caller]
|
||||||
pub fn stderr_utf8(&self) -> String {
|
pub fn stderr_utf8(&self) -> String {
|
||||||
String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
|
String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,6 @@ run-make/split-debuginfo/Makefile
|
|||||||
run-make/stable-symbol-names/Makefile
|
run-make/stable-symbol-names/Makefile
|
||||||
run-make/staticlib-dylib-linkage/Makefile
|
run-make/staticlib-dylib-linkage/Makefile
|
||||||
run-make/symbol-mangling-hashed/Makefile
|
run-make/symbol-mangling-hashed/Makefile
|
||||||
run-make/symbol-visibility/Makefile
|
|
||||||
run-make/sysroot-crates-are-unstable/Makefile
|
run-make/sysroot-crates-are-unstable/Makefile
|
||||||
run-make/thumb-none-cortex-m/Makefile
|
run-make/thumb-none-cortex-m/Makefile
|
||||||
run-make/thumb-none-qemu/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
|
|
179
tests/run-make/symbol-visibility/rmake.rs
Normal file
179
tests/run-make/symbol-visibility/rmake.rs
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
//FIXME(Oneirical): This currently uses llvm-nm for symbol detection. However,
|
||||||
|
// the custom Rust-based solution of #128314 may prove to be an interesting alternative.
|
||||||
|
|
||||||
|
use run_make_support::{bin_name, dynamic_lib_name, is_darwin, is_windows, llvm_nm, regex, rustc};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let cdylib_name = dynamic_lib_name("a_cdylib");
|
||||||
|
let rdylib_name = dynamic_lib_name("a_rust_dylib");
|
||||||
|
let exe_name = bin_name("an_executable");
|
||||||
|
let 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 mut nm = llvm_nm();
|
||||||
|
if is_windows() {
|
||||||
|
nm.arg("--extern-only");
|
||||||
|
} else if is_darwin() {
|
||||||
|
nm.arg("--extern-only").arg("--defined-only");
|
||||||
|
} else {
|
||||||
|
nm.arg("--dynamic");
|
||||||
|
}
|
||||||
|
let out = nm.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…
x
Reference in New Issue
Block a user