diff --git a/src/bin/cargo/commands/rustc.rs b/src/bin/cargo/commands/rustc.rs index 187ff4651f4..b8a8952610e 100644 --- a/src/bin/cargo/commands/rustc.rs +++ b/src/bin/cargo/commands/rustc.rs @@ -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) @@ -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() @@ -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(()) } diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 981afe23580..3d4cf8c96a1 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -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}; @@ -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; @@ -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, diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index 4853993e4a5..5b5894f991b 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -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}; diff --git a/src/cargo/util/command_prelude.rs b/src/cargo/util/command_prelude.rs index 4f56ab242f4..e60d7890225 100644 --- a/src/cargo/util/command_prelude.rs +++ b/src/cargo/util/command_prelude.rs @@ -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"), diff --git a/tests/testsuite/rustc.rs b/tests/testsuite/rustc.rs index 48f6859f02d..53b5c6fb19a 100644 --- a/tests/testsuite/rustc.rs +++ b/tests/testsuite/rustc.rs @@ -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(); +}