| // 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, |
| } |