| author | bors <bors@rust-lang.org> 2024-08-07 10:58:10 UTC |
| committer | bors <bors@rust-lang.org> 2024-08-07 10:58:10 UTC |
| log | 9bad7ba324099d124c77c5b06aebf68e11763f7b |
| tree | 0c09eff40547c5eab39de4fd3cbdbe9472ee0b1c |
| parent | 6a2cd0d50c9b7e1243d948641758c76d1f22e25e |
| parent | fe4cd9aa8debdf202ca869b32958b2dfc38f6f92 |
Migrate `cross-lang-lto-upstream-rlibs`, `long-linker-command-lines` and `long-linker-command-lines-cmd-exe` `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).
The `long-linker` tests are certainly doing something... interesting - they summon `rustc` calls with obscene quantities of arguments and check that this is appropriately handled. I removed the `RUSTC_ORIGINAL` magic - it's equivalent to `RUSTC` in `tools.mk`, so what is the purpose? Making it so the massive pile of flags doesn't modify rustc itself and start leaking into other tests? Tell me what you think.
Please try:
try-job: x86_64-msvc
try-job: i686-msvc
try-job: x86_64-mingw
try-job: i686-mingw
try-job: aarch64-apple
try-job: test-various
try-job: x86_64-gnu-debug
try-job: x86_64-gnu-llvm-179 files changed, 108 insertions(+), 88 deletions(-)
src/tools/tidy/src/allowed_run_make_makefiles.txt-3| ... | ... | @@ -1,6 +1,5 @@ |
| 1 | 1 | run-make/branch-protection-check-IBT/Makefile |
| 2 | 2 | run-make/cat-and-grep-sanity-check/Makefile |
| 3 | run-make/cross-lang-lto-upstream-rlibs/Makefile | |
| 4 | 3 | run-make/dep-info-doesnt-run-much/Makefile |
| 5 | 4 | run-make/dep-info-spaces/Makefile |
| 6 | 5 | run-make/dep-info/Makefile |
| ... | ... | @@ -13,8 +12,6 @@ run-make/libs-through-symlinks/Makefile |
| 13 | 12 | run-make/libtest-json/Makefile |
| 14 | 13 | run-make/libtest-junit/Makefile |
| 15 | 14 | run-make/libtest-thread-limit/Makefile |
| 16 | run-make/long-linker-command-lines-cmd-exe/Makefile | |
| 17 | run-make/long-linker-command-lines/Makefile | |
| 18 | 15 | run-make/macos-deployment-target/Makefile |
| 19 | 16 | run-make/min-global-align/Makefile |
| 20 | 17 | run-make/native-link-modifier-bundle/Makefile |
tests/run-make/cross-lang-lto-upstream-rlibs/Makefile deleted-32| ... | ... | @@ -1,32 +0,0 @@ |
| 1 | include ../tools.mk | |
| 2 | ||
| 3 | # ignore windows due to libLLVM being present in PATH and the PATH and library path being the same | |
| 4 | # (so fixing it is harder). See #57765 for context | |
| 5 | ifndef IS_WINDOWS | |
| 6 | ||
| 7 | # This test makes sure that we don't loose upstream object files when compiling | |
| 8 | # staticlibs with -C linker-plugin-lto | |
| 9 | ||
| 10 | all: staticlib.rs upstream.rs | |
| 11 | 	$(RUSTC) upstream.rs -C linker-plugin-lto -Ccodegen-units=1 | |
| 12 | ||
| 13 | 	# Check No LTO | |
| 14 | 	$(RUSTC) staticlib.rs -C linker-plugin-lto -Ccodegen-units=1 -L. -o $(TMPDIR)/staticlib.a | |
| 15 | 	(cd $(TMPDIR); "$(LLVM_BIN_DIR)"/llvm-ar x ./staticlib.a) | |
| 16 | 	# Make sure the upstream object file was included | |
| 17 | 	ls $(TMPDIR)/upstream.*.rcgu.o | |
| 18 | ||
| 19 | 	# Cleanup | |
| 20 | 	rm $(TMPDIR)/* | |
| 21 | ||
| 22 | 	# Check ThinLTO | |
| 23 | 	$(RUSTC) upstream.rs -C linker-plugin-lto -Ccodegen-units=1 -Clto=thin | |
| 24 | 	$(RUSTC) staticlib.rs -C linker-plugin-lto -Ccodegen-units=1 -Clto=thin -L. -o $(TMPDIR)/staticlib.a | |
| 25 | 	(cd $(TMPDIR); "$(LLVM_BIN_DIR)"/llvm-ar x ./staticlib.a) | |
| 26 | 	ls $(TMPDIR)/upstream.*.rcgu.o | |
| 27 | ||
| 28 | else | |
| 29 | ||
| 30 | all: | |
| 31 | ||
| 32 | endif |
tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs created+57| ... | ... | @@ -0,0 +1,57 @@ |
| 1 | // When using the flag -C linker-plugin-lto, static libraries could lose their upstream object | |
| 2 | // files during compilation. This bug was fixed in #53031, and this test compiles a staticlib | |
| 3 | // dependent on upstream, checking that the upstream object file still exists after no LTO and | |
| 4 | // thin LTO. | |
| 5 | // See https://github.com/rust-lang/rust/pull/53031 | |
| 6 | ||
| 7 | use run_make_support::{ | |
| 8 | cwd, has_extension, has_prefix, has_suffix, llvm_ar, rfs, rustc, shallow_find_files, | |
| 9 | static_lib_name, | |
| 10 | }; | |
| 11 | ||
| 12 | fn main() { | |
| 13 | // The test starts with no LTO enabled. | |
| 14 | rustc().input("upstream.rs").arg("-Clinker-plugin-lto").codegen_units(1).run(); | |
| 15 | rustc() | |
| 16 | .input("staticlib.rs") | |
| 17 | .arg("-Clinker-plugin-lto") | |
| 18 | .codegen_units(1) | |
| 19 | .output(static_lib_name("staticlib")) | |
| 20 | .run(); | |
| 21 | llvm_ar().extract().arg(static_lib_name("staticlib")).run(); | |
| 22 | // Ensure the upstream object file was included. | |
| 23 | assert_eq!( | |
| 24 | shallow_find_files(cwd(), |path| { | |
| 25 | has_prefix(path, "upstream.") && has_suffix(path, ".rcgu.o") | |
| 26 | }) | |
| 27 | .len(), | |
| 28 | 1 | |
| 29 | ); | |
| 30 | // Remove all output files that are not source Rust code for cleanup. | |
| 31 | for file in shallow_find_files(cwd(), |path| !has_extension(path, "rs")) { | |
| 32 | rfs::remove_file(file) | |
| 33 | } | |
| 34 | ||
| 35 | // Check it again, with Thin LTO. | |
| 36 | rustc() | |
| 37 | .input("upstream.rs") | |
| 38 | .arg("-Clinker-plugin-lto") | |
| 39 | .codegen_units(1) | |
| 40 | .arg("-Clto=thin") | |
| 41 | .run(); | |
| 42 | rustc() | |
| 43 | .input("staticlib.rs") | |
| 44 | .arg("-Clinker-plugin-lto") | |
| 45 | .codegen_units(1) | |
| 46 | .arg("-Clto=thin") | |
| 47 | .output(static_lib_name("staticlib")) | |
| 48 | .run(); | |
| 49 | llvm_ar().extract().arg(static_lib_name("staticlib")).run(); | |
| 50 | assert_eq!( | |
| 51 | shallow_find_files(cwd(), |path| { | |
| 52 | has_prefix(path, "upstream.") && has_suffix(path, ".rcgu.o") | |
| 53 | }) | |
| 54 | .len(), | |
| 55 | 1 | |
| 56 | ); | |
| 57 | } |
tests/run-make/long-linker-command-lines-cmd-exe/Makefile deleted-7| ... | ... | @@ -1,7 +0,0 @@ |
| 1 | # ignore-cross-compile | |
| 2 | include ../tools.mk | |
| 3 | ||
| 4 | all: | |
| 5 | 	$(RUSTC) foo.rs -g | |
| 6 | 	cp foo.bat $(TMPDIR)/ | |
| 7 | 	OUT_DIR="$(TMPDIR)" RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) |
tests/run-make/long-linker-command-lines-cmd-exe/foo.rs+3-23| ... | ... | @@ -1,16 +1,3 @@ |
| 1 | // Like the `long-linker-command-lines` test this test attempts to blow | |
| 2 | // a command line limit for running the linker. Unlike that test, however, | |
| 3 | // this test is testing `cmd.exe` specifically rather than the OS. | |
| 4 | // | |
| 5 | // Unfortunately `cmd.exe` has a 8192 limit which is relatively small | |
| 6 | // in the grand scheme of things and anyone sripting rustc's linker | |
| 7 | // is probably using a `*.bat` script and is likely to hit this limit. | |
| 8 | // | |
| 9 | // This test uses a `foo.bat` script as the linker which just simply | |
| 10 | // delegates back to this program. The compiler should use a lower | |
| 11 | // limit for arguments before passing everything via `@`, which | |
| 12 | // means that everything should still succeed here. | |
| 13 | ||
| 14 | 1 | use std::env; |
| 15 | 2 | use std::fs::{self, File}; |
| 16 | 3 | use std::io::{BufWriter, Read, Write}; |
| ... | ... | @@ -18,13 +5,8 @@ use std::path::PathBuf; |
| 18 | 5 | use std::process::Command; |
| 19 | 6 | |
| 20 | 7 | fn main() { |
| 21 | if !cfg!(windows) { | |
| 22 | return; | |
| 23 | } | |
| 24 | ||
| 25 | let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); | |
| 26 | let ok = tmpdir.join("ok"); | |
| 27 | let not_ok = tmpdir.join("not_ok"); | |
| 8 | let ok = PathBuf::from("ok"); | |
| 9 | let not_ok = PathBuf::from("not_ok"); | |
| 28 | 10 | if env::var("YOU_ARE_A_LINKER").is_ok() { |
| 29 | 11 | match env::args_os().find(|a| a.to_string_lossy().contains("@")) { |
| 30 | 12 | Some(file) => { |
| ... | ... | @@ -45,7 +27,7 @@ fn main() { |
| 45 | 27 | for i in (1..).map(|i| i * 10) { |
| 46 | 28 | println!("attempt: {}", i); |
| 47 | 29 | |
| 48 | let file = tmpdir.join("bar.rs"); | |
| 30 | let file = PathBuf::from("bar.rs"); | |
| 49 | 31 | let mut f = BufWriter::new(File::create(&file).unwrap()); |
| 50 | 32 | let mut lib_name = String::new(); |
| 51 | 33 | for _ in 0..i { |
| ... | ... | @@ -63,8 +45,6 @@ fn main() { |
| 63 | 45 | .arg(&file) |
| 64 | 46 | .arg("-C") |
| 65 | 47 | .arg(&bat_linker) |
| 66 | .arg("--out-dir") | |
| 67 | .arg(&tmpdir) | |
| 68 | 48 | .env("YOU_ARE_A_LINKER", "1") |
| 69 | 49 | .env("MY_LINKER", &me) |
| 70 | 50 | .status() |
tests/run-make/long-linker-command-lines-cmd-exe/rmake.rs created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | // Like the `long-linker-command-lines` test this test attempts to blow | |
| 2 | // a command line limit for running the linker. Unlike that test, however, | |
| 3 | // this test is testing `cmd.exe` specifically rather than the OS. | |
| 4 | // | |
| 5 | // Unfortunately, the maximum length of the string that you can use at the | |
| 6 | // command prompt (`cmd.exe`) is 8191 characters. | |
| 7 | // Anyone scripting rustc's linker | |
| 8 | // is probably using a `*.bat` script and is likely to hit this limit. | |
| 9 | // | |
| 10 | // This test uses a `foo.bat` script as the linker which just simply | |
| 11 | // delegates back to this program. The compiler should use a lower | |
| 12 | // limit for arguments before passing everything via `@`, which | |
| 13 | // means that everything should still succeed here. | |
| 14 | // See https://github.com/rust-lang/rust/pull/47507 | |
| 15 | ||
| 16 | //@ ignore-cross-compile | |
| 17 | // Reason: the compiled binary is executed | |
| 18 | //@ only-windows | |
| 19 | // Reason: this test is specific to Windows executables | |
| 20 | ||
| 21 | use run_make_support::{run, rustc}; | |
| 22 | ||
| 23 | fn main() { | |
| 24 | rustc().input("foo.rs").arg("-g").run(); | |
| 25 | run("foo"); | |
| 26 | } |
tests/run-make/long-linker-command-lines/Makefile deleted-8| ... | ... | @@ -1,8 +0,0 @@ |
| 1 | # ignore-cross-compile | |
| 2 | include ../tools.mk | |
| 3 | ||
| 4 | export LD_LIBRARY_PATH := $(HOST_RPATH_DIR) | |
| 5 | ||
| 6 | all: | |
| 7 | 	$(RUSTC) foo.rs -g -O | |
| 8 | 	RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) |
tests/run-make/long-linker-command-lines/foo.rs+3-15| ... | ... | @@ -1,12 +1,3 @@ |
| 1 | // This is a test which attempts to blow out the system limit with how many | |
| 2 | // arguments can be passed to a process. This'll successively call rustc with | |
| 3 | // larger and larger argument lists in an attempt to find one that's way too | |
| 4 | // big for the system at hand. This file itself is then used as a "linker" to | |
| 5 | // detect when the process creation succeeds. | |
| 6 | // | |
| 7 | // Eventually we should see an argument that looks like `@` as we switch from | |
| 8 | // passing literal arguments to passing everything in the file. | |
| 9 | ||
| 10 | 1 | use std::collections::HashSet; |
| 11 | 2 | use std::env; |
| 12 | 3 | use std::fs::{self, File}; |
| ... | ... | @@ -43,8 +34,7 @@ fn read_linker_args(path: &Path) -> String { |
| 43 | 34 | } |
| 44 | 35 | |
| 45 | 36 | fn main() { |
| 46 | let tmpdir = PathBuf::from(env::var_os("TMPDIR").unwrap()); | |
| 47 | let ok = tmpdir.join("ok"); | |
| 37 | let ok = PathBuf::from("ok"); | |
| 48 | 38 | if env::var("YOU_ARE_A_LINKER").is_ok() { |
| 49 | 39 | if let Some(file) = env::args_os().find(|a| a.to_string_lossy().contains("@")) { |
| 50 | 40 | let file = file.to_str().expect("non-utf8 file argument"); |
| ... | ... | @@ -53,11 +43,11 @@ fn main() { |
| 53 | 43 | return; |
| 54 | 44 | } |
| 55 | 45 | |
| 56 | let rustc = env::var_os("RUSTC").unwrap_or("rustc".into()); | |
| 46 | let rustc = env::var_os("RUSTC").unwrap(); | |
| 57 | 47 | let me_as_linker = format!("linker={}", env::current_exe().unwrap().display()); |
| 58 | 48 | for i in (1..).map(|i| i * 100) { |
| 59 | 49 | println!("attempt: {}", i); |
| 60 | let file = tmpdir.join("bar.rs"); | |
| 50 | let file = PathBuf::from("bar.rs"); | |
| 61 | 51 | let mut expected_libs = write_test_case(&file, i); |
| 62 | 52 | |
| 63 | 53 | drop(fs::remove_file(&ok)); |
| ... | ... | @@ -65,8 +55,6 @@ fn main() { |
| 65 | 55 | .arg(&file) |
| 66 | 56 | .arg("-C") |
| 67 | 57 | .arg(&me_as_linker) |
| 68 | .arg("--out-dir") | |
| 69 | .arg(&tmpdir) | |
| 70 | 58 | .env("YOU_ARE_A_LINKER", "1") |
| 71 | 59 | .output() |
| 72 | 60 | .unwrap(); |
tests/run-make/long-linker-command-lines/rmake.rs created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | // This is a test which attempts to blow out the system limit with how many | |
| 2 | // arguments can be passed to a process. This'll successively call rustc with | |
| 3 | // larger and larger argument lists in an attempt to find one that's way too | |
| 4 | // big for the system at hand. This file itself is then used as a "linker" to | |
| 5 | // detect when the process creation succeeds. | |
| 6 | // | |
| 7 | // Eventually we should see an argument that looks like `@` as we switch from | |
| 8 | // passing literal arguments to passing everything in the file. | |
| 9 | // See https://github.com/rust-lang/rust/issues/41190 | |
| 10 | ||
| 11 | //@ ignore-cross-compile | |
| 12 | // Reason: the compiled binary is executed | |
| 13 | ||
| 14 | use run_make_support::{run, rustc}; | |
| 15 | ||
| 16 | fn main() { | |
| 17 | rustc().input("foo.rs").arg("-g").opt().run(); | |
| 18 | run("foo"); | |
| 19 | } |