Skip to content

Commit f5348cc

Browse files
committed
Auto merge of #3854 - tee-too:fix-3499, r=alexcrichton
Add `[target.'cfg(...)']` syntax for rustc(doc)flags in .cargo/config Allow to use the Rust `cfg(...)` syntax to configure rust(doc)flags. The flags are concatenated when a build matches several `cfg`, or several `cfg` and a $triple. Fix #3499.
2 parents 305fa68 + e6e6f10 commit f5348cc

File tree

3 files changed

+117
-6
lines changed

3 files changed

+117
-6
lines changed

src/cargo/ops/cargo_rustc/context.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::sync::Arc;
1111
use core::{Package, PackageId, PackageSet, Resolve, Target, Profile};
1212
use core::{TargetKind, Profiles, Dependency, Workspace};
1313
use core::dependency::Kind as DepKind;
14-
use util::{self, CargoResult, ChainError, internal, Config, profile, Cfg, human};
14+
use util::{self, CargoResult, ChainError, internal, Config, profile, Cfg, CfgExpr, human};
1515

1616
use super::TargetConfig;
1717
use super::custom_build::{BuildState, BuildScripts};
@@ -178,6 +178,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
178178
-> CargoResult<()> {
179179
let rustflags = env_args(self.config,
180180
&self.build_config,
181+
&self.info(&kind),
181182
kind,
182183
"RUSTFLAGS")?;
183184
let mut process = self.config.rustc()?.process();
@@ -872,22 +873,30 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
872873
}
873874

874875
pub fn rustflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
875-
env_args(self.config, &self.build_config, unit.kind, "RUSTFLAGS")
876+
env_args(self.config, &self.build_config, self.info(&unit.kind), unit.kind, "RUSTFLAGS")
876877
}
877878

878879
pub fn rustdocflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
879-
env_args(self.config, &self.build_config, unit.kind, "RUSTDOCFLAGS")
880+
env_args(self.config, &self.build_config, self.info(&unit.kind), unit.kind, "RUSTDOCFLAGS")
880881
}
881882

882883
pub fn show_warnings(&self, pkg: &PackageId) -> bool {
883884
pkg.source_id().is_path() || self.config.extra_verbose()
884885
}
886+
887+
fn info(&self, kind: &Kind) -> &TargetInfo {
888+
match *kind {
889+
Kind::Host => &self.host_info,
890+
Kind::Target => &self.target_info,
891+
}
892+
}
885893
}
886894

887895
// Acquire extra flags to pass to the compiler from the
888896
// RUSTFLAGS environment variable and similar config values
889897
fn env_args(config: &Config,
890898
build_config: &BuildConfig,
899+
target_info: &TargetInfo,
891900
kind: Kind,
892901
name: &str) -> CargoResult<Vec<String>> {
893902
// We *want* to apply RUSTFLAGS only to builds for the
@@ -928,13 +937,34 @@ fn env_args(config: &Config,
928937
return Ok(args.collect());
929938
}
930939

940+
let mut rustflags = Vec::new();
941+
931942
let name = name.chars().flat_map(|c| c.to_lowercase()).collect::<String>();
932-
// Then the target.*.rustflags value
943+
// Then the target.*.rustflags value...
933944
let target = build_config.requested_target.as_ref().unwrap_or(&build_config.host_triple);
934945
let key = format!("target.{}.{}", target, name);
935946
if let Some(args) = config.get_list_or_split_string(&key)? {
936947
let args = args.val.into_iter();
937-
return Ok(args.collect());
948+
rustflags.extend(args);
949+
}
950+
// ...including target.'cfg(...)'.rustflags
951+
if let Some(ref target_cfg) = target_info.cfg {
952+
if let Some(table) = config.get_table("target")? {
953+
let cfgs = table.val.iter().map(|(t, _)| (CfgExpr::from_str(t), t))
954+
.filter_map(|(c, n)| c.map(|c| (c, n)).ok())
955+
.filter(|&(ref c, _)| c.matches(target_cfg));
956+
for (_, n) in cfgs {
957+
let key = format!("target.'{}'.{}", n, name);
958+
if let Some(args) = config.get_list_or_split_string(&key)? {
959+
let args = args.val.into_iter();
960+
rustflags.extend(args);
961+
}
962+
}
963+
}
964+
}
965+
966+
if !rustflags.is_empty() {
967+
return Ok(rustflags);
938968
}
939969

940970
// Then the build.rustflags value

src/doc/config.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ vcs = "none"
5858

5959
# For the following sections, $triple refers to any valid target triple, not the
6060
# literal string "$triple", and it will apply whenever that target triple is
61-
# being compiled to.
61+
# being compiled to. 'cfg(...)' refers to the Rust-like `#[cfg]` syntax for
62+
# conditional compilation.
6263
[target]
6364
# For Cargo builds which do not mention --target, this is the linker
6465
# which is passed to rustc (via `-C linker=`). By default this flag is not
@@ -73,6 +74,13 @@ linker = ".."
7374
# this value overrides build.rustflags when both are present
7475
rustflags = ["..", ".."]
7576

77+
[target.'cfg(...)']
78+
# Similar for the $triple configuration, but using the `cfg` syntax.
79+
# If several `cfg` and $triple targets are candidates, then the rustflags
80+
# are concatenated. The `cfg` syntax only applies to rustflags, and not to
81+
# linker.
82+
rustflags = ["..", ".."]
83+
7684
# Configuration keys related to the registry
7785
[registry]
7886
index = "..." # URL of the registry index (defaults to the central repository)

tests/rustflags.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,79 @@ fn target_rustflags_precedence() {
950950
execs().with_status(101));
951951
}
952952

953+
#[test]
954+
fn cfg_rustflags_normal_source() {
955+
let p = project("foo")
956+
.file("Cargo.toml", r#"
957+
[package]
958+
name = "foo"
959+
version = "0.0.1"
960+
"#)
961+
.file("src/lib.rs", "")
962+
.file("src/bin/a.rs", "fn main() {}")
963+
.file("examples/b.rs", "fn main() {}")
964+
.file("tests/c.rs", "#[test] fn f() { }")
965+
.file("benches/d.rs", r#"
966+
#![feature(test)]
967+
extern crate test;
968+
#[bench] fn run1(_ben: &mut test::Bencher) { }"#)
969+
.file(".cargo/config", "
970+
[target.'cfg(feature=\"feat\")']
971+
rustflags = [\"-Z\", \"bogus\"]
972+
");
973+
p.build();
974+
975+
assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
976+
.arg("--lib"),
977+
execs().with_status(101));
978+
assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
979+
.arg("--bin=a"),
980+
execs().with_status(101));
981+
assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
982+
.arg("--example=b"),
983+
execs().with_status(101));
984+
assert_that(p.cargo("test").arg("--features").arg("\"feat\""),
985+
execs().with_status(101));
986+
assert_that(p.cargo("bench").arg("--features").arg("\"feat\""),
987+
execs().with_status(101));
988+
}
989+
990+
// target.'cfg(...)'.rustflags takes precedence over build.rustflags
991+
#[test]
992+
fn cfg_rustflags_precedence() {
993+
let p = project("foo")
994+
.file("Cargo.toml", r#"
995+
[package]
996+
name = "foo"
997+
version = "0.0.1"
998+
"#)
999+
.file("src/lib.rs", "")
1000+
.file(".cargo/config", "
1001+
[build]
1002+
rustflags = [\"--cfg\", \"foo\"]
1003+
1004+
[target.'cfg(feature = \"feat\"')]
1005+
rustflags = [\"-Z\", \"bogus\"]
1006+
");
1007+
p.build();
1008+
1009+
assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
1010+
.arg("--lib"),
1011+
execs().with_status(101));
1012+
assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
1013+
.arg("--bin=a"),
1014+
execs().with_status(101));
1015+
assert_that(p.cargo("build").arg("--features").arg("\"feat\"")
1016+
.arg("--example=b"),
1017+
execs().with_status(101));
1018+
assert_that(p.cargo("test").arg("--features").arg("\"feat\""),
1019+
execs().with_status(101));
1020+
assert_that(p.cargo("bench").arg("--features").arg("\"feat\""),
1021+
execs().with_status(101));
1022+
}
1023+
1024+
1025+
9531026
#[test]
9541027
fn target_rustflags_string_and_array_form1() {
9551028
let p1 = project("foo")

0 commit comments

Comments
 (0)