diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 1687a5d2ace..7007d0dd8c2 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -796,6 +796,7 @@ fn build_base_args( let bcx = cx.bcx; let Profile { ref opt_level, + codegen_backend, codegen_units, debuginfo, debug_assertions, @@ -860,6 +861,10 @@ fn build_base_args( } } + if let Some(backend) = codegen_backend { + cmd.arg("-Z").arg(&format!("codegen-backend={}", backend)); + } + if let Some(n) = codegen_units { cmd.arg("-C").arg(&format!("codegen-units={}", n)); } diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index e338a66acea..31fe062ca0d 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -402,6 +402,9 @@ features! { // Allow to specify per-package targets (compile kinds) (unstable, per_package_target, "", "reference/unstable.html#per-package-target"), + + // Allow to specify which codegen backend should be used. + (unstable, codegen_backend, "", "reference/unstable.html#codegen-backend"), } pub struct Feature { diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 04ec2e6f9e1..ac167f17363 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -565,6 +565,9 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) { Some(StringOrBool::String(ref n)) => profile.lto = Lto::Named(InternedString::new(n)), None => {} } + if toml.codegen_backend.is_some() { + profile.codegen_backend = toml.codegen_backend; + } if toml.codegen_units.is_some() { profile.codegen_units = toml.codegen_units; } @@ -626,6 +629,8 @@ pub struct Profile { pub root: ProfileRoot, pub lto: Lto, // `None` means use rustc default. + pub codegen_backend: Option, + // `None` means use rustc default. pub codegen_units: Option, pub debuginfo: Option, pub split_debuginfo: Option, @@ -644,6 +649,7 @@ impl Default for Profile { opt_level: InternedString::new("0"), root: ProfileRoot::Debug, lto: Lto::Bool(false), + codegen_backend: None, codegen_units: None, debuginfo: None, debug_assertions: false, @@ -670,6 +676,7 @@ compact_debug! { opt_level lto root + codegen_backend codegen_units debuginfo split_debuginfo @@ -757,6 +764,7 @@ impl Profile { ( self.opt_level, self.lto, + self.codegen_backend, self.codegen_units, self.debuginfo, self.split_debuginfo, diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index e32160ea2b3..7c472bf8b2f 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -433,6 +433,7 @@ pub enum U32OrBool { pub struct TomlProfile { pub opt_level: Option, pub lto: Option, + pub codegen_backend: Option, pub codegen_units: Option, pub debug: Option, pub split_debuginfo: Option, @@ -491,12 +492,12 @@ impl TomlProfile { ) -> CargoResult<()> { if let Some(ref profile) = self.build_override { features.require(Feature::profile_overrides())?; - profile.validate_override("build-override")?; + profile.validate_override("build-override", features)?; } if let Some(ref packages) = self.package { features.require(Feature::profile_overrides())?; for profile in packages.values() { - profile.validate_override("package")?; + profile.validate_override("package", features)?; } } @@ -562,6 +563,18 @@ impl TomlProfile { if self.strip.is_some() { features.require(Feature::strip())?; } + + if let Some(codegen_backend) = &self.codegen_backend { + features.require(Feature::codegen_backend())?; + if codegen_backend.contains(|c: char| !c.is_ascii_alphanumeric() && c != '_') { + bail!( + "`profile.{}.codegen-backend` setting of `{}` is not a valid backend name.", + name, + codegen_backend, + ); + } + } + Ok(()) } @@ -642,7 +655,7 @@ impl TomlProfile { Ok(()) } - fn validate_override(&self, which: &str) -> CargoResult<()> { + fn validate_override(&self, which: &str, features: &Features) -> CargoResult<()> { if self.package.is_some() { bail!("package-specific profiles cannot be nested"); } @@ -658,6 +671,9 @@ impl TomlProfile { if self.rpath.is_some() { bail!("`rpath` may not be specified in a `{}` profile", which) } + if self.codegen_backend.is_some() { + features.require(Feature::codegen_backend())?; + } Ok(()) } @@ -671,6 +687,10 @@ impl TomlProfile { self.lto = Some(v.clone()); } + if let Some(v) = profile.codegen_backend { + self.codegen_backend = Some(v); + } + if let Some(v) = profile.codegen_units { self.codegen_units = Some(v); } diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 0eafbd0e5fe..6bdc2ac582e 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1406,3 +1406,21 @@ environment variables. The `rust-version` field in `Cargo.toml` has been stabilized in the 1.56 release. See the [rust-version field](manifest.html#the-rust-version-field) for more information on using the `rust-version` field and the `--ignore-rust-version` option. + +### codegen-backend + +The `codegen-backend` feature makes it possible to select the codegen backend used by rustc using a +profile. + +Example: + +```toml +[package] +name = "foo" + +[dependencies] +serde = "1.0.117" + +[profile.dev.package.foo] +codegen-backend = "cranelift" +``` diff --git a/tests/testsuite/unit_graph.rs b/tests/testsuite/unit_graph.rs index 977d04915c5..b61cb453f14 100644 --- a/tests/testsuite/unit_graph.rs +++ b/tests/testsuite/unit_graph.rs @@ -49,177 +49,183 @@ fn simple() { .masquerade_as_nightly_cargo() .with_json( r#"{ - "version": 1, + "roots": [ + 3 + ], "units": [ { + "dependencies": [ + { + "extern_crate_name": "b", + "index": 1, + "noprelude": false, + "public": false + } + ], + "features": [ + "feata" + ], + "mode": "build", "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, + "profile": { + "codegen_backend": null, + "codegen_units": null, + "debug_assertions": true, + "debuginfo": 2, + "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false, + "split_debuginfo": "{...}", + "strip": "none" + }, "target": { - "kind": [ + "crate_types": [ "lib" ], - "crate_types": [ + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ "lib" ], "name": "a", "src_path": "[..]/a-1.0.0/src/lib.rs", - "edition": "2015", - "doc": true, - "doctest": true, "test": true - }, + } + }, + { + "dependencies": [ + { + "extern_crate_name": "c", + "index": 2, + "noprelude": false, + "public": false + } + ], + "features": [ + "featb" + ], + "mode": "build", + "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, "profile": { - "name": "dev", - "opt_level": "0", - "lto": "false", + "codegen_backend": null, "codegen_units": null, - "debuginfo": 2, "debug_assertions": true, - "overflow_checks": true, - "rpath": false, + "debuginfo": 2, "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, "panic": "unwind", - "strip": "none", - "split_debuginfo": "{...}" + "rpath": false, + "split_debuginfo": "{...}", + "strip": "none" }, - "platform": null, - "mode": "build", - "features": [ - "feata" - ], - "dependencies": [ - { - "index": 1, - "extern_crate_name": "b", - "public": false, - "noprelude": false - } - ] - }, - { - "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "target": { - "kind": [ + "crate_types": [ "lib" ], - "crate_types": [ + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ "lib" ], "name": "b", "src_path": "[..]/b-1.0.0/src/lib.rs", - "edition": "2015", - "doc": true, - "doctest": true, "test": true - }, + } + }, + { + "dependencies": [], + "features": [ + "featc" + ], + "mode": "build", + "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, "profile": { - "name": "dev", - "opt_level": "0", - "lto": "false", + "codegen_backend": null, "codegen_units": null, - "debuginfo": 2, "debug_assertions": true, - "overflow_checks": true, - "rpath": false, + "debuginfo": 2, "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, "panic": "unwind", - "strip": "none", - "split_debuginfo": "{...}" + "rpath": false, + "split_debuginfo": "{...}", + "strip": "none" }, - "platform": null, - "mode": "build", - "features": [ - "featb" - ], - "dependencies": [ - { - "index": 2, - "extern_crate_name": "c", - "public": false, - "noprelude": false - } - ] - }, - { - "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "target": { - "kind": [ + "crate_types": [ "lib" ], - "crate_types": [ + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ "lib" ], "name": "c", "src_path": "[..]/c-1.0.0/src/lib.rs", - "edition": "2015", - "test": true, - "doc": true, - "doctest": true - }, + "test": true + } + }, + { + "dependencies": [ + { + "extern_crate_name": "a", + "index": 0, + "noprelude": false, + "public": false + } + ], + "features": [], + "mode": "build", + "pkg_id": "foo 0.1.0 (path+file://[..]/foo)", + "platform": null, "profile": { - "name": "dev", - "opt_level": "0", - "lto": "false", + "codegen_backend": null, "codegen_units": null, - "debuginfo": 2, "debug_assertions": true, - "overflow_checks": true, - "rpath": false, + "debuginfo": 2, "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, "panic": "unwind", - "strip": "none", - "split_debuginfo": "{...}" + "rpath": false, + "split_debuginfo": "{...}", + "strip": "none" }, - "platform": null, - "mode": "build", - "features": [ - "featc" - ], - "dependencies": [] - }, - { - "pkg_id": "foo 0.1.0 (path+file://[..]/foo)", "target": { - "kind": [ + "crate_types": [ "lib" ], - "crate_types": [ + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ "lib" ], "name": "foo", "src_path": "[..]/foo/src/lib.rs", - "edition": "2015", - "test": true, - "doc": true, - "doctest": true - }, - "profile": { - "name": "dev", - "opt_level": "0", - "lto": "false", - "codegen_units": null, - "debuginfo": 2, - "debug_assertions": true, - "overflow_checks": true, - "rpath": false, - "incremental": false, - "panic": "unwind", - "strip": "none", - "split_debuginfo": "{...}" - }, - "platform": null, - "mode": "build", - "features": [], - "dependencies": [ - { - "index": 0, - "extern_crate_name": "a", - "public": false, - "noprelude": false - } - ] + "test": true + } } ], - "roots": [3] + "version": 1 } "#, )