Skip to content

Commit

Permalink
Auto merge of #9002 - volks73:feature-rustc-cfg-argument, r=alexcrichton
Browse files Browse the repository at this point in the history
Add --cfg and --rustc-cfg flags to output compiler configuration

This PR is my attempt to address #8923.

I have added the `--cfg` flag to the `cargo rustc` subcommand and the `--rustc-cfg` flag to the `cargo build`, `cargo check`, `cargo test`, and `cargo bench` subcommands, respectively. Both versions of the flag, `--cfg` and `--rustc-cfg`, do the same thing, but I thought it looked weird for the `cargo rustc` subcommand to be `cargo rustc --rustc-cfg`. The following example invocations are possible, once stabilized:

- `cargo rustc --cfg`
- `cargo build --rustc-cfg`
- `cargo check --rustc-cfg`
- `cargo test --rustc-cfg`
- `cargo bench --rustc-cfg`

In each case, compilation is aborted and only compiler configuration is emitted. All of the context creation and configuration is still executed, but execution of the compilation job is aborted. Similar to the `--unit-graph` implementation, the `--cfg/--rustc-cfg` flag is hidden, marked as a "unstable", and requires the `-Z unstable-options` flag at the moment. A complete example invocation with this PR would be:

```bash
$ cargo +nightly rustc -Z unstable-options --cfg
```

I am open to alternatives for the flag name. I have thought of `--compiler-cfg`, `--compile-cfg`, and `--target-cfg`, but I went with `--rustc-cfg` because it is the Rust compiler (rustc) configuration (cfg). The `--target-cfg` could be confusing because there are Cargo targets and Compiler targets. A lone `--cfg` for the build, check, test, and bench subcommands would also be ambiguous and configuration that is being displayed.

Originally, I was only going to add the `--cfg` flag to the `cargo rustc` subcommand, but build, check, test, and bench all have the `--unit-graph` flag, and I used that flag's implementation and existence as a template for this implementation. I am not opposed to having just the `--cfg` flag for the `cargo rustc` subcommand as originally proposed in #8923.

I discovered during my initial investigation to implement the feature and familiarization with the Cargo codebase, that as part of the build context creation and compilation process, Cargo internally calls the `rustc --print cfg` command for all targets and stores the output in the `RustcTargetData` type. It does this for the host and any explicitly defined targets for cross-compilation. Compilation features, such as `+crt-static`, added to the compilation process through Cargo environment variables or TOML configuration directives are added to the internal `rustc --print cfg` command call. So, the `--cfg/--rustc-cfg` just emits the contents of the `RustcTagetData` type as JSON. There is no need to call the `rustc --print cfg` command again. The implementation then becomes nearly identical to the `--unit-graph` implementation.

The output is only in JSON, similar to the `--unit-graph` feature, instead of the key-value and name style of the `rustc --print cfg` output because it easily resolves issues related to multi-targets, explicit target (`--target <TRIPLE>`) versus host configurations, and cross compilation. Subcommands and other projects can parse the JSON to recreate the key-value and name style if desired based on a specific target or the host. Here is an example of the JSON output (formatted for humans, the actual output is condensed), which is also available as a comment in the `cargo::core::compiler::rustc_cfg` module:

```javascript
{
     "version": 1,
     "host": {
         "names": ["windows", "debug_assertions"],
         "arch":"x86_64",
         "endian":"little",
         "env":"msvc",
         "family":"windows",
         "features":["fxsr","sse","sse2"],
         "os":"windows",
         "pointer_width":"64",
         "vendor":"pc"
     },
     "targets": {
         "x86_64-unknown-linux-gnu": {
             "names": ["debug_assertions", "unix"],
             "arch":"x86_64",
             "endian":"little",
             "env":"gnu",
             "family":"unix",
             "features": ["fxsr","sse","sse2"],
             "os":"linux",
             "pointer_width":"64",
             "vendor":"unknown"
         },
         "i686-pc-windows-msvc": {
             "names": ["windows", "debug_assertions"],
             "arch":"x86",
             "endian":"little",
             "env":"msvc",
             "family":"windows",
             "features":["fxsr","sse","sse2"],
             "os":"windows",
             "pointer_width":"32",
             "vendor":"pc"
         }
     }
 }
```

I decided to remove the "target_" prefix from the relevant configurations to reduce "noise" in the output. Again, I am open to alternatives or suggestions on the JSON format.
  • Loading branch information
bors committed Feb 23, 2021
2 parents 6243e8e + 2a5355f commit 4ae4aad
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 5 deletions.
18 changes: 17 additions & 1 deletion src/bin/cargo/commands/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use crate::command_prelude::*;

use cargo::ops;

const PRINT_ARG_NAME: &str = "print";

pub fn cli() -> App {
subcommand("rustc")
.setting(AppSettings::TrailingVarArg)
Expand All @@ -26,6 +28,13 @@ pub fn cli() -> App {
.arg_profile("Build artifacts with the specified profile")
.arg_features()
.arg_target_triple("Target triple which compiles will be for")
.arg(
opt(
PRINT_ARG_NAME,
"Output compiler information without compiling",
)
.value_name("INFO"),
)
.arg_target_dir()
.arg_manifest_path()
.arg_message_format()
Expand Down Expand Up @@ -62,6 +71,13 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
} else {
Some(target_args)
};
ops::compile(&ws, &compile_opts)?;
if let Some(opt_value) = args.value_of(PRINT_ARG_NAME) {
config
.cli_unstable()
.fail_if_stable_opt(PRINT_ARG_NAME, 8923)?;
ops::print(&ws, &compile_opts, opt_value)?;
} else {
ops::compile(&ws, &compile_opts)?;
}
Ok(())
}
35 changes: 33 additions & 2 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ use std::collections::{BTreeSet, HashMap, HashSet};
use std::hash::{Hash, Hasher};
use std::sync::Arc;

use crate::core::compiler::standard_lib;
use crate::core::compiler::unit_dependencies::build_unit_dependencies;
use crate::core::compiler::unit_graph::{self, UnitDep, UnitGraph};
use crate::core::compiler::{standard_lib, TargetInfo};
use crate::core::compiler::{BuildConfig, BuildContext, Compilation, Context};
use crate::core::compiler::{CompileKind, CompileMode, CompileTarget, RustcTargetData, Unit};
use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner};
Expand All @@ -37,6 +37,7 @@ use crate::core::resolver::features::{self, FeaturesFor, RequestedFeatures};
use crate::core::resolver::{HasDevUnits, Resolve, ResolveOpts};
use crate::core::{FeatureValue, Package, PackageSet, Shell, Summary, Target};
use crate::core::{PackageId, PackageIdSpec, SourceId, TargetKind, Workspace};
use crate::drop_println;
use crate::ops;
use crate::ops::resolve::WorkspaceResolve;
use crate::util::config::Config;
Expand Down Expand Up @@ -289,12 +290,42 @@ pub fn compile_ws<'a>(
unit_graph::emit_serialized_unit_graph(&bcx.roots, &bcx.unit_graph)?;
return Compilation::new(&bcx);
}

let _p = profile::start("compiling");
let cx = Context::new(&bcx)?;
cx.compile(exec)
}

pub fn print<'a>(
ws: &Workspace<'a>,
options: &CompileOptions,
print_opt_value: &str,
) -> CargoResult<()> {
let CompileOptions {
ref build_config,
ref target_rustc_args,
..
} = *options;
let config = ws.config();
let rustc = config.load_global_rustc(Some(ws))?;
for (index, kind) in build_config.requested_kinds.iter().enumerate() {
if index != 0 {
drop_println!(config);
}
let target_info = TargetInfo::new(config, &build_config.requested_kinds, &rustc, *kind)?;
let mut process = rustc.process();
process.args(&target_info.rustflags);
if let Some(args) = target_rustc_args {
process.args(args);
}
if let CompileKind::Target(t) = kind {
process.arg("--target").arg(t.short_name());
}
process.arg("--print").arg(print_opt_value);
process.exec()?;
}
Ok(())
}

pub fn create_bcx<'a, 'cfg>(
ws: &'a Workspace<'cfg>,
options: &'a CompileOptions,
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub use self::cargo_clean::{clean, CleanOptions};
pub use self::cargo_compile::{
compile, compile_with_exec, compile_ws, create_bcx, resolve_all_features, CompileOptions,
compile, compile_with_exec, compile_ws, create_bcx, print, resolve_all_features, CompileOptions,
};
pub use self::cargo_compile::{CompileFilter, FilterRule, LibRule, Packages};
pub use self::cargo_doc::{doc, DocOptions};
Expand Down
1 change: 0 additions & 1 deletion src/cargo/util/command_prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,6 @@ pub trait ArgMatchesExt {
.cli_unstable()
.fail_if_stable_opt("--unit-graph", 8002)?;
}

let opts = CompileOptions {
build_config,
features: self._values_of("features"),
Expand Down
101 changes: 101 additions & 0 deletions tests/testsuite/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,104 @@ fn rustc_test_with_implicit_bin() {
)
.run();
}

#[cargo_test]
fn rustc_with_print_cfg_single_target() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/main.rs", r#"fn main() {} "#)
.build();

p.cargo("rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg")
.masquerade_as_nightly_cargo()
.with_stdout_contains("debug_assertions")
.with_stdout_contains("target_arch=\"x86_64\"")
.with_stdout_contains("target_endian=\"little\"")
.with_stdout_contains("target_env=\"msvc\"")
.with_stdout_contains("target_family=\"windows\"")
.with_stdout_contains("target_os=\"windows\"")
.with_stdout_contains("target_pointer_width=\"64\"")
.with_stdout_contains("target_vendor=\"pc\"")
.with_stdout_contains("windows")
.run();
}

#[cargo_test]
fn rustc_with_print_cfg_multiple_targets() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/main.rs", r#"fn main() {} "#)
.build();

p.cargo("rustc -Z unstable-options -Z multitarget --target x86_64-pc-windows-msvc --target i686-unknown-linux-gnu --print cfg")
.masquerade_as_nightly_cargo()
.with_stdout_contains("debug_assertions")
.with_stdout_contains("target_arch=\"x86_64\"")
.with_stdout_contains("target_endian=\"little\"")
.with_stdout_contains("target_env=\"msvc\"")
.with_stdout_contains("target_family=\"windows\"")
.with_stdout_contains("target_os=\"windows\"")
.with_stdout_contains("target_pointer_width=\"64\"")
.with_stdout_contains("target_vendor=\"pc\"")
.with_stdout_contains("windows")
.with_stdout_contains("target_env=\"gnu\"")
.with_stdout_contains("target_family=\"unix\"")
.with_stdout_contains("target_pointer_width=\"32\"")
.with_stdout_contains("target_vendor=\"unknown\"")
.with_stdout_contains("target_os=\"linux\"")
.with_stdout_contains("unix")
.run();
}

#[cargo_test]
fn rustc_with_print_cfg_rustflags_env_var() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file("src/main.rs", r#"fn main() {} "#)
.build();

p.cargo("rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg")
.masquerade_as_nightly_cargo()
.env("RUSTFLAGS", "-C target-feature=+crt-static")
.with_stdout_contains("debug_assertions")
.with_stdout_contains("target_arch=\"x86_64\"")
.with_stdout_contains("target_endian=\"little\"")
.with_stdout_contains("target_env=\"msvc\"")
.with_stdout_contains("target_family=\"windows\"")
.with_stdout_contains("target_feature=\"crt-static\"")
.with_stdout_contains("target_os=\"windows\"")
.with_stdout_contains("target_pointer_width=\"64\"")
.with_stdout_contains("target_vendor=\"pc\"")
.with_stdout_contains("windows")
.run();
}

#[cargo_test]
fn rustc_with_print_cfg_config_toml() {
let p = project()
.file("Cargo.toml", &basic_bin_manifest("foo"))
.file(
".cargo/config.toml",
r#"
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
"#,
)
.file("src/main.rs", r#"fn main() {} "#)
.build();

p.cargo("rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg")
.masquerade_as_nightly_cargo()
.env("RUSTFLAGS", "-C target-feature=+crt-static")
.with_stdout_contains("debug_assertions")
.with_stdout_contains("target_arch=\"x86_64\"")
.with_stdout_contains("target_endian=\"little\"")
.with_stdout_contains("target_env=\"msvc\"")
.with_stdout_contains("target_family=\"windows\"")
.with_stdout_contains("target_feature=\"crt-static\"")
.with_stdout_contains("target_os=\"windows\"")
.with_stdout_contains("target_pointer_width=\"64\"")
.with_stdout_contains("target_vendor=\"pc\"")
.with_stdout_contains("windows")
.run();
}

0 comments on commit 4ae4aad

Please sign in to comment.