Skip to content

Commit

Permalink
Allow configuration of LTO in [profile]
Browse files Browse the repository at this point in the history
This should help give access to ThinLTO when desired!
  • Loading branch information
alexcrichton committed Jan 26, 2018
1 parent 1d6dfea commit f52f489
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 10 deletions.
10 changes: 8 additions & 2 deletions src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl ser::Serialize for TargetKind {
pub struct Profile {
pub opt_level: String,
#[serde(skip_serializing)]
pub lto: bool,
pub lto: Lto,
#[serde(skip_serializing)]
pub codegen_units: Option<u32>, // None = use rustc default
#[serde(skip_serializing)]
Expand All @@ -181,6 +181,12 @@ pub struct Profile {
pub incremental: bool,
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum Lto {
Bool(bool),
Named(String),
}

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct Profiles {
pub release: Profile,
Expand Down Expand Up @@ -702,7 +708,7 @@ impl Default for Profile {
fn default() -> Profile {
Profile {
opt_level: "0".to_string(),
lto: false,
lto: Lto::Bool(false),
codegen_units: None,
rustc_args: None,
rustdoc_args: None,
Expand Down
19 changes: 15 additions & 4 deletions src/cargo/ops/cargo_rustc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use serde_json;

use core::{Package, PackageId, PackageSet, Target, Resolve};
use core::{Profile, Profiles, Workspace};
use core::manifest::Lto;
use core::shell::ColorChoice;
use util::{self, ProcessBuilder, machine_message};
use util::{Config, internal, profile, join_paths};
Expand Down Expand Up @@ -744,7 +745,7 @@ fn build_base_args<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
unit: &Unit<'a>,
crate_types: &[&str]) -> CargoResult<()> {
let Profile {
ref opt_level, lto, codegen_units, ref rustc_args, debuginfo,
ref opt_level, ref lto, codegen_units, ref rustc_args, debuginfo,
debug_assertions, overflow_checks, rpath, test, doc: _doc,
run_custom_build, ref panic, rustdoc_args: _, check, incremental: _,
} = *unit.profile;
Expand Down Expand Up @@ -806,9 +807,19 @@ fn build_base_args<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,

// Disable LTO for host builds as prefer_dynamic and it are mutually
// exclusive.
if unit.target.can_lto() && lto && !unit.target.for_host() {
cmd.args(&["-C", "lto"]);
} else if let Some(n) = codegen_units {
if unit.target.can_lto() && !unit.target.for_host() {
match *lto {
Lto::Bool(false) => {}
Lto::Bool(true) => {
cmd.args(&["-C", "lto"]);
}
Lto::Named(ref s) => {
cmd.arg("-C").arg(format!("lto={}", s));
}
}
}

if let Some(n) = codegen_units {
// There are some restrictions with LTO and codegen-units, so we
// only add codegen units when LTO is not used.
cmd.arg("-C").arg(&format!("codegen-units={}", n));
Expand Down
12 changes: 8 additions & 4 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use core::{SourceId, Profiles, PackageIdSpec, GitReference, WorkspaceConfig, Wor
use core::{Summary, Manifest, Target, Dependency, PackageId};
use core::{EitherManifest, VirtualManifest, Features, Feature};
use core::dependency::{Kind, Platform};
use core::manifest::{LibKind, Profile, ManifestMetadata};
use core::manifest::{LibKind, Profile, ManifestMetadata, Lto};
use sources::CRATES_IO;
use util::paths;
use util::{self, ToUrl, Config};
Expand Down Expand Up @@ -327,7 +327,7 @@ impl<'de> de::Deserialize<'de> for U32OrBool {
pub struct TomlProfile {
#[serde(rename = "opt-level")]
opt_level: Option<TomlOptLevel>,
lto: Option<bool>,
lto: Option<StringOrBool>,
#[serde(rename = "codegen-units")]
codegen_units: Option<u32>,
debug: Option<U32OrBool>,
Expand Down Expand Up @@ -1150,7 +1150,7 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {

fn merge(profile: Profile, toml: Option<&TomlProfile>) -> Profile {
let &TomlProfile {
ref opt_level, lto, codegen_units, ref debug, debug_assertions, rpath,
ref opt_level, ref lto, codegen_units, ref debug, debug_assertions, rpath,
ref panic, ref overflow_checks, ref incremental,
} = match toml {
Some(toml) => toml,
Expand All @@ -1164,7 +1164,11 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
};
Profile {
opt_level: opt_level.clone().unwrap_or(TomlOptLevel(profile.opt_level)).0,
lto: lto.unwrap_or(profile.lto),
lto: match *lto {
Some(StringOrBool::Bool(b)) => Lto::Bool(b),
Some(StringOrBool::String(ref n)) => Lto::Named(n.clone()),
None => profile.lto,
},
codegen_units: codegen_units,
rustc_args: None,
rustdoc_args: None,
Expand Down
26 changes: 26 additions & 0 deletions tests/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,3 +986,29 @@ fn workspace_produces_rlib() {
assert_that(&p.root().join("target/debug/libfoo.rlib"), existing_file());

}

#[test]
fn thin_lto_works() {
if !cargotest::is_nightly() {
return
}
let p = project("foo")
.file("Cargo.toml", r#"
[project]
name = "top"
version = "0.5.0"
authors = []
[profile.release]
lto = 'thin'
"#)
.file("src/main.rs", "fn main() {}")
.build();

assert_that(p.cargo("build").arg("--release").arg("-v"),
execs().with_stderr("\
[COMPILING] top [..]
[RUNNING] `rustc [..] -C lto=thin [..]`
[FINISHED] [..]
"));
}

0 comments on commit f52f489

Please sign in to comment.