diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index ba4524c150c46..2397fa767d8ea 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -30,7 +30,8 @@ pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc}; pub use clang::{clang, Clang}; pub use diff::{diff, Diff}; pub use llvm::{ - llvm_filecheck, llvm_profdata, llvm_readobj, LlvmFilecheck, LlvmProfdata, LlvmReadobj, + llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmFilecheck, LlvmObjdump, + LlvmProfdata, LlvmReadobj, }; pub use run::{cmd, run, run_fail, run_with_args}; pub use rustc::{aux_build, rustc, Rustc}; diff --git a/src/tools/run-make-support/src/llvm.rs b/src/tools/run-make-support/src/llvm.rs index 664093e072d72..fe4131819baec 100644 --- a/src/tools/run-make-support/src/llvm.rs +++ b/src/tools/run-make-support/src/llvm.rs @@ -23,6 +23,12 @@ pub fn llvm_filecheck() -> LlvmFilecheck { LlvmFilecheck::new() } +/// Construct a new `llvm-objdump` invocation. This assumes that `llvm-objdump` is available +/// at `$LLVM_BIN_DIR/llvm-objdump`. +pub fn llvm_objdump() -> LlvmObjdump { + LlvmObjdump::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] @@ -44,9 +50,17 @@ pub struct LlvmFilecheck { cmd: Command, } +/// A `llvm-objdump` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmObjdump { + cmd: Command, +} + crate::impl_common_helpers!(LlvmReadobj); crate::impl_common_helpers!(LlvmProfdata); crate::impl_common_helpers!(LlvmFilecheck); +crate::impl_common_helpers!(LlvmObjdump); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -131,3 +145,19 @@ impl LlvmFilecheck { self } } + +impl LlvmObjdump { + /// Construct a new `llvm-objdump` invocation. This assumes that `llvm-objdump` is available + /// at `$LLVM_BIN_DIR/llvm-objdump`. + pub fn new() -> Self { + let llvm_objdump = llvm_bin_dir().join("llvm-objdump"); + let cmd = Command::new(llvm_objdump); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index fdd0be79a4de7..f8e2459983a02 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -72,7 +72,6 @@ run-make/interdependent-c-libraries/Makefile run-make/intrinsic-unreachable/Makefile run-make/invalid-library/Makefile run-make/invalid-so/Makefile -run-make/invalid-staticlib/Makefile run-make/issue-107094/Makefile run-make/issue-10971-temps-dir/Makefile run-make/issue-109934-lto-debuginfo/Makefile @@ -93,7 +92,6 @@ run-make/issue-40535/Makefile run-make/issue-47384/Makefile run-make/issue-47551/Makefile run-make/issue-51671/Makefile -run-make/issue-64153/Makefile run-make/issue-68794-textrel-on-minimal-lib/Makefile run-make/issue-69368/Makefile run-make/issue-83045/Makefile @@ -145,7 +143,6 @@ run-make/native-link-modifier-verbatim-rustc/Makefile run-make/native-link-modifier-whole-archive/Makefile run-make/no-alloc-shim/Makefile run-make/no-builtins-attribute/Makefile -run-make/no-builtins-lto/Makefile run-make/no-duplicate-libs/Makefile run-make/obey-crate-type-flag/Makefile run-make/optimization-remarks-dir-pgo/Makefile diff --git a/tests/run-make/invalid-staticlib/Makefile b/tests/run-make/invalid-staticlib/Makefile deleted file mode 100644 index 3f0f74ce3cb02..0000000000000 --- a/tests/run-make/invalid-staticlib/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../tools.mk - -all: - touch $(TMPDIR)/libfoo.a - echo | $(RUSTC) - --crate-type=rlib -lstatic=foo 2>&1 | $(CGREP) "failed to add native library" diff --git a/tests/run-make/invalid-staticlib/rmake.rs b/tests/run-make/invalid-staticlib/rmake.rs new file mode 100644 index 0000000000000..451292932477c --- /dev/null +++ b/tests/run-make/invalid-staticlib/rmake.rs @@ -0,0 +1,17 @@ +// If the static library provided is not valid (in this test, +// created as an empty file), +// rustc should print a normal error message and not throw +// an internal compiler error (ICE). +// See https://github.com/rust-lang/rust/pull/28673 + +use run_make_support::{fs_wrapper, rustc, static_lib_name}; + +fn main() { + fs_wrapper::create_file(static_lib_name("foo")); + rustc() + .arg("-") + .crate_type("rlib") + .arg("-lstatic=foo") + .run_fail() + .assert_stderr_contains("failed to add native library"); +} diff --git a/tests/run-make/issue-64153/Makefile b/tests/run-make/issue-64153/Makefile deleted file mode 100644 index f42ea620fb9d1..0000000000000 --- a/tests/run-make/issue-64153/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include ../tools.mk - -# `llvm-objdump`'s output looks different on windows than on other platforms. -# It should be enough to check on Unix platforms, so: -# ignore-windows - -# Staticlibs don't include Rust object files from upstream crates if the same -# code was already pulled into the lib via LTO. However, the bug described in -# https://github.com/rust-lang/rust/issues/64153 lead to this exclusion not -# working properly if the upstream crate was compiled with an explicit filename -# (via `-o`). -# -# This test makes sure that functions defined in the upstream crates do not -# appear twice in the final staticlib when listing all the symbols from it. - -all: - $(RUSTC) --crate-type rlib upstream.rs -o $(TMPDIR)/libupstream.rlib -Ccodegen-units=1 - $(RUSTC) --crate-type staticlib downstream.rs -Clto -Ccodegen-units=1 -o $(TMPDIR)/libdownstream.a - # Dump all the symbols from the staticlib into `syms` - "$(LLVM_BIN_DIR)"/llvm-objdump -t $(TMPDIR)/libdownstream.a > $(TMPDIR)/syms - # Count the global instances of `issue64153_test_function`. There'll be 2 - # if the `upstream` object file got erroneously included twice. - # The line we are testing for with the regex looks something like: - # 0000000000000000 g F .text.issue64153_test_function 00000023 issue64153_test_function - grep -c -e "[[:space:]]g[[:space:]]*F[[:space:]].*issue64153_test_function" $(TMPDIR)/syms > $(TMPDIR)/count - [ "$$(cat $(TMPDIR)/count)" -eq "1" ] diff --git a/tests/run-make/issue-64153/downstream.rs b/tests/run-make/lto-avoid-object-duplication/downstream.rs similarity index 100% rename from tests/run-make/issue-64153/downstream.rs rename to tests/run-make/lto-avoid-object-duplication/downstream.rs diff --git a/tests/run-make/lto-avoid-object-duplication/rmake.rs b/tests/run-make/lto-avoid-object-duplication/rmake.rs new file mode 100644 index 0000000000000..a15089efc957f --- /dev/null +++ b/tests/run-make/lto-avoid-object-duplication/rmake.rs @@ -0,0 +1,38 @@ +// ignore-tidy-tab +// Staticlibs don't include Rust object files from upstream crates if the same +// code was already pulled into the lib via LTO. However, the bug described in +// https://github.com/rust-lang/rust/issues/64153 lead to this exclusion not +// working properly if the upstream crate was compiled with an explicit filename +// (via `-o`). + +// This test makes sure that functions defined in the upstream crates do not +// appear twice in the final staticlib when listing all the symbols from it. + +//FIXME(Oneirical): temporarily remove ignorewindows +// Reason: `llvm-objdump`'s output looks different on windows than on other platforms. +// Only checking on Unix platforms should suffice. + +use run_make_support::{llvm_objdump, regex, rust_lib_name, rustc, static_lib_name}; + +fn main() { + rustc() + .crate_type("rlib") + .input("upstream.rs") + .output(rust_lib_name("upstream")) + .codegen_units(1) + .run(); + rustc() + .crate_type("staticlib") + .input("downstream.rs") + .arg("-Clto") + .output(static_lib_name("downstream")) + .codegen_units(1) + .run(); + let syms = llvm_objdump().arg("-t").input(static_lib_name("downstream")).run().stdout_utf8(); + let re = regex::Regex::new(r#"\s*g\s*F\s.*issue64153_test_function"#).unwrap(); + // Count the global instances of `issue64153_test_function`. There'll be 2 + // if the `upstream` object file got erroneously included twice. + // The line we are testing for with the regex looks something like: + // 0000000000000000 g F .text.issue64153_test_function 00000023 issue64153_test_function + assert_eq!(re.find_iter(syms.as_str()).count(), 1); +} diff --git a/tests/run-make/issue-64153/upstream.rs b/tests/run-make/lto-avoid-object-duplication/upstream.rs similarity index 100% rename from tests/run-make/issue-64153/upstream.rs rename to tests/run-make/lto-avoid-object-duplication/upstream.rs diff --git a/tests/run-make/no-builtins-lto/Makefile b/tests/run-make/no-builtins-lto/Makefile deleted file mode 100644 index c8f05d9918b91..0000000000000 --- a/tests/run-make/no-builtins-lto/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../tools.mk - -all: - # Compile a `#![no_builtins]` rlib crate - $(RUSTC) no_builtins.rs - # Build an executable that depends on that crate using LTO. The no_builtins crate doesn't - # participate in LTO, so its rlib must be explicitly linked into the final binary. Verify this by - # grepping the linker arguments. - $(RUSTC) main.rs -C lto --print link-args | $(CGREP) 'libno_builtins.rlib' diff --git a/tests/run-make/no-builtins-lto/rmake.rs b/tests/run-make/no-builtins-lto/rmake.rs new file mode 100644 index 0000000000000..8e0c3a636490f --- /dev/null +++ b/tests/run-make/no-builtins-lto/rmake.rs @@ -0,0 +1,20 @@ +// The rlib produced by a no_builtins crate should be explicitely linked +// during compilation, and as a result be present in the linker arguments. +// See the comments inside this file for more details. +// See https://github.com/rust-lang/rust/pull/35637 + +use run_make_support::{rust_lib_name, rustc}; + +fn main() { + // Compile a `#![no_builtins]` rlib crate + rustc().input("no_builtins.rs").run(); + // Build an executable that depends on that crate using LTO. The no_builtins crate doesn't + // participate in LTO, so its rlib must be explicitly + // linked into the final binary. Verify this by grepping the linker arguments. + rustc() + .input("main.rs") + .arg("-Clto") + .print("link-args") + .run() + .assert_stdout_contains(rust_lib_name("no_builtins")); +}