Ensure `[target]` rustflags are deterministically passed
authorAlex Crichton <alex@alexcrichton.com>
Tue, 16 Jan 2018 19:22:40 +0000 (11:22 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 16 Jan 2018 19:23:49 +0000 (11:23 -0800)
The usage of `HashMap` in the `Config` tables introduced some nondeterminism, so
reverse that with a sort right before we pass it down to rustc. One day we'll
probably want to sort by the position where these keys were defined, but for now
a blanket sort should do the trick.

Closes #4935

src/cargo/ops/cargo_rustc/context.rs
tests/rustflags.rs

index d8f3f3eefdca9feb9300c995b0941b54c1879d25..670ae9985060951ba91d5ba144956733e10c5d91 100644 (file)
@@ -1221,6 +1221,16 @@ fn env_args(config: &Config,
                     None
                 }
             });
+
+            // Note that we may have multiple matching `[target]` sections and
+            // because we're passing flags to the compiler this can affect
+            // cargo's caching and whether it rebuilds. Ensure a deterministic
+            // ordering through sorting for now. We may perhaps one day wish to
+            // ensure a deterministic ordering via the order keys were defined
+            // in files perhaps.
+            let mut cfgs = cfgs.collect::<Vec<_>>();
+            cfgs.sort();
+
             for n in cfgs {
                 let key = format!("target.{}.{}", n, name);
                 if let Some(args) = config.get_list_or_split_string(&key)? {
index 144dad5c2d6a3d7e3c8e5801fae94aa30f4a1258..ff8fe0aac9a3d5b30aa609f3d8fbad076a3b3718 100644 (file)
@@ -974,21 +974,21 @@ fn cfg_rustflags_normal_source() {
 [RUNNING] `rustc [..] --cfg bar[..]`
 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
 "));
-    
+
     assert_that(p.cargo("build").arg("--bin=a").arg("-v"),
                 execs().with_status(0).with_stderr("\
 [COMPILING] foo v0.0.1 ([..])
 [RUNNING] `rustc [..] --cfg bar[..]`
 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
 "));
-    
+
     assert_that(p.cargo("build").arg("--example=b").arg("-v"),
                 execs().with_status(0).with_stderr("\
 [COMPILING] foo v0.0.1 ([..])
 [RUNNING] `rustc [..] --cfg bar[..]`
 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
 "));
-    
+
     assert_that(p.cargo("test").arg("--no-run").arg("-v"),
                 execs().with_status(0).with_stderr("\
 [COMPILING] foo v0.0.1 ([..])
@@ -997,7 +997,7 @@ fn cfg_rustflags_normal_source() {
 [RUNNING] `rustc [..] --cfg bar[..]`
 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
 "));
-    
+
     assert_that(p.cargo("bench").arg("--no-run").arg("-v"),
                 execs().with_status(0).with_stderr("\
 [COMPILING] foo v0.0.1 ([..])
@@ -1006,7 +1006,7 @@ fn cfg_rustflags_normal_source() {
 [RUNNING] `rustc [..] --cfg bar[..]`
 [FINISHED] release [optimized] target(s) in [..]
 "));
-                
+
 }
 
 // target.'cfg(...)'.rustflags takes precedence over build.rustflags
@@ -1069,7 +1069,7 @@ fn cfg_rustflags_precedence() {
 [RUNNING] `rustc [..] --cfg bar[..]`
 [FINISHED] release [optimized] target(s) in [..]
 "));
-                
+
 }
 
 #[test]
@@ -1157,5 +1157,42 @@ fn target_rustflags_string_and_array_form2() {
 [RUNNING] `rustc [..] --cfg foo[..]`
 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
 "));
+}
+
+#[test]
+fn two_matching_in_config() {
+    let p1 = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+        "#)
+        .file(".cargo/config", r#"
+            [target.'cfg(unix)']
+            rustflags = ["--cfg", 'foo="a"']
+            [target.'cfg(windows)']
+            rustflags = ["--cfg", 'foo="a"']
+            [target.'cfg(target_pointer_width = "32")']
+            rustflags = ["--cfg", 'foo="b"']
+            [target.'cfg(target_pointer_width = "64")']
+            rustflags = ["--cfg", 'foo="b"']
+        "#)
+        .file("src/main.rs", r#"
+            fn main() {
+                if cfg!(foo = "a") {
+                    println!("a");
+                } else if cfg!(foo = "b") {
+                    println!("b");
+                } else {
+                    panic!()
+                }
+            }
+        "#)
+        .build();
 
+    assert_that(p1.cargo("run"), execs().with_status(0));
+    assert_that(p1.cargo("build"),
+                execs().with_status(0).with_stderr("\
+[FINISHED] [..]
+"));
 }