diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index b76515763fbdb..586a362b5e3fe 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -45,7 +45,7 @@ impl Step for Std { let compiler = builder.compiler(0, builder.config.build); let mut cargo = builder.cargo(compiler, Mode::Std, target, cargo_subcommand(builder.kind)); - std_cargo(builder, target, &mut cargo); + std_cargo(builder, target, compiler.stage, &mut cargo); builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo( diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index f44096af6dd53..06ab0a9c310af 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -86,7 +86,7 @@ impl Step for Std { target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter()); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); - std_cargo(builder, target, &mut cargo); + std_cargo(builder, target, compiler.stage, &mut cargo); builder.info(&format!( "Building stage{} std artifacts ({} -> {})", @@ -164,7 +164,7 @@ fn copy_third_party_objects( /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. -pub fn std_cargo(builder: &Builder<'_>, target: Interned, cargo: &mut Cargo) { +pub fn std_cargo(builder: &Builder<'_>, target: Interned, stage: u32, cargo: &mut Cargo) { if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -231,6 +231,18 @@ pub fn std_cargo(builder: &Builder<'_>, target: Interned, cargo: &mut Ca } } } + + // By default, rustc uses `-Cbitcode-in-rlib=yes`, and Cargo overrides that + // with `-Cbitcode-in-rlib=no` for non-LTO builds. However, libstd must be + // built with bitcode so that the produced rlibs can be used for both LTO + // builds (which use bitcode) and non-LTO builds (which use object code). + // So we override the override here! + // + // But we don't bother for the stage 0 compiler because it's never used + // with LTO. + if stage >= 1 { + cargo.rustflag("-Cbitcode-in-rlib=yes"); + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 04da3cc1015b8..fc217a707db94 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -394,7 +394,7 @@ impl Step for Std { let run_cargo_rustdoc_for = |package: &str| { let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc"); - compile::std_cargo(builder, target, &mut cargo); + compile::std_cargo(builder, target, compiler.stage, &mut cargo); // Keep a whitelist so we do not build internal stdlib crates, these will be // build by the rustc step later if enabled. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 85c5d28bb8924..125563b7b6086 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1725,7 +1725,7 @@ impl Step for Crate { let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand()); match mode { Mode::Std => { - compile::std_cargo(builder, target, &mut cargo); + compile::std_cargo(builder, target, compiler.stage, &mut cargo); } Mode::Rustc => { builder.ensure(compile::Rustc { compiler, target }); diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 5dda5ec2cb890..eb7e34ad9ed2e 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -387,6 +387,26 @@ It takes one of the following values: For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to the linker. +## bitcode-in-rlib + +This flag controls whether or not the compiler puts compressed LLVM bitcode +into generated rlibs. It takes one of the following values: + +* `y`, `yes`, `on`, or no value: put bitcode in rlibs (the default). +* `n`, `no`, or `off`: omit bitcode from rlibs. + +LLVM bitcode is only needed when link-time optimization (LTO) is being +performed, but it is enabled by default for backwards compatibility reasons. + +The use of `-C bitcode-in-rlib=no` can significantly improve compile times and +reduce generated file sizes. For these reasons, Cargo uses `-C +bitcode-in-rlib=no` whenever possible. Likewise, if you are building directly +with `rustc` we recommend using `-C bitcode-in-rlib=no` whenever you are not +using LTO. + +If combined with `-C lto`, `-C bitcode-in-rlib=no` will cause `rustc` to abort +at start-up, because the combination is invalid. + [option-emit]: ../command-line-arguments.md#option-emit [option-o-optimize]: ../command-line-arguments.md#option-o-optimize [profile-guided optimization]: ../profile-guided-optimization.md diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index d81a767abd447..db60760e4596f 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -378,7 +378,8 @@ pub struct CompiledModules { } fn need_crate_bitcode_for_rlib(sess: &Session) -> bool { - sess.crate_types.borrow().contains(&config::CrateType::Rlib) + sess.opts.cg.bitcode_in_rlib + && sess.crate_types.borrow().contains(&config::CrateType::Rlib) && sess.opts.output_types.contains_key(&OutputType::Exe) } diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 13c0c8f46b9b0..02fad11d9b879 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -505,6 +505,10 @@ fn test_codegen_options_tracking_hash() { opts = reference.clone(); opts.cg.linker_plugin_lto = LinkerPluginLto::LinkerPluginAuto; assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.cg.bitcode_in_rlib = false; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); } #[test] diff --git a/src/librustc_middle/mir/cache.rs b/src/librustc_middle/mir/cache.rs index af0f7efc3e354..12822cea418d7 100644 --- a/src/librustc_middle/mir/cache.rs +++ b/src/librustc_middle/mir/cache.rs @@ -60,7 +60,6 @@ impl Cache { } /// This will recompute the predecessors cache if it is not available - // njn: typedef? fn predecessors( &mut self, body: &Body<'_>, diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 2513cfa73e56c..f6d7e091e00d6 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1685,6 +1685,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } + if !cg.bitcode_in_rlib { + match cg.lto { + LtoCli::No | LtoCli::Unspecified => {} + LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => early_error( + error_format, + "options `-C bitcode-in-rlib=no` and `-C lto` are incompatible", + ), + } + } + let prints = collect_print_requests(&mut cg, &mut debugging_opts, matches, error_format); let cg = cg; diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 5e17fc989856b..62eb3fca59531 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -703,6 +703,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "compile the program with profiling instrumentation"), profile_use: Option = (None, parse_opt_pathbuf, [TRACKED], "use the given `.profdata` file for profile-guided optimization"), + bitcode_in_rlib: bool = (true, parse_bool, [TRACKED], + "emit bitcode in rlibs (default: yes)"), } options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, diff --git a/src/test/ui/lto-and-no-bitcode-in-rlib.rs b/src/test/ui/lto-and-no-bitcode-in-rlib.rs new file mode 100644 index 0000000000000..1dd11ce3d2467 --- /dev/null +++ b/src/test/ui/lto-and-no-bitcode-in-rlib.rs @@ -0,0 +1,3 @@ +// compile-flags: -C lto -C bitcode-in-rlib=no + +fn main() {} diff --git a/src/test/ui/lto-and-no-bitcode-in-rlib.stderr b/src/test/ui/lto-and-no-bitcode-in-rlib.stderr new file mode 100644 index 0000000000000..2221fc1645d61 --- /dev/null +++ b/src/test/ui/lto-and-no-bitcode-in-rlib.stderr @@ -0,0 +1,2 @@ +error: options `-C bitcode-in-rlib=no` and `-C lto` are incompatible +