diff --git a/src/bin/cargo/commands/check.rs b/src/bin/cargo/commands/check.rs index 8c14395bf73..c7d1800662a 100644 --- a/src/bin/cargo/commands/check.rs +++ b/src/bin/cargo/commands/check.rs @@ -36,6 +36,7 @@ pub fn cli() -> App { .arg_message_format() .arg_unit_graph() .arg_future_incompat_report() + .arg_only_build_scripts_and_proc_macros() .after_help("Run `cargo help check` for more detailed information.\n") } diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 593aaf2076d..9d5b45c1c71 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -26,6 +26,11 @@ pub struct BuildConfig { pub build_plan: bool, /// Output the unit graph to stdout instead of actually compiling. pub unit_graph: bool, + /// Only for `cargo check`. + /// Skips actual check and only compile proc macros and run build script. + /// This is needed for IDEs. + /// See https://github.com/rust-lang/cargo/issues/7178 for details. + pub only_build_scripts_and_proc_macros: bool, /// An optional override of the rustc process for primary units pub primary_unit_rustc: Option, /// A thread used by `cargo fix` to receive messages on a socket regarding @@ -79,6 +84,7 @@ impl BuildConfig { force_rebuild: false, build_plan: false, unit_graph: false, + only_build_scripts_and_proc_macros: false, primary_unit_rustc: None, rustfix_diagnostic_server: RefCell::new(None), export_dir: None, diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index ef08bc942db..441ebeb68bf 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -147,6 +147,7 @@ fn compile<'cfg>( ) -> CargoResult<()> { let bcx = cx.bcx; let build_plan = bcx.build_config.build_plan; + let only_build_scripts_and_proc_macros = bcx.build_config.only_build_scripts_and_proc_macros; if !cx.compiled.insert(unit.clone()) { return Ok(()); } @@ -163,6 +164,8 @@ fn compile<'cfg>( Job::new_fresh() } else if build_plan { Job::new_dirty(rustc(cx, unit, &exec.clone())?) + } else if only_build_scripts_and_proc_macros && matches!(unit.mode, CompileMode::Check { .. }) { + Job::new_fresh() } else { let force = exec.force_rebuild(unit) || force_rebuild; let mut job = fingerprint::prepare_target(cx, unit, force)?; diff --git a/src/cargo/util/command_prelude.rs b/src/cargo/util/command_prelude.rs index d27fbfb972c..2561d910e31 100644 --- a/src/cargo/util/command_prelude.rs +++ b/src/cargo/util/command_prelude.rs @@ -172,6 +172,11 @@ pub trait AppExt: Sized { self._arg(opt("unit-graph", "Output build graph in JSON (unstable)")) } + fn arg_only_build_scripts_and_proc_macros(self) -> Self { + let help = "Skip actual check and only run build scripts and compile proc macros"; + self._arg(opt("only-build-scripts-and-proc-macros", help).hidden(true)) + } + fn arg_new_opts(self) -> Self { self._arg( opt( @@ -470,6 +475,8 @@ pub trait ArgMatchesExt { build_config.build_plan = self._is_present("build-plan"); build_config.unit_graph = self._is_present("unit-graph"); build_config.future_incompat_report = self._is_present("future-incompat-report"); + build_config.only_build_scripts_and_proc_macros = + self._is_present("only-build-scripts-and-proc-macros"); if build_config.build_plan { config .cli_unstable() @@ -492,6 +499,11 @@ pub trait ArgMatchesExt { ) } } + if build_config.only_build_scripts_and_proc_macros { + config + .cli_unstable() + .fail_if_stable_opt("--only-build-scripts-and-proc-macros", 7178)?; + } let opts = CompileOptions { build_config, diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs index 1d4c967b99d..5d7e4405d6a 100644 --- a/tests/testsuite/main.rs +++ b/tests/testsuite/main.rs @@ -81,6 +81,7 @@ mod net_config; mod new; mod offline; mod old_cargos; +mod only_build_scripts_and_proc_macros; mod out_dir; mod owner; mod package; diff --git a/tests/testsuite/only_build_scripts_and_proc_macros.rs b/tests/testsuite/only_build_scripts_and_proc_macros.rs new file mode 100644 index 00000000000..2384b55ec9b --- /dev/null +++ b/tests/testsuite/only_build_scripts_and_proc_macros.rs @@ -0,0 +1,33 @@ +//! Tests for --only-build-scripts-and-proc-macros feature. + +use cargo_test_support::{basic_bin_manifest, project}; + +#[cargo_test] +fn simple_build_script() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", "fn main() {}") + .file( + "build.rs", + r#"fn main() { println!("cargo:rustc-cfg=my_feature"); }"#, + ) + .build(); + + p.cargo("check -Zunstable-options --only-build-scripts-and-proc-macros --message-format json") + .masquerade_as_nightly_cargo() + .with_stdout_contains("[..]my_feature[..]") + .run(); +} + +#[cargo_test] +fn main_code_not_checked() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", "some invalid code") + .build(); + + p.cargo("check -Zunstable-options --only-build-scripts-and-proc-macros") + .masquerade_as_nightly_cargo() + .run(); + assert!(!p.bin("foo").is_file()); +}