mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
rewrite cross-lang-lto to rmake
This commit is contained in:
parent
e552c168c7
commit
152db2760c
@ -42,6 +42,12 @@ pub fn llvm_nm() -> LlvmNm {
|
|||||||
LlvmNm::new()
|
LlvmNm::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
|
||||||
|
/// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
|
||||||
|
pub fn llvm_bcanalyzer() -> LlvmBcanalyzer {
|
||||||
|
LlvmBcanalyzer::new()
|
||||||
|
}
|
||||||
|
|
||||||
/// A `llvm-readobj` invocation builder.
|
/// A `llvm-readobj` invocation builder.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -84,12 +90,20 @@ pub struct LlvmNm {
|
|||||||
cmd: Command,
|
cmd: Command,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A `llvm-bcanalyzer` invocation builder.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[must_use]
|
||||||
|
pub struct LlvmBcanalyzer {
|
||||||
|
cmd: Command,
|
||||||
|
}
|
||||||
|
|
||||||
crate::macros::impl_common_helpers!(LlvmReadobj);
|
crate::macros::impl_common_helpers!(LlvmReadobj);
|
||||||
crate::macros::impl_common_helpers!(LlvmProfdata);
|
crate::macros::impl_common_helpers!(LlvmProfdata);
|
||||||
crate::macros::impl_common_helpers!(LlvmFilecheck);
|
crate::macros::impl_common_helpers!(LlvmFilecheck);
|
||||||
crate::macros::impl_common_helpers!(LlvmObjdump);
|
crate::macros::impl_common_helpers!(LlvmObjdump);
|
||||||
crate::macros::impl_common_helpers!(LlvmAr);
|
crate::macros::impl_common_helpers!(LlvmAr);
|
||||||
crate::macros::impl_common_helpers!(LlvmNm);
|
crate::macros::impl_common_helpers!(LlvmNm);
|
||||||
|
crate::macros::impl_common_helpers!(LlvmBcanalyzer);
|
||||||
|
|
||||||
/// Generate the path to the bin directory of LLVM.
|
/// Generate the path to the bin directory of LLVM.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -250,6 +264,12 @@ impl LlvmAr {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract archive members back to files.
|
||||||
|
pub fn extract(&mut self) -> &mut Self {
|
||||||
|
self.cmd.arg("x");
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Provide an output, then an input file. Bundled in one function, as llvm-ar has
|
/// Provide an output, then an input file. Bundled in one function, as llvm-ar has
|
||||||
/// no "--output"-style flag.
|
/// no "--output"-style flag.
|
||||||
pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {
|
pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {
|
||||||
@ -274,3 +294,19 @@ impl LlvmNm {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LlvmBcanalyzer {
|
||||||
|
/// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
|
||||||
|
/// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let llvm_bcanalyzer = llvm_bin_dir().join("llvm-bcanalyzer");
|
||||||
|
let cmd = Command::new(llvm_bcanalyzer);
|
||||||
|
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 use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc};
|
|||||||
pub use clang::{clang, Clang};
|
pub use clang::{clang, Clang};
|
||||||
pub use htmldocck::htmldocck;
|
pub use htmldocck::htmldocck;
|
||||||
pub use llvm::{
|
pub use llvm::{
|
||||||
llvm_ar, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr,
|
llvm_ar, llvm_bcanalyzer, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj,
|
||||||
LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj,
|
LlvmAr, LlvmBcanalyzer, LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj,
|
||||||
};
|
};
|
||||||
pub use python::python_command;
|
pub use python::python_command;
|
||||||
pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
|
pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
|
||||||
|
@ -4,7 +4,6 @@ run-make/cdylib-dylib-linkage/Makefile
|
|||||||
run-make/cross-lang-lto-clang/Makefile
|
run-make/cross-lang-lto-clang/Makefile
|
||||||
run-make/cross-lang-lto-pgo-smoketest/Makefile
|
run-make/cross-lang-lto-pgo-smoketest/Makefile
|
||||||
run-make/cross-lang-lto-upstream-rlibs/Makefile
|
run-make/cross-lang-lto-upstream-rlibs/Makefile
|
||||||
run-make/cross-lang-lto/Makefile
|
|
||||||
run-make/dep-info-doesnt-run-much/Makefile
|
run-make/dep-info-doesnt-run-much/Makefile
|
||||||
run-make/dep-info-spaces/Makefile
|
run-make/dep-info-spaces/Makefile
|
||||||
run-make/dep-info/Makefile
|
run-make/dep-info/Makefile
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
|
|
||||||
include ../tools.mk
|
|
||||||
|
|
||||||
# ignore windows due to libLLVM being present in PATH and the PATH and library path being the same
|
|
||||||
# (so fixing it is harder). See #57765 for context
|
|
||||||
ifndef IS_WINDOWS
|
|
||||||
|
|
||||||
# This test makes sure that the object files we generate are actually
|
|
||||||
# LLVM bitcode files (as used by linker LTO plugins) when compiling with
|
|
||||||
# -Clinker-plugin-lto.
|
|
||||||
|
|
||||||
# this only succeeds for bitcode files
|
|
||||||
ASSERT_IS_BITCODE_OBJ=("$(LLVM_BIN_DIR)"/llvm-bcanalyzer $(1))
|
|
||||||
EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; "$(LLVM_BIN_DIR)"/llvm-ar x $(1))
|
|
||||||
|
|
||||||
BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1
|
|
||||||
BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 --emit=obj
|
|
||||||
|
|
||||||
all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib
|
|
||||||
|
|
||||||
staticlib: lib.rs
|
|
||||||
$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a
|
|
||||||
$(call EXTRACT_OBJS, liblib.a)
|
|
||||||
for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
|
|
||||||
|
|
||||||
staticlib-fat-lto: lib.rs
|
|
||||||
$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat
|
|
||||||
$(call EXTRACT_OBJS, liblib-fat-lto.a)
|
|
||||||
for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
|
|
||||||
|
|
||||||
staticlib-thin-lto: lib.rs
|
|
||||||
$(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin
|
|
||||||
$(call EXTRACT_OBJS, liblib-thin-lto.a)
|
|
||||||
for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
|
|
||||||
|
|
||||||
rlib: lib.rs
|
|
||||||
$(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib
|
|
||||||
$(call EXTRACT_OBJS, liblib.rlib)
|
|
||||||
for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
|
|
||||||
|
|
||||||
cdylib: lib.rs
|
|
||||||
$(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o
|
|
||||||
$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/cdylib.o)
|
|
||||||
|
|
||||||
rdylib: lib.rs
|
|
||||||
$(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o
|
|
||||||
$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/rdylib.o)
|
|
||||||
|
|
||||||
exe: lib.rs
|
|
||||||
$(BUILD_EXE) -o $(TMPDIR)/exe.o
|
|
||||||
$(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/exe.o)
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
all:
|
|
||||||
|
|
||||||
endif
|
|
110
tests/run-make/cross-lang-lto/rmake.rs
Normal file
110
tests/run-make/cross-lang-lto/rmake.rs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// This test checks that the object files we generate are actually
|
||||||
|
// LLVM bitcode files (as used by linker LTO plugins) when compiling with
|
||||||
|
// -Clinker-plugin-lto.
|
||||||
|
// See https://github.com/rust-lang/rust/pull/50000
|
||||||
|
|
||||||
|
#![feature(path_file_prefix)]
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use run_make_support::{
|
||||||
|
cwd, has_extension, has_prefix, llvm_ar, llvm_bcanalyzer, path, rfs, rust_lib_name, rustc,
|
||||||
|
shallow_find_files, static_lib_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
check_bitcode(LibBuild {
|
||||||
|
source: path("lib.rs"),
|
||||||
|
crate_type: Some("staticlib"),
|
||||||
|
output: path(static_lib_name("liblib")),
|
||||||
|
lto: None,
|
||||||
|
emit_obj: false,
|
||||||
|
});
|
||||||
|
check_bitcode(LibBuild {
|
||||||
|
source: path("lib.rs"),
|
||||||
|
crate_type: Some("staticlib"),
|
||||||
|
output: path(static_lib_name("liblib-fat-lto")),
|
||||||
|
lto: Some("fat"),
|
||||||
|
emit_obj: false,
|
||||||
|
});
|
||||||
|
check_bitcode(LibBuild {
|
||||||
|
source: path("lib.rs"),
|
||||||
|
crate_type: Some("staticlib"),
|
||||||
|
output: path(static_lib_name("liblib-thin-lto")),
|
||||||
|
lto: Some("thin"),
|
||||||
|
emit_obj: false,
|
||||||
|
});
|
||||||
|
check_bitcode(LibBuild {
|
||||||
|
source: path("lib.rs"),
|
||||||
|
crate_type: Some("rlib"),
|
||||||
|
output: path(rust_lib_name("liblib")),
|
||||||
|
lto: None,
|
||||||
|
emit_obj: false,
|
||||||
|
});
|
||||||
|
check_bitcode(LibBuild {
|
||||||
|
source: path("lib.rs"),
|
||||||
|
crate_type: Some("cdylib"),
|
||||||
|
output: path("cdylib.o"),
|
||||||
|
lto: None,
|
||||||
|
emit_obj: true,
|
||||||
|
});
|
||||||
|
check_bitcode(LibBuild {
|
||||||
|
source: path("lib.rs"),
|
||||||
|
crate_type: Some("dylib"),
|
||||||
|
output: path("rdylib.o"),
|
||||||
|
lto: None,
|
||||||
|
emit_obj: true,
|
||||||
|
});
|
||||||
|
check_bitcode(LibBuild {
|
||||||
|
source: path("main.rs"),
|
||||||
|
crate_type: None,
|
||||||
|
output: path("exe.o"),
|
||||||
|
lto: None,
|
||||||
|
emit_obj: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn check_bitcode(instructions: LibBuild) {
|
||||||
|
let mut rustc = rustc();
|
||||||
|
rustc
|
||||||
|
.input(instructions.source)
|
||||||
|
.output(&instructions.output)
|
||||||
|
.opt_level("2")
|
||||||
|
.codegen_units(1)
|
||||||
|
.arg("-Clinker-plugin-lto");
|
||||||
|
if instructions.emit_obj {
|
||||||
|
rustc.emit("obj");
|
||||||
|
}
|
||||||
|
if let Some(crate_type) = instructions.crate_type {
|
||||||
|
rustc.crate_type(crate_type);
|
||||||
|
}
|
||||||
|
if let Some(lto) = instructions.lto {
|
||||||
|
rustc.arg(format!("-Clto={lto}"));
|
||||||
|
}
|
||||||
|
rustc.run();
|
||||||
|
|
||||||
|
if instructions.output.extension().unwrap() != "o" {
|
||||||
|
// Remove all potential leftover object files, then turn the output into an object file.
|
||||||
|
for object in shallow_find_files(cwd(), |path| has_extension(path, "o")) {
|
||||||
|
rfs::remove_file(object);
|
||||||
|
}
|
||||||
|
llvm_ar().extract().arg(&instructions.output).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
for object in shallow_find_files(cwd(), |path| {
|
||||||
|
has_prefix(path, instructions.output.file_prefix().unwrap().to_str().unwrap())
|
||||||
|
&& has_extension(path, "o")
|
||||||
|
}) {
|
||||||
|
// All generated object files should be LLVM bitcode files - this will fail otherwise.
|
||||||
|
llvm_bcanalyzer().input(object).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LibBuild {
|
||||||
|
source: PathBuf,
|
||||||
|
crate_type: Option<&'static str>,
|
||||||
|
output: PathBuf,
|
||||||
|
lto: Option<&'static str>,
|
||||||
|
emit_obj: bool,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user