authorbors <bors@rust-lang.org> 2024-08-02 10:59:19 UTC
committerbors <bors@rust-lang.org> 2024-08-02 10:59:19 UTC
log53676730146e38e4697b6204c2ee61a9fd6b7e51
treec27f5399f91b70d4c06521235c283c807eee7baf
parent19326022d243f487b5752661cd9b597d620a489e
parent152db2760cbd21b6c4fcd2c22ee1dcb422fb9965

Auto merge of #128352 - Oneirical:daLTOnist-vision, r=jieyouxu

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-18

5 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 {
4242 LlvmNm::new()
4343}
4444
45/// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
46/// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
47pub fn llvm_bcanalyzer() -> LlvmBcanalyzer {
48 LlvmBcanalyzer::new()
49}
50
4551/// A `llvm-readobj` invocation builder.
4652#[derive(Debug)]
4753#[must_use]
......@@ -84,12 +90,20 @@ pub struct LlvmNm {
8490 cmd: Command,
8591}
8692
93/// A `llvm-bcanalyzer` invocation builder.
94#[derive(Debug)]
95#[must_use]
96pub struct LlvmBcanalyzer {
97 cmd: Command,
98}
99
87100crate::macros::impl_common_helpers!(LlvmReadobj);
88101crate::macros::impl_common_helpers!(LlvmProfdata);
89102crate::macros::impl_common_helpers!(LlvmFilecheck);
90103crate::macros::impl_common_helpers!(LlvmObjdump);
91104crate::macros::impl_common_helpers!(LlvmAr);
92105crate::macros::impl_common_helpers!(LlvmNm);
106crate::macros::impl_common_helpers!(LlvmBcanalyzer);
93107
94108/// Generate the path to the bin directory of LLVM.
95109#[must_use]
......@@ -250,6 +264,12 @@ impl LlvmAr {
250264 self
251265 }
252266
267 /// Extract archive members back to files.
268 pub fn extract(&mut self) -> &mut Self {
269 self.cmd.arg("x");
270 self
271 }
272
253273 /// Provide an output, then an input file. Bundled in one function, as llvm-ar has
254274 /// no "--output"-style flag.
255275 pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {
......@@ -274,3 +294,19 @@ impl LlvmNm {
274294 self
275295 }
276296}
297
298impl 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};
4949pub use clang::{clang, Clang};
5050pub use htmldocck::htmldocck;
5151pub 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,
5454};
5555pub use python::python_command;
5656pub 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
44run-make/cross-lang-lto-clang/Makefile
55run-make/cross-lang-lto-pgo-smoketest/Makefile
66run-make/cross-lang-lto-upstream-rlibs/Makefile
7run-make/cross-lang-lto/Makefile
87run-make/dep-info-doesnt-run-much/Makefile
98run-make/dep-info-spaces/Makefile
109run-make/dep-info/Makefile
tests/run-make/cross-lang-lto/Makefile deleted-57
......@@ -1,57 +0,0 @@
1
2include ../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
6ifndef 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
13ASSERT_IS_BITCODE_OBJ=("$(LLVM_BIN_DIR)"/llvm-bcanalyzer $(1))
14EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; "$(LLVM_BIN_DIR)"/llvm-ar x $(1))
15
16BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1
17BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 --emit=obj
18
19all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib
20
21staticlib: 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
26staticlib-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
31staticlib-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
36rlib: 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
41cdylib: lib.rs
42 $(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o
43 $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/cdylib.o)
44
45rdylib: lib.rs
46 $(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o
47 $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/rdylib.o)
48
49exe: lib.rs
50 $(BUILD_EXE) -o $(TMPDIR)/exe.o
51 $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/exe.o)
52
53else
54
55all:
56
57endif
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
8use std::path::PathBuf;
9
10use 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
15fn 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]
68fn 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
104struct LibBuild {
105 source: PathBuf,
106 crate_type: Option<&'static str>,
107 output: PathBuf,
108 lto: Option<&'static str>,
109 emit_obj: bool,
110}