Auto merge of #128075 - Oneirical:try-your-damnetest, r=jieyouxu
Migrate `rlib-format-packed-bundled-libs-2`, `native-link-modifier-whole-archive` and `no-builtins-attribute` `run-make` tests 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). Please try: try-job: x86_64-msvc try-job: test-various try-job: armhf-gnu try-job: aarch64-apple try-job: x86_64-gnu-llvm-18
This commit is contained in:
commit
83dcdb3a5d
@ -3,7 +3,7 @@
|
||||
use std::panic;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::fs;
|
||||
use crate::{fs, regex};
|
||||
|
||||
/// Assert that `actual` is equal to `expected`.
|
||||
#[track_caller]
|
||||
@ -47,6 +47,36 @@ pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N)
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert that `haystack` contains the regex pattern `needle`.
|
||||
#[track_caller]
|
||||
pub fn assert_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
|
||||
let haystack = haystack.as_ref();
|
||||
let needle = needle.as_ref();
|
||||
let re = regex::Regex::new(needle).unwrap();
|
||||
if !re.is_match(haystack) {
|
||||
eprintln!("=== HAYSTACK ===");
|
||||
eprintln!("{}", haystack);
|
||||
eprintln!("=== NEEDLE ===");
|
||||
eprintln!("{}", needle);
|
||||
panic!("needle was not found in haystack");
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert that `haystack` does not contain the regex pattern `needle`.
|
||||
#[track_caller]
|
||||
pub fn assert_not_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
|
||||
let haystack = haystack.as_ref();
|
||||
let needle = needle.as_ref();
|
||||
let re = regex::Regex::new(needle).unwrap();
|
||||
if re.is_match(haystack) {
|
||||
eprintln!("=== HAYSTACK ===");
|
||||
eprintln!("{}", haystack);
|
||||
eprintln!("=== NEEDLE ===");
|
||||
eprintln!("{}", needle);
|
||||
panic!("needle was unexpectedly found in haystack");
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert that all files in `dir1` exist and have the same content in `dir2`
|
||||
pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
|
||||
let dir2 = dir2.as_ref();
|
||||
|
@ -7,7 +7,10 @@
|
||||
use build_helper::drop_bomb::DropBomb;
|
||||
|
||||
use crate::util::handle_failed_output;
|
||||
use crate::{assert_contains, assert_equals, assert_not_contains};
|
||||
use crate::{
|
||||
assert_contains, assert_contains_regex, assert_equals, assert_not_contains,
|
||||
assert_not_contains_regex,
|
||||
};
|
||||
|
||||
/// This is a custom command wrapper that simplifies working with commands and makes it easier to
|
||||
/// ensure that we check the exit status of executed processes.
|
||||
@ -191,6 +194,13 @@ pub fn assert_stdout_not_contains<S: AsRef<str>>(&self, unexpected: S) -> &Self
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that `stdout` does not contain the regex pattern `unexpected`.
|
||||
#[track_caller]
|
||||
pub fn assert_stdout_not_contains_regex<S: AsRef<str>>(&self, unexpected: S) -> &Self {
|
||||
assert_not_contains_regex(&self.stdout_utf8(), unexpected);
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that `stdout` contains `expected`.
|
||||
#[track_caller]
|
||||
pub fn assert_stdout_contains<S: AsRef<str>>(&self, expected: S) -> &Self {
|
||||
@ -198,6 +208,13 @@ pub fn assert_stdout_contains<S: AsRef<str>>(&self, expected: S) -> &Self {
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that `stdout` contains the regex pattern `expected`.
|
||||
#[track_caller]
|
||||
pub fn assert_stdout_contains_regex<S: AsRef<str>>(&self, expected: S) -> &Self {
|
||||
assert_contains_regex(&self.stdout_utf8(), expected);
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that trimmed `stderr` matches trimmed `expected`.
|
||||
#[track_caller]
|
||||
pub fn assert_stderr_equals<S: AsRef<str>>(&self, expected: S) -> &Self {
|
||||
@ -212,6 +229,13 @@ pub fn assert_stderr_contains<S: AsRef<str>>(&self, expected: S) -> &Self {
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that `stderr` contains the regex pattern `expected`.
|
||||
#[track_caller]
|
||||
pub fn assert_stderr_contains_regex<S: AsRef<str>>(&self, expected: S) -> &Self {
|
||||
assert_contains_regex(&self.stderr_utf8(), expected);
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that `stderr` does not contain `unexpected`.
|
||||
#[track_caller]
|
||||
pub fn assert_stderr_not_contains<S: AsRef<str>>(&self, unexpected: S) -> &Self {
|
||||
@ -219,6 +243,13 @@ pub fn assert_stderr_not_contains<S: AsRef<str>>(&self, unexpected: S) -> &Self
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that `stderr` does not contain the regex pattern `unexpected`.
|
||||
#[track_caller]
|
||||
pub fn assert_stderr_not_contains_regex<S: AsRef<str>>(&self, unexpected: S) -> &Self {
|
||||
assert_not_contains_regex(&self.stdout_utf8(), unexpected);
|
||||
self
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn assert_exit_code(&self, code: i32) -> &Self {
|
||||
assert!(self.output.status.code() == Some(code));
|
||||
|
@ -36,6 +36,12 @@ pub fn llvm_ar() -> LlvmAr {
|
||||
LlvmAr::new()
|
||||
}
|
||||
|
||||
/// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
|
||||
/// at `$LLVM_BIN_DIR/llvm-nm`.
|
||||
pub fn llvm_nm() -> LlvmNm {
|
||||
LlvmNm::new()
|
||||
}
|
||||
|
||||
/// A `llvm-readobj` invocation builder.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
@ -71,11 +77,19 @@ pub struct LlvmAr {
|
||||
cmd: Command,
|
||||
}
|
||||
|
||||
/// A `llvm-nm` invocation builder.
|
||||
#[derive(Debug)]
|
||||
#[must_use]
|
||||
pub struct LlvmNm {
|
||||
cmd: Command,
|
||||
}
|
||||
|
||||
crate::macros::impl_common_helpers!(LlvmReadobj);
|
||||
crate::macros::impl_common_helpers!(LlvmProfdata);
|
||||
crate::macros::impl_common_helpers!(LlvmFilecheck);
|
||||
crate::macros::impl_common_helpers!(LlvmObjdump);
|
||||
crate::macros::impl_common_helpers!(LlvmAr);
|
||||
crate::macros::impl_common_helpers!(LlvmNm);
|
||||
|
||||
/// Generate the path to the bin directory of LLVM.
|
||||
#[must_use]
|
||||
@ -244,3 +258,19 @@ pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl LlvmNm {
|
||||
/// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
|
||||
/// at `$LLVM_BIN_DIR/llvm-nm`.
|
||||
pub fn new() -> Self {
|
||||
let llvm_nm = llvm_bin_dir().join("llvm-nm");
|
||||
let cmd = Command::new(llvm_nm);
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
/// Provide an input file.
|
||||
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
||||
self.cmd.arg(path.as_ref());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ pub mod rfs {
|
||||
pub use clang::{clang, Clang};
|
||||
pub use htmldocck::htmldocck;
|
||||
pub use llvm::{
|
||||
llvm_ar, llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, LlvmFilecheck,
|
||||
LlvmObjdump, LlvmProfdata, LlvmReadobj,
|
||||
llvm_ar, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr,
|
||||
LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj,
|
||||
};
|
||||
pub use python::python_command;
|
||||
pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
|
||||
@ -84,7 +84,8 @@ pub mod rfs {
|
||||
pub use scoped_run::{run_in_tmpdir, test_while_readonly};
|
||||
|
||||
pub use assertion_helpers::{
|
||||
assert_contains, assert_dirs_are_equal, assert_equals, assert_not_contains,
|
||||
assert_contains, assert_contains_regex, assert_dirs_are_equal, assert_equals,
|
||||
assert_not_contains, assert_not_contains_regex,
|
||||
};
|
||||
|
||||
pub use string::{
|
||||
|
@ -31,9 +31,7 @@ run-make/long-linker-command-lines/Makefile
|
||||
run-make/macos-deployment-target/Makefile
|
||||
run-make/min-global-align/Makefile
|
||||
run-make/native-link-modifier-bundle/Makefile
|
||||
run-make/native-link-modifier-whole-archive/Makefile
|
||||
run-make/no-alloc-shim/Makefile
|
||||
run-make/no-builtins-attribute/Makefile
|
||||
run-make/pdb-buildinfo-cl-cmd/Makefile
|
||||
run-make/pgo-gen-lto/Makefile
|
||||
run-make/pgo-indirect-call-promotion/Makefile
|
||||
@ -45,7 +43,6 @@ run-make/redundant-libs/Makefile
|
||||
run-make/remap-path-prefix-dwarf/Makefile
|
||||
run-make/reproducible-build-2/Makefile
|
||||
run-make/reproducible-build/Makefile
|
||||
run-make/rlib-format-packed-bundled-libs-2/Makefile
|
||||
run-make/rlib-format-packed-bundled-libs/Makefile
|
||||
run-make/simd-ffi/Makefile
|
||||
run-make/split-debuginfo/Makefile
|
||||
|
@ -1,52 +0,0 @@
|
||||
# ignore-cross-compile -- compiling C++ code does not work well when cross-compiling
|
||||
|
||||
# This test case makes sure that native libraries are linked with appropriate semantics
|
||||
# when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
|
||||
#
|
||||
# The test works by checking that the resulting executables produce the expected output,
|
||||
# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
|
||||
# that code would never make it into the final executable and we'd thus be missing some
|
||||
# of the output.
|
||||
|
||||
include ../tools.mk
|
||||
|
||||
all: $(TMPDIR)/$(call BIN,directly_linked) \
|
||||
$(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive) \
|
||||
$(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive) \
|
||||
$(TMPDIR)/$(call BIN,indirectly_linked) \
|
||||
$(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
|
||||
$(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.'
|
||||
$(call RUN,directly_linked_test_plus_whole_archive) --nocapture | $(CGREP) 'static-initializer.'
|
||||
$(call RUN,directly_linked_test_minus_whole_archive) --nocapture | $(CGREP) -v 'static-initializer.'
|
||||
$(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.'
|
||||
$(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.'
|
||||
|
||||
# Native lib linked directly into executable
|
||||
$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
|
||||
$(RUSTC) directly_linked.rs -l static:+whole-archive=c_static_lib_with_constructor
|
||||
|
||||
# Native lib linked into test executable, +whole-archive
|
||||
$(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
|
||||
$(RUSTC) directly_linked_test_plus_whole_archive.rs --test -l static:+whole-archive=c_static_lib_with_constructor
|
||||
# Native lib linked into test executable, -whole-archive
|
||||
$(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
|
||||
$(RUSTC) directly_linked_test_minus_whole_archive.rs --test -l static:-whole-archive=c_static_lib_with_constructor
|
||||
|
||||
# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
|
||||
$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib
|
||||
$(RUSTC) indirectly_linked.rs
|
||||
|
||||
# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
|
||||
$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib
|
||||
$(RUSTC) indirectly_linked_via_attr.rs
|
||||
|
||||
# Native lib linked into rlib with via commandline
|
||||
$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
|
||||
$(RUSTC) rlib_with_cmdline_native_lib.rs --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor
|
||||
|
||||
# Native lib linked into rlib via `#[link()]` attribute on extern block.
|
||||
$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
|
||||
$(RUSTC) native_lib_in_src.rs --crate-type=rlib
|
||||
|
||||
$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp
|
||||
$(call COMPILE_OBJ_CXX,$@,$<)
|
86
tests/run-make/native-link-modifier-whole-archive/rmake.rs
Normal file
86
tests/run-make/native-link-modifier-whole-archive/rmake.rs
Normal file
@ -0,0 +1,86 @@
|
||||
// This test case makes sure that native libraries are linked with appropriate semantics
|
||||
// when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
|
||||
// The test works by checking that the resulting executables produce the expected output,
|
||||
// part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
|
||||
// that code would never make it into the final executable and we'd thus be missing some
|
||||
// of the output.
|
||||
// See https://github.com/rust-lang/rust/issues/88085
|
||||
|
||||
//@ ignore-cross-compile
|
||||
// Reason: compiling C++ code does not work well when cross-compiling
|
||||
// plus, the compiled binary is executed
|
||||
|
||||
use run_make_support::{cxx, is_msvc, llvm_ar, run, run_with_args, rustc, static_lib_name};
|
||||
|
||||
fn main() {
|
||||
let mut cxx = cxx();
|
||||
if is_msvc() {
|
||||
cxx.arg("-EHs");
|
||||
}
|
||||
cxx.input("c_static_lib_with_constructor.cpp")
|
||||
.arg("-c")
|
||||
.out_exe("libc_static_lib_with_constructor")
|
||||
.run();
|
||||
|
||||
let mut llvm_ar = llvm_ar();
|
||||
llvm_ar.obj_to_ar();
|
||||
if is_msvc() {
|
||||
llvm_ar
|
||||
.output_input(
|
||||
static_lib_name("c_static_lib_with_constructor"),
|
||||
"libc_static_lib_with_constructor.obj",
|
||||
)
|
||||
.run();
|
||||
} else {
|
||||
llvm_ar
|
||||
.output_input(
|
||||
static_lib_name("c_static_lib_with_constructor"),
|
||||
"libc_static_lib_with_constructor",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
// Native lib linked directly into executable
|
||||
rustc()
|
||||
.input("directly_linked.rs")
|
||||
.arg("-lstatic:+whole-archive=c_static_lib_with_constructor")
|
||||
.run();
|
||||
|
||||
// Native lib linked into test executable, +whole-archive
|
||||
rustc()
|
||||
.input("directly_linked_test_plus_whole_archive.rs")
|
||||
.arg("--test")
|
||||
.arg("-lstatic:+whole-archive=c_static_lib_with_constructor")
|
||||
.run();
|
||||
|
||||
// Native lib linked into test executable, -whole-archive
|
||||
rustc()
|
||||
.input("directly_linked_test_minus_whole_archive.rs")
|
||||
.arg("--test")
|
||||
.arg("-lstatic:-whole-archive=c_static_lib_with_constructor")
|
||||
.run();
|
||||
|
||||
// Native lib linked into rlib with via commandline
|
||||
rustc()
|
||||
.input("rlib_with_cmdline_native_lib.rs")
|
||||
.crate_type("rlib")
|
||||
.arg("-lstatic:-bundle,+whole-archive=c_static_lib_with_constructor")
|
||||
.run();
|
||||
// Native lib linked into RLIB via `-l static:-bundle,+whole-archive`
|
||||
// RLIB linked into executable
|
||||
rustc().input("indirectly_linked.rs").run();
|
||||
|
||||
// Native lib linked into rlib via `#[link()]` attribute on extern block.
|
||||
rustc().input("native_lib_in_src.rs").crate_type("rlib").run();
|
||||
// Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
|
||||
rustc().input("indirectly_linked_via_attr.rs").run();
|
||||
|
||||
run("directly_linked").assert_stdout_contains("static-initializer.directly_linked.");
|
||||
run_with_args("directly_linked_test_plus_whole_archive", &["--nocapture"])
|
||||
.assert_stdout_contains("static-initializer.");
|
||||
run_with_args("directly_linked_test_minus_whole_archive", &["--nocapture"])
|
||||
.assert_stdout_not_contains("static-initializer.");
|
||||
run("indirectly_linked").assert_stdout_contains("static-initializer.indirectly_linked.");
|
||||
run("indirectly_linked_via_attr")
|
||||
.assert_stdout_contains("static-initializer.native_lib_in_src.");
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
# We want to check if `no-builtins` is also added to the function declarations in the used crate.
|
||||
|
||||
all:
|
||||
$(RUSTC) no_builtins.rs --emit=link
|
||||
$(RUSTC) main.rs --emit=llvm-ir
|
||||
|
||||
cat "$(TMPDIR)"/main.ll | "$(LLVM_FILECHECK)" filecheck.main.txt
|
13
tests/run-make/no-builtins-attribute/rmake.rs
Normal file
13
tests/run-make/no-builtins-attribute/rmake.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// `no_builtins` is an attribute related to LLVM's optimizations. In order to ensure that it has an
|
||||
// effect on link-time optimizations (LTO), it should be added to function declarations in a crate.
|
||||
// This test uses the `llvm-filecheck` tool to determine that this attribute is successfully
|
||||
// being added to these function declarations.
|
||||
// See https://github.com/rust-lang/rust/pull/113716
|
||||
|
||||
use run_make_support::{llvm_filecheck, rfs, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc().input("no_builtins.rs").emit("link").run();
|
||||
rustc().input("main.rs").emit("llvm-ir").run();
|
||||
llvm_filecheck().patterns("filecheck.main.txt").stdin(rfs::read("main.ll")).run();
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
# ignore-cross-compile
|
||||
|
||||
# Make sure -Zpacked_bundled_libs is compatible with verbatim.
|
||||
|
||||
# We're using the llvm-nm instead of the system nm to ensure it is compatible
|
||||
# with the LLVM bitcode generated by rustc.
|
||||
# Except on Windows where piping/IO redirection under MSYS2 is wonky with llvm-nm.
|
||||
ifndef IS_WINDOWS
|
||||
NM = "$(LLVM_BIN_DIR)"/llvm-nm
|
||||
else
|
||||
NM = nm
|
||||
endif
|
||||
|
||||
all:
|
||||
# Build strange-named dep.
|
||||
$(RUSTC) native_dep.rs --crate-type=staticlib -o $(TMPDIR)/native_dep.ext
|
||||
|
||||
$(RUSTC) rust_dep.rs --crate-type=rlib -Zpacked_bundled_libs
|
||||
$(NM) $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "U.*native_f1"
|
||||
$(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) "native_dep.ext"
|
||||
|
||||
# Make sure compiler doesn't use files, that it shouldn't know about.
|
||||
rm $(TMPDIR)/native_dep.ext
|
||||
|
||||
$(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib -Zpacked_bundled_libs
|
28
tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
Normal file
28
tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler
|
||||
// only require a native library and no supplementary object files to compile.
|
||||
// This test simply checks that this flag can be passed alongside verbatim syntax
|
||||
// in rustc flags without a compilation failure or the removal of expected symbols.
|
||||
// See https://github.com/rust-lang/rust/pull/100101
|
||||
|
||||
use run_make_support::{llvm_ar, llvm_nm, rfs, rust_lib_name, rustc};
|
||||
|
||||
fn main() {
|
||||
// Build a strangely named dependency.
|
||||
rustc().input("native_dep.rs").crate_type("staticlib").output("native_dep.ext").run();
|
||||
|
||||
rustc().input("rust_dep.rs").crate_type("rlib").arg("-Zpacked_bundled_libs").run();
|
||||
llvm_nm().input(rust_lib_name("rust_dep")).run().assert_stdout_contains_regex("U.*native_f1");
|
||||
llvm_ar()
|
||||
.arg("t")
|
||||
.arg(rust_lib_name("rust_dep"))
|
||||
.run()
|
||||
.assert_stdout_contains("native_dep.ext");
|
||||
|
||||
// Ensure the compiler does not use files it should not be aware of.
|
||||
rfs::remove_file("native_dep.ext");
|
||||
rustc()
|
||||
.input("main.rs")
|
||||
.extern_("rust_dep", rust_lib_name("rust_dep"))
|
||||
.arg("-Zpacked_bundled_libs")
|
||||
.run();
|
||||
}
|
Loading…
Reference in New Issue
Block a user