Repository: dtolnay/cxx (language: rust)

Issue:
specify c++ standard flag for msvc



Discussion / hints:
I can see that it's only  the four builds on nightly that are failing, and I can reproduce this locally on nightly. stable is fine.

Note that the failed build is not because of trying to include the Windows flag support, but by trying to push the C++ version feature flags so that they are visible to the test suite's `build.rs` command. I guess as a workaround we could force the test suite to always use a particular C++ version and not worry about allowing a C++ version feature for the test suite?

I'm not clear if it's a bug/stricter nightly requirement or a nightly regression though. Tempted to leave this open a few days and see if nightly fixes this.

It looks like another instance of https://github.com/rust-lang/cargo/issues/6941, which leads to an open bug raised by @dtolnay here https://github.com/rust-lang/cargo/issues/6915

The cargo bugs mention that part of the issue may be that cxx-test-suite is in dev-dependencies 

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index a9db03979..5f20ad9b6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,9 +14,10 @@ keywords = ["ffi"]
 categories = ["development-tools::ffi", "api-bindings"]
 
 [features]
-default = [] # c++11
-"c++14" = []
-"c++17" = []
+default = ["cxxbridge-flags/default"] # c++11
+"c++14" = ["cxxbridge-flags/c++14"]
+"c++17" = ["cxxbridge-flags/c++17"]
+"c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
 cxxbridge-macro = { version = "=0.3.6", path = "macro" }
@@ -24,6 +25,7 @@ link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
+cxxbridge-flags = { version = "=0.3.6", path = "flags", default-features = false }
 
 [dev-dependencies]
 cxx-build = { version = "=0.3.6", path = "gen/build" }
@@ -32,7 +34,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
-members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
+members = ["demo-rs", "flags", "gen/build", "gen/cmd", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/build.rs b/build.rs
index a412dbdaf..2aad99f48 100644
--- a/build.rs
+++ b/build.rs
@@ -3,13 +3,7 @@ fn main() {
         .file("src/cxx.cc")
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
-        .flag_if_supported(if cfg!(feature = "c++17") {
-            "-std=c++17"
-        } else if cfg!(feature = "c++14") {
-            "-std=c++14"
-        } else {
-            "-std=c++11"
-        })
+        .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
new file mode 100644
index 000000000..6e5bc5d44
--- /dev/null
+++ b/flags/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "cxxbridge-flags"
+version = "0.3.6"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "Compiler configuration of the `cxx` crate (implementation detail)"
+repository = "https://github.com/dtolnay/cxx"
+
+[features]
+default = [] # c++11
+"c++14" = []
+"c++17" = []
+"c++20" = []
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/flags/src/impl.rs b/flags/src/impl.rs
new file mode 100644
index 000000000..4f7b8fb4b
--- /dev/null
+++ b/flags/src/impl.rs
@@ -0,0 +1,20 @@
+#[allow(unused_assignments, unused_mut, unused_variables)]
+pub const STD: &str = {
+    let mut flags = ["-std=c++11", "/std:c++11"];
+
+    #[cfg(feature = "c++14")]
+    (flags = ["-std=c++14", "/std:c++14"]);
+
+    #[cfg(feature = "c++17")]
+    (flags = ["-std=c++17", "/std:c++17"]);
+
+    #[cfg(feature = "c++20")]
+    (flags = ["-std=c++20", "/std:c++20"]);
+
+    let [mut flag, msvc_flag] = flags;
+
+    #[cfg(target_env = "msvc")]
+    (flag = msvc_flag);
+
+    flag
+};
diff --git a/flags/src/lib.rs b/flags/src/lib.rs
new file mode 100644
index 000000000..55172b214
--- /dev/null
+++ b/flags/src/lib.rs
@@ -0,0 +1,7 @@
+//! This crate is an implementation detail of the `cxx` and `cxx-build` crates,
+//! and does not expose any public API.
+
+mod r#impl;
+
+#[doc(hidden)]
+pub use r#impl::*;
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2a3746295..65ec21124 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -70,6 +70,7 @@ dependencies = [
  "cc",
  "cxx-build",
  "cxx-test-suite",
+ "cxxbridge-flags",
  "cxxbridge-macro",
  "link-cplusplus",
  "rustversion",
@@ -94,6 +95,7 @@ version = "0.0.0"
 dependencies = [
  "cxx",
  "cxx-build",
+ "cxxbridge-flags",
 ]
 
 [[package]]
@@ -116,6 +118,10 @@ dependencies = [
  "cxx-build",
 ]
 
+[[package]]
+name = "cxxbridge-flags"
+version = "0.3.6"
+
 [[package]]
 name = "cxxbridge-macro"
 version = "0.3.6"


Test patch:
diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml
index c2d82276c..e62d09069 100644
--- a/tests/ffi/Cargo.toml
+++ b/tests/ffi/Cargo.toml
@@ -12,3 +12,4 @@ cxx = { path = "../.." }
 
 [build-dependencies]
 cxx-build = { path = "../../gen/build" }
+cxxbridge-flags = { path = "../../flags" }
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index f6fa59ea6..8042129fa 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,6 +6,6 @@ fn main() {
     let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
-        .flag_if_supported("-std=c++11")
+        .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxx-test-suite");
 }