let mut unstable_opts = false;
let mut args = compiler::extern_args(&self, unit, &mut unstable_opts)?;
args.extend(compiler::lto_args(&self, unit));
+ args.extend(compiler::features_args(&self, unit));
- for feature in &unit.features {
- args.push("--cfg".into());
- args.push(format!("feature=\"{}\"", feature).into());
- }
let script_meta = self.find_build_script_metadata(unit);
if let Some(meta) = script_meta {
if let Some(output) = self.build_script_outputs.lock().unwrap().get(meta) {
paths::create_dir_all(&doc_dir)?;
rustdoc.arg("-o").arg(&doc_dir);
-
- for feat in &unit.features {
- rustdoc.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
- }
+ rustdoc.args(&features_args(cx, unit));
add_error_format_and_color(cx, &mut rustdoc, unit);
add_allow_features(cx, &mut rustdoc);
}
}
-/// Add all features as cfg
-fn add_features(cx: &Context<'_, '_>, cmd: &mut ProcessBuilder, unit: &Unit) {
- for feat in &unit.features {
- cmd.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
- }
-
- if cx.bcx.config.cli_unstable().check_cfg_features {
- // This generate something like this:
- // - values(feature)
- // - values(feature, "foo", "bar")
- let mut arg = String::from("values(feature");
- for (&feat, _) in unit.pkg.summary().features() {
- arg.push_str(", \"");
- arg.push_str(&feat);
- arg.push_str("\"");
- }
- arg.push(')');
-
- cmd.arg("-Zunstable-options").arg("--check-cfg").arg(&arg);
- }
-}
-
/// Add error-format flags to the command.
///
/// Cargo always uses JSON output. This has several benefits, such as being
cmd.arg("--cfg").arg("test");
}
- add_features(cx, cmd, unit);
+ cmd.args(&features_args(cx, unit));
let meta = cx.files().metadata(unit);
cmd.arg("-C").arg(&format!("metadata={}", meta));
Ok(())
}
+/// Features with --cfg and all features with --check-cfg
+fn features_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec<OsString> {
+ let mut args = Vec::with_capacity(unit.features.len() + 2);
+
+ for feat in &unit.features {
+ args.push(OsString::from("--cfg"));
+ args.push(OsString::from(format!("feature=\"{}\"", feat)));
+ }
+
+ if cx.bcx.config.cli_unstable().check_cfg_features {
+ // This generate something like this:
+ // - values(feature)
+ // - values(feature, "foo", "bar")
+ let mut arg = OsString::from("values(feature");
+ for (&feat, _) in unit.pkg.summary().features() {
+ arg.push(", \"");
+ arg.push(&feat);
+ arg.push("\"");
+ }
+ arg.push(")");
+
+ args.push(OsString::from("-Zunstable-options"));
+ args.push(OsString::from("--check-cfg"));
+ args.push(arg);
+ }
+
+ args
+}
+
fn lto_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec<OsString> {
let mut result = Vec::new();
let mut push = |arg: &str| {
* RFC: [#3013](https://github.com/rust-lang/rfcs/pull/3013)
The `-Z check-cfg-features` argument tells Cargo to pass all possible features of a package to
-`rustc` unstable `--check-cfg` command line as `--check-cfg=values(feature, ...)`. This enables
-compile time checking of feature values in `#[cfg]`, `cfg!` and `#[cfg_attr]`. Note than this
-command line options will probably become the default when stabilizing.
+`rustc` and `rustdoc` unstable `--check-cfg` command line as `--check-cfg=values(feature, ...)`.
+This enables compile time checking of feature values in `#[cfg]`, `cfg!` and `#[cfg_attr]`.
+Note than this command line options will probably become the default when stabilizing.
For instance:
```
assert!(p.build_dir().join("doc/foo").exists());
assert!(!p.build_dir().join("doc/bar").exists());
}
+
+#[cfg_attr(windows, ignore)] // weird normalization issue with windows and cargo-test-support
+#[cargo_test]
+fn doc_check_cfg_features() {
+ if !is_nightly() {
+ // --check-cfg is a nightly only rustdoc command line
+ return;
+ }
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [features]
+ default = ["f_a"]
+ f_a = []
+ f_b = []
+ "#,
+ )
+ .file("src/lib.rs", "#[allow(dead_code)] fn foo() {}")
+ .build();
+
+ p.cargo("doc -v -Z check-cfg-features")
+ .masquerade_as_nightly_cargo()
+ .with_stderr(
+ "\
+[DOCUMENTING] foo v0.1.0 [..]
+[RUNNING] `rustdoc [..] --check-cfg 'values(feature, \"default\", \"f_a\", \"f_b\")' [..]
+[FINISHED] [..]
+",
+ )
+ .run();
+}
)
.run();
}
+
+#[cfg_attr(windows, ignore)] // weird normalization issue with windows and cargo-test-support
+#[cargo_test]
+fn check_cfg_features_doc() {
+ if !is_nightly() {
+ // --check-cfg is a nightly only rustc and rustdoc command line
+ return;
+ }
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [project]
+ name = "foo"
+ version = "0.1.0"
+
+ [features]
+ default = ["f_a"]
+ f_a = []
+ f_b = []
+ "#,
+ )
+ .file("src/lib.rs", "#[allow(dead_code)] fn foo() {}")
+ .build();
+
+ p.cargo("test -v --doc -Z check-cfg-features")
+ .masquerade_as_nightly_cargo()
+ .with_stderr(
+ "\
+[COMPILING] foo v0.1.0 [..]
+[RUNNING] `rustc [..] --check-cfg 'values(feature, \"default\", \"f_a\", \"f_b\")' [..]
+[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
+[DOCTEST] foo
+[RUNNING] `rustdoc [..] --check-cfg 'values(feature, \"default\", \"f_a\", \"f_b\")' [..]
+",
+ )
+ .run();
+}