| author | bors <bors@rust-lang.org> 2024-08-02 10:59:19 UTC |
| committer | bors <bors@rust-lang.org> 2024-08-02 10:59:19 UTC |
| log | 53676730146e38e4697b6204c2ee61a9fd6b7e51 |
| tree | c27f5399f91b70d4c06521235c283c807eee7baf |
| parent | 19326022d243f487b5752661cd9b597d620a489e |
| parent | 152db2760cbd21b6c4fcd2c22ee1dcb422fb9965 |
Migrate `cross-lang-lto` `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).
Please try:
try-job: x86_64-msvc
try-job: i686-mingw
try-job: x86_64-mingw
try-job: armhf-gnu
try-job: test-various
try-job: aarch64-apple
try-job: x86_64-gnu-llvm-185 files changed, 148 insertions(+), 60 deletions(-)
src/tools/run-make-support/src/external_deps/llvm.rs+36| ... | ... | @@ -42,6 +42,12 @@ pub fn llvm_nm() -> LlvmNm { |
| 42 | 42 | LlvmNm::new() |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | /// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available | |
| 46 | /// at `$LLVM_BIN_DIR/llvm-bcanalyzer`. | |
| 47 | pub fn llvm_bcanalyzer() -> LlvmBcanalyzer { | |
| 48 | LlvmBcanalyzer::new() | |
| 49 | } | |
| 50 | ||
| 45 | 51 | /// A `llvm-readobj` invocation builder. |
| 46 | 52 | #[derive(Debug)] |
| 47 | 53 | #[must_use] |
| ... | ... | @@ -84,12 +90,20 @@ pub struct LlvmNm { |
| 84 | 90 | cmd: Command, |
| 85 | 91 | } |
| 86 | 92 | |
| 93 | /// A `llvm-bcanalyzer` invocation builder. | |
| 94 | #[derive(Debug)] | |
| 95 | #[must_use] | |
| 96 | pub struct LlvmBcanalyzer { | |
| 97 | cmd: Command, | |
| 98 | } | |
| 99 | ||
| 87 | 100 | crate::macros::impl_common_helpers!(LlvmReadobj); |
| 88 | 101 | crate::macros::impl_common_helpers!(LlvmProfdata); |
| 89 | 102 | crate::macros::impl_common_helpers!(LlvmFilecheck); |
| 90 | 103 | crate::macros::impl_common_helpers!(LlvmObjdump); |
| 91 | 104 | crate::macros::impl_common_helpers!(LlvmAr); |
| 92 | 105 | crate::macros::impl_common_helpers!(LlvmNm); |
| 106 | crate::macros::impl_common_helpers!(LlvmBcanalyzer); | |
| 93 | 107 | |
| 94 | 108 | /// Generate the path to the bin directory of LLVM. |
| 95 | 109 | #[must_use] |
| ... | ... | @@ -250,6 +264,12 @@ impl LlvmAr { |
| 250 | 264 | self |
| 251 | 265 | } |
| 252 | 266 | |
| 267 | /// Extract archive members back to files. | |
| 268 | pub fn extract(&mut self) -> &mut Self { | |
| 269 | self.cmd.arg("x"); | |
| 270 | self | |
| 271 | } | |
| 272 | ||
| 253 | 273 | /// Provide an output, then an input file. Bundled in one function, as llvm-ar has |
| 254 | 274 | /// no "--output"-style flag. |
| 255 | 275 | pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self { |
| ... | ... | @@ -274,3 +294,19 @@ impl LlvmNm { |
| 274 | 294 | self |
| 275 | 295 | } |
| 276 | 296 | } |
| 297 | ||
| 298 | impl LlvmBcanalyzer { | |
| 299 | /// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available | |
| 300 | /// at `$LLVM_BIN_DIR/llvm-bcanalyzer`. | |
| 301 | pub fn new() -> Self { | |
| 302 | let llvm_bcanalyzer = llvm_bin_dir().join("llvm-bcanalyzer"); | |
| 303 | let cmd = Command::new(llvm_bcanalyzer); | |
| 304 | Self { cmd } | |
| 305 | } | |
| 306 | ||
| 307 | /// Provide an input file. | |
| 308 | pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self { | |
| 309 | self.cmd.arg(path.as_ref()); | |
| 310 | self | |
| 311 | } | |
| 312 | } |
src/tools/run-make-support/src/lib.rs+2-2| ... | ... | @@ -49,8 +49,8 @@ pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; |
| 49 | 49 | pub use clang::{clang, Clang}; |
| 50 | 50 | pub use htmldocck::htmldocck; |
| 51 | 51 | pub use llvm::{ |
| 52 | llvm_ar, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, | |
| 53 | LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, | |
| 52 | llvm_ar, llvm_bcanalyzer, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, | |
| 53 | LlvmAr, LlvmBcanalyzer, LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, | |
| 54 | 54 | }; |
| 55 | 55 | pub use python::python_command; |
| 56 | 56 | pub use rustc::{aux_build, bare_rustc, rustc, Rustc}; |
src/tools/tidy/src/allowed_run_make_makefiles.txt-1| ... | ... | @@ -4,7 +4,6 @@ run-make/cdylib-dylib-linkage/Makefile |
| 4 | 4 | run-make/cross-lang-lto-clang/Makefile |
| 5 | 5 | run-make/cross-lang-lto-pgo-smoketest/Makefile |
| 6 | 6 | run-make/cross-lang-lto-upstream-rlibs/Makefile |
| 7 | run-make/cross-lang-lto/Makefile | |
| 8 | 7 | run-make/dep-info-doesnt-run-much/Makefile |
| 9 | 8 | run-make/dep-info-spaces/Makefile |
| 10 | 9 | run-make/dep-info/Makefile |
tests/run-make/cross-lang-lto/Makefile deleted-57| ... | ... | @@ -1,57 +0,0 @@ |
| 1 | ||
| 2 | include ../tools.mk | |
| 3 | ||
| 4 | # ignore windows due to libLLVM being present in PATH and the PATH and library path being the same | |
| 5 | # (so fixing it is harder). See #57765 for context | |
| 6 | ifndef IS_WINDOWS | |
| 7 | ||
| 8 | # This test makes sure that the object files we generate are actually | |
| 9 | # LLVM bitcode files (as used by linker LTO plugins) when compiling with | |
| 10 | # -Clinker-plugin-lto. | |
| 11 | ||
| 12 | # this only succeeds for bitcode files | |
| 13 | ASSERT_IS_BITCODE_OBJ=("$(LLVM_BIN_DIR)"/llvm-bcanalyzer $(1)) | |
| 14 | EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; "$(LLVM_BIN_DIR)"/llvm-ar x $(1)) | |
| 15 | ||
| 16 | BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 | |
| 17 | BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 --emit=obj | |
| 18 | ||
| 19 | all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib | |
| 20 | ||
| 21 | staticlib: lib.rs | |
| 22 | 	$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a | |
| 23 | 	$(call EXTRACT_OBJS, liblib.a) | |
| 24 | 	for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done | |
| 25 | ||
| 26 | staticlib-fat-lto: lib.rs | |
| 27 | 	$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat | |
| 28 | 	$(call EXTRACT_OBJS, liblib-fat-lto.a) | |
| 29 | 	for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done | |
| 30 | ||
| 31 | staticlib-thin-lto: lib.rs | |
| 32 | 	$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin | |
| 33 | 	$(call EXTRACT_OBJS, liblib-thin-lto.a) | |
| 34 | 	for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done | |
| 35 | ||
| 36 | rlib: lib.rs | |
| 37 | 	$(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib | |
| 38 | 	$(call EXTRACT_OBJS, liblib.rlib) | |
| 39 | 	for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done | |
| 40 | ||
| 41 | cdylib: lib.rs | |
| 42 | 	$(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o | |
| 43 | 	$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/cdylib.o) | |
| 44 | ||
| 45 | rdylib: lib.rs | |
| 46 | 	$(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o | |
| 47 | 	$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/rdylib.o) | |
| 48 | ||
| 49 | exe: lib.rs | |
| 50 | 	$(BUILD_EXE) -o $(TMPDIR)/exe.o | |
| 51 | 	$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/exe.o) | |
| 52 | ||
| 53 | else | |
| 54 | ||
| 55 | all: | |
| 56 | ||
| 57 | endif |
tests/run-make/cross-lang-lto/rmake.rs created+110| ... | ... | @@ -0,0 +1,110 @@ |
| 1 | // This test checks that the object files we generate are actually | |
| 2 | // LLVM bitcode files (as used by linker LTO plugins) when compiling with | |
| 3 | // -Clinker-plugin-lto. | |
| 4 | // See https://github.com/rust-lang/rust/pull/50000 | |
| 5 | ||
| 6 | #![feature(path_file_prefix)] | |
| 7 | ||
| 8 | use std::path::PathBuf; | |
| 9 | ||
| 10 | use run_make_support::{ | |
| 11 | cwd, has_extension, has_prefix, llvm_ar, llvm_bcanalyzer, path, rfs, rust_lib_name, rustc, | |
| 12 | shallow_find_files, static_lib_name, | |
| 13 | }; | |
| 14 | ||
| 15 | fn main() { | |
| 16 | check_bitcode(LibBuild { | |
| 17 | source: path("lib.rs"), | |
| 18 | crate_type: Some("staticlib"), | |
| 19 | output: path(static_lib_name("liblib")), | |
| 20 | lto: None, | |
| 21 | emit_obj: false, | |
| 22 | }); | |
| 23 | check_bitcode(LibBuild { | |
| 24 | source: path("lib.rs"), | |
| 25 | crate_type: Some("staticlib"), | |
| 26 | output: path(static_lib_name("liblib-fat-lto")), | |
| 27 | lto: Some("fat"), | |
| 28 | emit_obj: false, | |
| 29 | }); | |
| 30 | check_bitcode(LibBuild { | |
| 31 | source: path("lib.rs"), | |
| 32 | crate_type: Some("staticlib"), | |
| 33 | output: path(static_lib_name("liblib-thin-lto")), | |
| 34 | lto: Some("thin"), | |
| 35 | emit_obj: false, | |
| 36 | }); | |
| 37 | check_bitcode(LibBuild { | |
| 38 | source: path("lib.rs"), | |
| 39 | crate_type: Some("rlib"), | |
| 40 | output: path(rust_lib_name("liblib")), | |
| 41 | lto: None, | |
| 42 | emit_obj: false, | |
| 43 | }); | |
| 44 | check_bitcode(LibBuild { | |
| 45 | source: path("lib.rs"), | |
| 46 | crate_type: Some("cdylib"), | |
| 47 | output: path("cdylib.o"), | |
| 48 | lto: None, | |
| 49 | emit_obj: true, | |
| 50 | }); | |
| 51 | check_bitcode(LibBuild { | |
| 52 | source: path("lib.rs"), | |
| 53 | crate_type: Some("dylib"), | |
| 54 | output: path("rdylib.o"), | |
| 55 | lto: None, | |
| 56 | emit_obj: true, | |
| 57 | }); | |
| 58 | check_bitcode(LibBuild { | |
| 59 | source: path("main.rs"), | |
| 60 | crate_type: None, | |
| 61 | output: path("exe.o"), | |
| 62 | lto: None, | |
| 63 | emit_obj: true, | |
| 64 | }); | |
| 65 | } | |
| 66 | ||
| 67 | #[track_caller] | |
| 68 | fn check_bitcode(instructions: LibBuild) { | |
| 69 | let mut rustc = rustc(); | |
| 70 | rustc | |
| 71 | .input(instructions.source) | |
| 72 | .output(&instructions.output) | |
| 73 | .opt_level("2") | |
| 74 | .codegen_units(1) | |
| 75 | .arg("-Clinker-plugin-lto"); | |
| 76 | if instructions.emit_obj { | |
| 77 | rustc.emit("obj"); | |
| 78 | } | |
| 79 | if let Some(crate_type) = instructions.crate_type { | |
| 80 | rustc.crate_type(crate_type); | |
| 81 | } | |
| 82 | if let Some(lto) = instructions.lto { | |
| 83 | rustc.arg(format!("-Clto={lto}")); | |
| 84 | } | |
| 85 | rustc.run(); | |
| 86 | ||
| 87 | if instructions.output.extension().unwrap() != "o" { | |
| 88 | // Remove all potential leftover object files, then turn the output into an object file. | |
| 89 | for object in shallow_find_files(cwd(), |path| has_extension(path, "o")) { | |
| 90 | rfs::remove_file(object); | |
| 91 | } | |
| 92 | llvm_ar().extract().arg(&instructions.output).run(); | |
| 93 | } | |
| 94 | ||
| 95 | for object in shallow_find_files(cwd(), |path| { | |
| 96 | has_prefix(path, instructions.output.file_prefix().unwrap().to_str().unwrap()) | |
| 97 | && has_extension(path, "o") | |
| 98 | }) { | |
| 99 | // All generated object files should be LLVM bitcode files - this will fail otherwise. | |
| 100 | llvm_bcanalyzer().input(object).run(); | |
| 101 | } | |
| 102 | } | |
| 103 | ||
| 104 | struct LibBuild { | |
| 105 | source: PathBuf, | |
| 106 | crate_type: Option<&'static str>, | |
| 107 | output: PathBuf, | |
| 108 | lto: Option<&'static str>, | |
| 109 | emit_obj: bool, | |
| 110 | } |