mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
refactor: separate "global" mode from CompileMode (#15601)
### What does this PR try to resolve? This separates the concern of two different "mode". - UserIntent: focus on the overall goal of the build - CompileMode: the actual compile operation for each unit (I'd like to rename it to something else in the future, such as CompileAction) This is a preparation of adding `-Zno-link`/`-Zlink-only` support, which we'll have `CompileMode::Link` but that doesn't make sense to show up in `UserIntent`. ### How should we test and review this PR? It should have no functional change. ### Additional information
This commit is contained in:
commit
bffece899e
@ -61,7 +61,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
let ws = args.workspace(gctx)?;
|
||||
|
||||
let mut compile_opts =
|
||||
args.compile_options(gctx, CompileMode::Bench, Some(&ws), ProfileChecking::Custom)?;
|
||||
args.compile_options(gctx, UserIntent::Bench, Some(&ws), ProfileChecking::Custom)?;
|
||||
|
||||
compile_opts.build_config.requested_profile =
|
||||
args.get_profile_name("bench", ProfileChecking::Custom)?;
|
||||
|
@ -49,7 +49,7 @@ pub fn cli() -> Command {
|
||||
pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
let ws = args.workspace(gctx)?;
|
||||
let mut compile_opts =
|
||||
args.compile_options(gctx, CompileMode::Build, Some(&ws), ProfileChecking::Custom)?;
|
||||
args.compile_options(gctx, UserIntent::Build, Some(&ws), ProfileChecking::Custom)?;
|
||||
|
||||
if let Some(artifact_dir) = args.value_of_path("artifact-dir", gctx) {
|
||||
// If the user specifies `--artifact-dir`, use that
|
||||
|
@ -50,9 +50,9 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
args.get_one::<String>("profile").map(String::as_str),
|
||||
Some("test")
|
||||
);
|
||||
let mode = CompileMode::Check { test };
|
||||
let intent = UserIntent::Check { test };
|
||||
let compile_opts =
|
||||
args.compile_options(gctx, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?;
|
||||
args.compile_options(gctx, intent, Some(&ws), ProfileChecking::LegacyTestOnly)?;
|
||||
|
||||
ops::compile(&ws, &compile_opts)?;
|
||||
Ok(())
|
||||
|
@ -48,11 +48,12 @@ pub fn cli() -> Command {
|
||||
|
||||
pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
let ws = args.workspace(gctx)?;
|
||||
let mode = CompileMode::Doc {
|
||||
let intent = UserIntent::Doc {
|
||||
deps: !args.flag("no-deps"),
|
||||
json: false,
|
||||
};
|
||||
let mut compile_opts = args.compile_options(gctx, mode, Some(&ws), ProfileChecking::Custom)?;
|
||||
let mut compile_opts =
|
||||
args.compile_options(gctx, intent, Some(&ws), ProfileChecking::Custom)?;
|
||||
compile_opts.rustdoc_document_private_items = args.flag("document-private-items");
|
||||
|
||||
let doc_opts = DocOptions {
|
||||
|
@ -67,7 +67,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
args.get_one::<String>("profile").map(String::as_str),
|
||||
Some("test")
|
||||
);
|
||||
let mode = CompileMode::Check { test };
|
||||
let intent = UserIntent::Check { test };
|
||||
|
||||
// Unlike other commands default `cargo fix` to all targets to fix as much
|
||||
// code as we can.
|
||||
@ -79,7 +79,8 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
let lockfile_path = args.lockfile_path(gctx)?;
|
||||
ws.set_requested_lockfile_path(lockfile_path.clone());
|
||||
|
||||
let mut opts = args.compile_options(gctx, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?;
|
||||
let mut opts =
|
||||
args.compile_options(gctx, intent, Some(&ws), ProfileChecking::LegacyTestOnly)?;
|
||||
|
||||
let edition = args.flag("edition") || args.flag("edition-idioms");
|
||||
if !opts.filter.is_specific() && edition {
|
||||
|
@ -216,7 +216,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
|
||||
let mut compile_opts = args.compile_options(
|
||||
gctx,
|
||||
CompileMode::Build,
|
||||
UserIntent::Build,
|
||||
workspace.as_ref(),
|
||||
ProfileChecking::Custom,
|
||||
)?;
|
||||
|
@ -51,7 +51,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
let ws = args.workspace(gctx)?;
|
||||
|
||||
let mut compile_opts =
|
||||
args.compile_options(gctx, CompileMode::Build, Some(&ws), ProfileChecking::Custom)?;
|
||||
args.compile_options(gctx, UserIntent::Build, Some(&ws), ProfileChecking::Custom)?;
|
||||
|
||||
// Disallow `spec` to be an glob pattern
|
||||
if let Packages::Packages(opt_in) = &compile_opts.spec {
|
||||
@ -180,7 +180,7 @@ pub fn exec_manifest_command(gctx: &mut GlobalContext, cmd: &str, args: &[OsStri
|
||||
}
|
||||
|
||||
let mut compile_opts =
|
||||
cargo::ops::CompileOptions::new(gctx, cargo::core::compiler::CompileMode::Build)?;
|
||||
cargo::ops::CompileOptions::new(gctx, cargo::core::compiler::UserIntent::Build)?;
|
||||
compile_opts.spec = cargo::ops::Packages::Default;
|
||||
|
||||
cargo::ops::run(&ws, &compile_opts, args).map_err(|err| to_run_error(gctx, err))
|
||||
|
@ -64,15 +64,15 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
// This is a legacy behavior that changes the behavior based on the profile.
|
||||
// If we want to support this more formally, I think adding a --mode flag
|
||||
// would be warranted.
|
||||
let mode = match args.get_one::<String>("profile").map(String::as_str) {
|
||||
Some("test") => CompileMode::Test,
|
||||
Some("bench") => CompileMode::Bench,
|
||||
Some("check") => CompileMode::Check { test: false },
|
||||
_ => CompileMode::Build,
|
||||
let intent = match args.get_one::<String>("profile").map(String::as_str) {
|
||||
Some("test") => UserIntent::Test,
|
||||
Some("bench") => UserIntent::Bench,
|
||||
Some("check") => UserIntent::Check { test: false },
|
||||
_ => UserIntent::Build,
|
||||
};
|
||||
let mut compile_opts = args.compile_options_for_single_package(
|
||||
gctx,
|
||||
mode,
|
||||
intent,
|
||||
Some(&ws),
|
||||
ProfileChecking::LegacyRustc,
|
||||
)?;
|
||||
|
@ -64,7 +64,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
|
||||
let mut compile_opts = args.compile_options_for_single_package(
|
||||
gctx,
|
||||
CompileMode::Doc {
|
||||
UserIntent::Doc {
|
||||
deps: false,
|
||||
json: matches!(output_format, OutputFormat::Json),
|
||||
},
|
||||
|
@ -72,7 +72,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
let ws = args.workspace(gctx)?;
|
||||
|
||||
let mut compile_opts =
|
||||
args.compile_options(gctx, CompileMode::Test, Some(&ws), ProfileChecking::Custom)?;
|
||||
args.compile_options(gctx, UserIntent::Test, Some(&ws), ProfileChecking::Custom)?;
|
||||
|
||||
compile_opts.build_config.requested_profile =
|
||||
args.get_profile_name("test", ProfileChecking::Custom)?;
|
||||
@ -95,7 +95,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||
if no_run {
|
||||
return Err(anyhow::format_err!("Can't skip running doc tests with --no-run").into());
|
||||
}
|
||||
compile_opts.build_config.mode = CompileMode::Doctest;
|
||||
compile_opts.build_config.intent = UserIntent::Doctest;
|
||||
compile_opts.filter = ops::CompileFilter::lib_only();
|
||||
} else if test_name.is_some() && !compile_opts.filter.is_specific() {
|
||||
// If arg `TESTNAME` is provided, assumed that the user knows what
|
||||
|
@ -21,8 +21,8 @@ pub struct BuildConfig {
|
||||
pub keep_going: bool,
|
||||
/// Build profile
|
||||
pub requested_profile: InternedString,
|
||||
/// The mode we are compiling in.
|
||||
pub mode: CompileMode,
|
||||
/// The intent we are compiling in.
|
||||
pub intent: UserIntent,
|
||||
/// `true` to print stdout in JSON format (for machine reading).
|
||||
pub message_format: MessageFormat,
|
||||
/// Force Cargo to do a full rebuild and treat each target as changed.
|
||||
@ -72,7 +72,7 @@ impl BuildConfig {
|
||||
jobs: Option<JobsConfig>,
|
||||
keep_going: bool,
|
||||
requested_targets: &[String],
|
||||
mode: CompileMode,
|
||||
intent: UserIntent,
|
||||
) -> CargoResult<BuildConfig> {
|
||||
let cfg = gctx.build_config()?;
|
||||
let requested_kinds = CompileKind::from_requested_targets(gctx, requested_targets)?;
|
||||
@ -117,7 +117,7 @@ impl BuildConfig {
|
||||
jobs,
|
||||
keep_going,
|
||||
requested_profile: InternedString::new("dev"),
|
||||
mode,
|
||||
intent,
|
||||
message_format: MessageFormat::Human,
|
||||
force_rebuild: false,
|
||||
build_plan: false,
|
||||
@ -138,10 +138,6 @@ impl BuildConfig {
|
||||
matches!(self.message_format, MessageFormat::Json { .. })
|
||||
}
|
||||
|
||||
pub fn test(&self) -> bool {
|
||||
self.mode == CompileMode::Test || self.mode == CompileMode::Bench
|
||||
}
|
||||
|
||||
pub fn single_requested_kind(&self) -> CargoResult<CompileKind> {
|
||||
match self.requested_kinds.len() {
|
||||
1 => Ok(self.requested_kinds[0]),
|
||||
@ -167,37 +163,28 @@ pub enum MessageFormat {
|
||||
Short,
|
||||
}
|
||||
|
||||
/// The general "mode" for what to do.
|
||||
///
|
||||
/// This is used for two purposes. The commands themselves pass this in to
|
||||
/// `compile_ws` to tell it the general execution strategy. This influences
|
||||
/// the default targets selected. The other use is in the `Unit` struct
|
||||
/// to indicate what is being done with a specific target.
|
||||
/// The specific action to be performed on each `Unit` of work.
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]
|
||||
pub enum CompileMode {
|
||||
/// A target being built for a test.
|
||||
/// Test with `rustc`.
|
||||
Test,
|
||||
/// Building a target with `rustc` (lib or bin).
|
||||
/// Compile with `rustc`.
|
||||
Build,
|
||||
/// Building a target with `rustc` to emit `rmeta` metadata only. If
|
||||
/// `test` is true, then it is also compiled with `--test` to check it like
|
||||
/// Type-check with `rustc` by emitting `rmeta` metadata only.
|
||||
///
|
||||
/// If `test` is true, then it is also compiled with `--test` to check it like
|
||||
/// a test.
|
||||
Check { test: bool },
|
||||
/// Used to indicate benchmarks should be built. This is not used in
|
||||
/// `Unit`, because it is essentially the same as `Test` (indicating
|
||||
/// `--test` should be passed to rustc) and by using `Test` instead it
|
||||
/// allows some de-duping of Units to occur.
|
||||
Bench,
|
||||
/// A target that will be documented with `rustdoc`.
|
||||
|
||||
/// Document with `rustdoc`.
|
||||
///
|
||||
/// If `deps` is true, then it will also document all dependencies.
|
||||
/// if `json` is true, the documentation output is in json format.
|
||||
Doc { deps: bool, json: bool },
|
||||
/// A target that will be tested with `rustdoc`.
|
||||
/// Test with `rustdoc`.
|
||||
Doctest,
|
||||
/// An example or library that will be scraped for function calls by `rustdoc`.
|
||||
/// Scrape for function calls by `rustdoc`.
|
||||
Docscrape,
|
||||
/// A marker for Units that represent the execution of a `build.rs` script.
|
||||
/// Execute the binary built from the `build.rs` script.
|
||||
RunCustomBuild,
|
||||
}
|
||||
|
||||
@ -211,7 +198,6 @@ impl ser::Serialize for CompileMode {
|
||||
Test => "test".serialize(s),
|
||||
Build => "build".serialize(s),
|
||||
Check { .. } => "check".serialize(s),
|
||||
Bench => "bench".serialize(s),
|
||||
Doc { .. } => "doc".serialize(s),
|
||||
Doctest => "doctest".serialize(s),
|
||||
Docscrape => "docscrape".serialize(s),
|
||||
@ -246,19 +232,13 @@ impl CompileMode {
|
||||
pub fn is_any_test(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
CompileMode::Test
|
||||
| CompileMode::Bench
|
||||
| CompileMode::Check { test: true }
|
||||
| CompileMode::Doctest
|
||||
CompileMode::Test | CompileMode::Check { test: true } | CompileMode::Doctest
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is something that passes `--test` to rustc.
|
||||
pub fn is_rustc_test(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
CompileMode::Test | CompileMode::Bench | CompileMode::Check { test: true }
|
||||
)
|
||||
matches!(self, CompileMode::Test | CompileMode::Check { test: true })
|
||||
}
|
||||
|
||||
/// Returns `true` if this is the *execution* of a `build.rs` script.
|
||||
@ -271,9 +251,64 @@ impl CompileMode {
|
||||
/// Note that this also returns `true` for building libraries, so you also
|
||||
/// have to check the target.
|
||||
pub fn generates_executable(self) -> bool {
|
||||
matches!(self, CompileMode::Test | CompileMode::Build)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the high-level operation requested by the user.
|
||||
///
|
||||
/// It determines which "Cargo targets" are selected by default and influences
|
||||
/// how they will be processed. This is derived from the Cargo command the user
|
||||
/// invoked (like `cargo build` or `cargo test`).
|
||||
///
|
||||
/// Unlike [`CompileMode`], which describes the specific compilation steps for
|
||||
/// individual units, [`UserIntent`] represents the overall goal of the build
|
||||
/// process as specified by the user.
|
||||
///
|
||||
/// For example, when a user runs `cargo test`, the intent is [`UserIntent::Test`],
|
||||
/// but this might result in multiple [`CompileMode`]s for different units.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum UserIntent {
|
||||
/// Build benchmark binaries, e.g., `cargo bench`
|
||||
Bench,
|
||||
/// Build binaries and libraray, e.g., `cargo run`, `cargo install`, `cargo build`.
|
||||
Build,
|
||||
/// Perform type-check, e.g., `cargo check`.
|
||||
Check { test: bool },
|
||||
/// Document packages.
|
||||
///
|
||||
/// If `deps` is true, then it will also document all dependencies.
|
||||
/// if `json` is true, the documentation output is in json format.
|
||||
Doc { deps: bool, json: bool },
|
||||
/// Build doctest binaries, e.g., `cargo test --doc`
|
||||
Doctest,
|
||||
/// Build test binaries, e.g., `cargo test`
|
||||
Test,
|
||||
}
|
||||
|
||||
impl UserIntent {
|
||||
/// Returns `true` if this is generating documentation.
|
||||
pub fn is_doc(self) -> bool {
|
||||
matches!(self, UserIntent::Doc { .. })
|
||||
}
|
||||
|
||||
/// Returns `true` if this is any type of test (test, benchmark, doc test, or
|
||||
/// check test).
|
||||
pub fn is_any_test(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
CompileMode::Test | CompileMode::Bench | CompileMode::Build
|
||||
UserIntent::Test
|
||||
| UserIntent::Bench
|
||||
| UserIntent::Check { test: true }
|
||||
| UserIntent::Doctest
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is something that passes `--test` to rustc.
|
||||
pub fn is_rustc_test(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
UserIntent::Test | UserIntent::Bench | UserIntent::Check { test: true }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -574,7 +574,7 @@ impl TargetInfo {
|
||||
) -> CargoResult<(Vec<FileType>, Vec<CrateType>)> {
|
||||
match mode {
|
||||
CompileMode::Build => self.calc_rustc_outputs(target_kind, target_triple, gctx),
|
||||
CompileMode::Test | CompileMode::Bench => {
|
||||
CompileMode::Test => {
|
||||
match self.file_types(&CrateType::Bin, FileFlavor::Normal, target_triple)? {
|
||||
Some(fts) => Ok((fts, Vec::new())),
|
||||
None => Ok((Vec::new(), vec![CrateType::Bin])),
|
||||
|
@ -493,10 +493,7 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> {
|
||||
flavor: FileFlavor::Normal,
|
||||
}]
|
||||
}
|
||||
CompileMode::Test
|
||||
| CompileMode::Build
|
||||
| CompileMode::Bench
|
||||
| CompileMode::Check { .. } => {
|
||||
CompileMode::Test | CompileMode::Build | CompileMode::Check { .. } => {
|
||||
let mut outputs = self.calc_outputs_rustc(unit, bcx)?;
|
||||
if bcx.build_config.sbom && bcx.gctx.cli_unstable().sbom {
|
||||
let sbom_files: Vec<_> = outputs
|
||||
|
@ -183,7 +183,7 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
|
||||
// any versioning (See https://github.com/rust-lang/cargo/issues/8461).
|
||||
// Therefore, we can end up with weird bugs and behaviours if we mix different
|
||||
// versions of these files.
|
||||
if self.bcx.build_config.mode.is_doc() {
|
||||
if self.bcx.build_config.intent.is_doc() {
|
||||
RustDocFingerprint::check_rustdoc_fingerprint(&self)?
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
//! [build script]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html
|
||||
//! [`TargetKind::CustomBuild`]: crate::core::manifest::TargetKind::CustomBuild
|
||||
//! [`UnitGraph`]: super::unit_graph::UnitGraph
|
||||
//! [`CompileMode::RunCustomBuild`]: super::CompileMode
|
||||
//! [`CompileMode::RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild
|
||||
//! [instructions]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script
|
||||
|
||||
use super::{fingerprint, get_dynamic_search_path, BuildRunner, Job, Unit, Work};
|
||||
@ -36,8 +36,8 @@ use crate::core::compiler::artifact;
|
||||
use crate::core::compiler::build_runner::UnitHash;
|
||||
use crate::core::compiler::fingerprint::DirtyReason;
|
||||
use crate::core::compiler::job_queue::JobState;
|
||||
use crate::core::compiler::CompileMode;
|
||||
use crate::core::{profiles::ProfileRoot, PackageId, Target};
|
||||
use crate::util::command_prelude::CompileMode;
|
||||
use crate::util::errors::CargoResult;
|
||||
use crate::util::internal;
|
||||
use crate::util::machine_message::{self, Message};
|
||||
|
@ -97,7 +97,7 @@ fn calculate(
|
||||
let crate_types = match unit.mode {
|
||||
// Note: Doctest ignores LTO, but for now we'll compute it as-if it is
|
||||
// a Bin, in case it is ever supported in the future.
|
||||
CompileMode::Test | CompileMode::Bench | CompileMode::Doctest => vec![CrateType::Bin],
|
||||
CompileMode::Test | CompileMode::Doctest => vec![CrateType::Bin],
|
||||
// Notes on other modes:
|
||||
// - Check: Treat as the underlying type, it doesn't really matter.
|
||||
// - Doc: LTO is N/A for the Doc unit itself since rustdoc does not
|
||||
|
@ -69,6 +69,7 @@ use anyhow::{Context as _, Error};
|
||||
use lazycell::LazyCell;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
pub use self::build_config::UserIntent;
|
||||
pub use self::build_config::{BuildConfig, CompileMode, MessageFormat, TimingOutput};
|
||||
pub use self::build_context::{
|
||||
BuildContext, FileFlavor, FileType, RustDocFingerprint, RustcTargetData, TargetInfo,
|
||||
|
@ -168,7 +168,6 @@ impl<'gctx> Timings<'gctx> {
|
||||
CompileMode::Build => {}
|
||||
CompileMode::Check { test: true } => target.push_str(" (check-test)"),
|
||||
CompileMode::Check { test: false } => target.push_str(" (check)"),
|
||||
CompileMode::Bench => target.push_str(" (bench)"),
|
||||
CompileMode::Doc { .. } => target.push_str(" (doc)"),
|
||||
CompileMode::Doctest => target.push_str(" (doc test)"),
|
||||
CompileMode::Docscrape => target.push_str(" (doc scrape)"),
|
||||
|
@ -21,6 +21,7 @@ use tracing::trace;
|
||||
|
||||
use crate::core::compiler::artifact::match_artifacts_kind_with_targets;
|
||||
use crate::core::compiler::unit_graph::{UnitDep, UnitGraph};
|
||||
use crate::core::compiler::UserIntent;
|
||||
use crate::core::compiler::{
|
||||
CompileKind, CompileMode, CrateType, RustcTargetData, Unit, UnitInterner,
|
||||
};
|
||||
@ -51,8 +52,9 @@ struct State<'a, 'gctx> {
|
||||
std_features: Option<&'a ResolvedFeatures>,
|
||||
/// `true` while generating the dependencies for the standard library.
|
||||
is_std: bool,
|
||||
/// The mode we are compiling in. Used for preventing from building lib thrice.
|
||||
global_mode: CompileMode,
|
||||
/// The high-level operation requested by the user.
|
||||
/// Used for preventing from building lib thrice.
|
||||
intent: UserIntent,
|
||||
target_data: &'a RustcTargetData<'gctx>,
|
||||
profiles: &'a Profiles,
|
||||
interner: &'a UnitInterner,
|
||||
@ -91,7 +93,7 @@ pub fn build_unit_dependencies<'a, 'gctx>(
|
||||
roots: &[Unit],
|
||||
scrape_units: &[Unit],
|
||||
std_roots: &HashMap<CompileKind, Vec<Unit>>,
|
||||
global_mode: CompileMode,
|
||||
intent: UserIntent,
|
||||
target_data: &'a RustcTargetData<'gctx>,
|
||||
profiles: &'a Profiles,
|
||||
interner: &'a UnitInterner,
|
||||
@ -116,7 +118,7 @@ pub fn build_unit_dependencies<'a, 'gctx>(
|
||||
std_resolve,
|
||||
std_features,
|
||||
is_std: false,
|
||||
global_mode,
|
||||
intent,
|
||||
target_data,
|
||||
profiles,
|
||||
interner,
|
||||
@ -203,13 +205,13 @@ fn attach_std_deps(
|
||||
fn deps_of_roots(roots: &[Unit], state: &mut State<'_, '_>) -> CargoResult<()> {
|
||||
for unit in roots.iter() {
|
||||
// Dependencies of tests/benches should not have `panic` set.
|
||||
// We check the global test mode to see if we are running in `cargo
|
||||
// test` in which case we ensure all dependencies have `panic`
|
||||
// cleared, and avoid building the lib thrice (once with `panic`, once
|
||||
// without, once for `--test`). In particular, the lib included for
|
||||
// Doc tests and examples are `Build` mode here.
|
||||
// We check the user intent to see if we are running in `cargo test` in
|
||||
// which case we ensure all dependencies have `panic` cleared, and
|
||||
// avoid building the lib thrice (once with `panic`, once without, once
|
||||
// for `--test`). In particular, the lib included for Doc tests and
|
||||
// examples are `Build` mode here.
|
||||
let root_compile_kind = unit.kind;
|
||||
let unit_for = if unit.mode.is_any_test() || state.global_mode.is_rustc_test() {
|
||||
let unit_for = if unit.mode.is_any_test() || state.intent.is_rustc_test() {
|
||||
if unit.target.proc_macro() {
|
||||
// Special-case for proc-macros, which are forced to for-host
|
||||
// since they need to link with the proc_macro crate.
|
||||
|
@ -1,7 +1,6 @@
|
||||
//! Filters and their rules to select which Cargo targets will be built.
|
||||
|
||||
use crate::core::compiler::CompileMode;
|
||||
|
||||
use crate::core::compiler::UserIntent;
|
||||
use crate::core::{Target, TargetKind};
|
||||
use crate::util::restricted_names::is_glob_pattern;
|
||||
|
||||
@ -216,23 +215,21 @@ impl CompileFilter {
|
||||
}
|
||||
|
||||
/// Indicates if Cargo needs to build any dev dependency.
|
||||
pub fn need_dev_deps(&self, mode: CompileMode) -> bool {
|
||||
match mode {
|
||||
CompileMode::Test | CompileMode::Doctest | CompileMode::Bench => true,
|
||||
CompileMode::Check { test: true } => true,
|
||||
CompileMode::Build
|
||||
| CompileMode::Doc { .. }
|
||||
| CompileMode::Docscrape
|
||||
| CompileMode::Check { test: false } => match *self {
|
||||
CompileFilter::Default { .. } => false,
|
||||
CompileFilter::Only {
|
||||
ref examples,
|
||||
ref tests,
|
||||
ref benches,
|
||||
..
|
||||
} => examples.is_specific() || tests.is_specific() || benches.is_specific(),
|
||||
},
|
||||
CompileMode::RunCustomBuild => panic!("Invalid mode"),
|
||||
pub fn need_dev_deps(&self, intent: UserIntent) -> bool {
|
||||
match intent {
|
||||
UserIntent::Test | UserIntent::Doctest | UserIntent::Bench => true,
|
||||
UserIntent::Check { test: true } => true,
|
||||
UserIntent::Build | UserIntent::Doc { .. } | UserIntent::Check { test: false } => {
|
||||
match *self {
|
||||
CompileFilter::Default { .. } => false,
|
||||
CompileFilter::Only {
|
||||
ref examples,
|
||||
ref tests,
|
||||
ref benches,
|
||||
..
|
||||
} => examples.is_specific() || tests.is_specific() || benches.is_specific(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,10 @@ use std::sync::Arc;
|
||||
|
||||
use crate::core::compiler::unit_dependencies::build_unit_dependencies;
|
||||
use crate::core::compiler::unit_graph::{self, UnitDep, UnitGraph};
|
||||
use crate::core::compiler::UserIntent;
|
||||
use crate::core::compiler::{apply_env_config, standard_lib, CrateType, TargetInfo};
|
||||
use crate::core::compiler::{BuildConfig, BuildContext, BuildRunner, Compilation};
|
||||
use crate::core::compiler::{CompileKind, CompileMode, CompileTarget, RustcTargetData, Unit};
|
||||
use crate::core::compiler::{CompileKind, CompileTarget, RustcTargetData, Unit};
|
||||
use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner};
|
||||
use crate::core::profiles::Profiles;
|
||||
use crate::core::resolver::features::{self, CliFeatures, FeaturesFor};
|
||||
@ -101,11 +102,11 @@ pub struct CompileOptions {
|
||||
}
|
||||
|
||||
impl CompileOptions {
|
||||
pub fn new(gctx: &GlobalContext, mode: CompileMode) -> CargoResult<CompileOptions> {
|
||||
pub fn new(gctx: &GlobalContext, intent: UserIntent) -> CargoResult<CompileOptions> {
|
||||
let jobs = None;
|
||||
let keep_going = false;
|
||||
Ok(CompileOptions {
|
||||
build_config: BuildConfig::new(gctx, jobs, keep_going, &[], mode)?,
|
||||
build_config: BuildConfig::new(gctx, jobs, keep_going, &[], intent)?,
|
||||
cli_features: CliFeatures::new_all(false),
|
||||
spec: ops::Packages::Packages(Vec::new()),
|
||||
filter: CompileFilter::Default {
|
||||
@ -226,19 +227,15 @@ pub fn create_bcx<'a, 'gctx>(
|
||||
let gctx = ws.gctx();
|
||||
|
||||
// Perform some pre-flight validation.
|
||||
match build_config.mode {
|
||||
CompileMode::Test
|
||||
| CompileMode::Build
|
||||
| CompileMode::Check { .. }
|
||||
| CompileMode::Bench
|
||||
| CompileMode::RunCustomBuild => {
|
||||
match build_config.intent {
|
||||
UserIntent::Test | UserIntent::Build | UserIntent::Check { .. } | UserIntent::Bench => {
|
||||
if ws.gctx().get_env("RUST_FLAGS").is_ok() {
|
||||
gctx.shell().warn(
|
||||
"Cargo does not read `RUST_FLAGS` environment variable. Did you mean `RUSTFLAGS`?",
|
||||
)?;
|
||||
}
|
||||
}
|
||||
CompileMode::Doc { .. } | CompileMode::Doctest | CompileMode::Docscrape => {
|
||||
UserIntent::Doc { .. } | UserIntent::Doctest => {
|
||||
if ws.gctx().get_env("RUSTDOC_FLAGS").is_ok() {
|
||||
gctx.shell().warn(
|
||||
"Cargo does not read `RUSTDOC_FLAGS` environment variable. Did you mean `RUSTDOCFLAGS`?"
|
||||
@ -264,8 +261,8 @@ pub fn create_bcx<'a, 'gctx>(
|
||||
.any(|target| target.is_example() && target.doc_scrape_examples().is_enabled())
|
||||
});
|
||||
|
||||
if filter.need_dev_deps(build_config.mode)
|
||||
|| (build_config.mode.is_doc() && any_pkg_has_scrape_enabled)
|
||||
if filter.need_dev_deps(build_config.intent)
|
||||
|| (build_config.intent.is_doc() && any_pkg_has_scrape_enabled)
|
||||
{
|
||||
HasDevUnits::Yes
|
||||
} else {
|
||||
@ -321,7 +318,7 @@ pub fn create_bcx<'a, 'gctx>(
|
||||
for pkg in to_builds.iter() {
|
||||
pkg.manifest().print_teapot(gctx);
|
||||
|
||||
if build_config.mode.is_any_test()
|
||||
if build_config.intent.is_any_test()
|
||||
&& !ws.is_member(pkg)
|
||||
&& pkg.dependencies().iter().any(|dep| !dep.is_transitive())
|
||||
{
|
||||
@ -379,7 +376,7 @@ pub fn create_bcx<'a, 'gctx>(
|
||||
filter,
|
||||
requested_kinds: &build_config.requested_kinds,
|
||||
explicit_host_kind,
|
||||
mode: build_config.mode,
|
||||
intent: build_config.intent,
|
||||
resolve: &resolve,
|
||||
workspace_resolve: &workspace_resolve,
|
||||
resolved_features: &resolved_features,
|
||||
@ -394,13 +391,9 @@ pub fn create_bcx<'a, 'gctx>(
|
||||
override_rustc_crate_types(&mut units, args, interner)?;
|
||||
}
|
||||
|
||||
let should_scrape = build_config.mode.is_doc() && gctx.cli_unstable().rustdoc_scrape_examples;
|
||||
let should_scrape = build_config.intent.is_doc() && gctx.cli_unstable().rustdoc_scrape_examples;
|
||||
let mut scrape_units = if should_scrape {
|
||||
UnitGenerator {
|
||||
mode: CompileMode::Docscrape,
|
||||
..generator
|
||||
}
|
||||
.generate_scrape_units(&units)?
|
||||
generator.generate_scrape_units(&units)?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
@ -431,7 +424,7 @@ pub fn create_bcx<'a, 'gctx>(
|
||||
&units,
|
||||
&scrape_units,
|
||||
&std_roots,
|
||||
build_config.mode,
|
||||
build_config.intent,
|
||||
&target_data,
|
||||
&profiles,
|
||||
interner,
|
||||
@ -439,7 +432,7 @@ pub fn create_bcx<'a, 'gctx>(
|
||||
|
||||
// TODO: In theory, Cargo should also dedupe the roots, but I'm uncertain
|
||||
// what heuristics to use in that case.
|
||||
if matches!(build_config.mode, CompileMode::Doc { deps: true, .. }) {
|
||||
if matches!(build_config.intent, UserIntent::Doc { deps: true, .. }) {
|
||||
remove_duplicate_doc(build_config, &units, &mut unit_graph);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ use std::fmt::Write;
|
||||
|
||||
use crate::core::compiler::rustdoc::RustdocScrapeExamples;
|
||||
use crate::core::compiler::unit_dependencies::IsArtifact;
|
||||
use crate::core::compiler::UserIntent;
|
||||
use crate::core::compiler::{CompileKind, CompileMode, Unit};
|
||||
use crate::core::compiler::{RustcTargetData, UnitInterner};
|
||||
use crate::core::dependency::DepKind;
|
||||
@ -53,7 +54,7 @@ pub(super) struct UnitGenerator<'a, 'gctx> {
|
||||
pub filter: &'a CompileFilter,
|
||||
pub requested_kinds: &'a [CompileKind],
|
||||
pub explicit_host_kind: CompileKind,
|
||||
pub mode: CompileMode,
|
||||
pub intent: UserIntent,
|
||||
pub resolve: &'a Resolve,
|
||||
pub workspace_resolve: &'a Option<Resolve>,
|
||||
pub resolved_features: &'a features::ResolvedFeatures,
|
||||
@ -85,18 +86,9 @@ impl<'a> UnitGenerator<'a, '_> {
|
||||
}
|
||||
CompileMode::Build => match *target.kind() {
|
||||
TargetKind::Test => CompileMode::Test,
|
||||
TargetKind::Bench => CompileMode::Bench,
|
||||
TargetKind::Bench => CompileMode::Test,
|
||||
_ => CompileMode::Build,
|
||||
},
|
||||
// `CompileMode::Bench` is only used to inform `filter_default_targets`
|
||||
// which command is being used (`cargo bench`). Afterwards, tests
|
||||
// and benches are treated identically. Switching the mode allows
|
||||
// de-duplication of units that are essentially identical. For
|
||||
// example, `cargo build --all-targets --release` creates the units
|
||||
// (lib profile:bench, mode:test) and (lib profile:bench, mode:bench)
|
||||
// and since these are the same, we want them to be de-duplicated in
|
||||
// `unit_dependencies`.
|
||||
CompileMode::Bench => CompileMode::Test,
|
||||
_ => initial_target_mode,
|
||||
};
|
||||
|
||||
@ -188,17 +180,17 @@ impl<'a> UnitGenerator<'a, '_> {
|
||||
/// Given a list of all targets for a package, filters out only the targets
|
||||
/// that are automatically included when the user doesn't specify any targets.
|
||||
fn filter_default_targets<'b>(&self, targets: &'b [Target]) -> Vec<&'b Target> {
|
||||
match self.mode {
|
||||
CompileMode::Bench => targets.iter().filter(|t| t.benched()).collect(),
|
||||
CompileMode::Test => targets
|
||||
match self.intent {
|
||||
UserIntent::Bench => targets.iter().filter(|t| t.benched()).collect(),
|
||||
UserIntent::Test => targets
|
||||
.iter()
|
||||
.filter(|t| t.tested() || t.is_example())
|
||||
.collect(),
|
||||
CompileMode::Build | CompileMode::Check { .. } => targets
|
||||
UserIntent::Build | UserIntent::Check { .. } => targets
|
||||
.iter()
|
||||
.filter(|t| t.is_bin() || t.is_lib())
|
||||
.collect(),
|
||||
CompileMode::Doc { .. } => {
|
||||
UserIntent::Doc { .. } => {
|
||||
// `doc` does lib and bins (bin with same name as lib is skipped).
|
||||
targets
|
||||
.iter()
|
||||
@ -211,8 +203,8 @@ impl<'a> UnitGenerator<'a, '_> {
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
CompileMode::Doctest | CompileMode::RunCustomBuild | CompileMode::Docscrape => {
|
||||
panic!("Invalid mode {:?}", self.mode)
|
||||
UserIntent::Doctest => {
|
||||
panic!("Invalid intent {:?}", self.intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -395,9 +387,9 @@ impl<'a> UnitGenerator<'a, '_> {
|
||||
pkg,
|
||||
target,
|
||||
requires_features: !required_features_filterable,
|
||||
mode: self.mode,
|
||||
mode: to_compile_mode(self.intent),
|
||||
}));
|
||||
if self.mode == CompileMode::Test {
|
||||
if matches!(self.intent, UserIntent::Test) {
|
||||
if let Some(t) = pkg
|
||||
.targets()
|
||||
.iter()
|
||||
@ -423,9 +415,10 @@ impl<'a> UnitGenerator<'a, '_> {
|
||||
} => {
|
||||
if *lib != LibRule::False {
|
||||
let mut libs = Vec::new();
|
||||
for proposal in self.filter_targets(Target::is_lib, false, self.mode) {
|
||||
let compile_mode = to_compile_mode(self.intent);
|
||||
for proposal in self.filter_targets(Target::is_lib, false, compile_mode) {
|
||||
let Proposal { target, pkg, .. } = proposal;
|
||||
if self.mode.is_doc_test() && !target.doctestable() {
|
||||
if matches!(self.intent, UserIntent::Doctest) && !target.doctestable() {
|
||||
let types = target.rustc_crate_types();
|
||||
let types_str: Vec<&str> = types.iter().map(|t| t.as_str()).collect();
|
||||
self.ws.gctx().shell().warn(format!(
|
||||
@ -455,16 +448,18 @@ impl<'a> UnitGenerator<'a, '_> {
|
||||
proposals.extend(libs);
|
||||
}
|
||||
|
||||
let default_mode = to_compile_mode(self.intent);
|
||||
|
||||
// If `--tests` was specified, add all targets that would be
|
||||
// generated by `cargo test`.
|
||||
let test_filter = match tests {
|
||||
FilterRule::All => Target::tested,
|
||||
FilterRule::Just(_) => Target::is_test,
|
||||
};
|
||||
let test_mode = match self.mode {
|
||||
CompileMode::Build => CompileMode::Test,
|
||||
CompileMode::Check { .. } => CompileMode::Check { test: true },
|
||||
_ => self.mode,
|
||||
let test_mode = match self.intent {
|
||||
UserIntent::Build => CompileMode::Test,
|
||||
UserIntent::Check { .. } => CompileMode::Check { test: true },
|
||||
_ => default_mode,
|
||||
};
|
||||
// If `--benches` was specified, add all targets that would be
|
||||
// generated by `cargo bench`.
|
||||
@ -472,25 +467,25 @@ impl<'a> UnitGenerator<'a, '_> {
|
||||
FilterRule::All => Target::benched,
|
||||
FilterRule::Just(_) => Target::is_bench,
|
||||
};
|
||||
let bench_mode = match self.mode {
|
||||
CompileMode::Build => CompileMode::Bench,
|
||||
CompileMode::Check { .. } => CompileMode::Check { test: true },
|
||||
_ => self.mode,
|
||||
};
|
||||
|
||||
proposals.extend(self.list_rule_targets(bins, "bin", Target::is_bin, self.mode)?);
|
||||
proposals.extend(self.list_rule_targets(
|
||||
bins,
|
||||
"bin",
|
||||
Target::is_bin,
|
||||
default_mode,
|
||||
)?);
|
||||
proposals.extend(self.list_rule_targets(
|
||||
examples,
|
||||
"example",
|
||||
Target::is_example,
|
||||
self.mode,
|
||||
default_mode,
|
||||
)?);
|
||||
proposals.extend(self.list_rule_targets(tests, "test", test_filter, test_mode)?);
|
||||
proposals.extend(self.list_rule_targets(
|
||||
benches,
|
||||
"bench",
|
||||
bench_filter,
|
||||
bench_mode,
|
||||
test_mode,
|
||||
)?);
|
||||
}
|
||||
}
|
||||
@ -779,3 +774,14 @@ Rustdoc did not scrape the following examples because they require dev-dependenc
|
||||
Ok(scrape_units)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts [`UserIntent`] to [`CompileMode`] for root units.
|
||||
fn to_compile_mode(intent: UserIntent) -> CompileMode {
|
||||
match intent {
|
||||
UserIntent::Test | UserIntent::Bench => CompileMode::Test,
|
||||
UserIntent::Build => CompileMode::Build,
|
||||
UserIntent::Check { test } => CompileMode::Check { test },
|
||||
UserIntent::Doc { deps, json } => CompileMode::Doc { deps, json },
|
||||
UserIntent::Doctest => CompileMode::Doctest,
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
use crate::core::compiler::standard_lib;
|
||||
use crate::core::compiler::{BuildConfig, CompileMode, RustcTargetData};
|
||||
use crate::core::compiler::BuildConfig;
|
||||
use crate::core::compiler::RustcTargetData;
|
||||
use crate::core::compiler::UserIntent;
|
||||
use crate::core::{PackageSet, Resolve, Workspace};
|
||||
use crate::ops;
|
||||
use crate::util::context::JobsConfig;
|
||||
@ -26,7 +28,7 @@ pub fn fetch<'a>(
|
||||
let keep_going = false;
|
||||
let gctx = ws.gctx();
|
||||
let build_config =
|
||||
BuildConfig::new(gctx, jobs, keep_going, &options.targets, CompileMode::Build)?;
|
||||
BuildConfig::new(gctx, jobs, keep_going, &options.targets, UserIntent::Build)?;
|
||||
let mut data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
|
||||
let mut fetched_packages = HashSet::new();
|
||||
let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();
|
||||
|
@ -15,9 +15,9 @@ use flate2::read::GzDecoder;
|
||||
use tar::Archive;
|
||||
|
||||
use crate::core::compiler::BuildConfig;
|
||||
use crate::core::compiler::CompileMode;
|
||||
use crate::core::compiler::DefaultExecutor;
|
||||
use crate::core::compiler::Executor;
|
||||
use crate::core::compiler::UserIntent;
|
||||
use crate::core::Feature;
|
||||
use crate::core::Package;
|
||||
use crate::core::SourceId;
|
||||
@ -103,7 +103,7 @@ pub fn run_verify(
|
||||
opts.jobs.clone(),
|
||||
opts.keep_going,
|
||||
&opts.targets,
|
||||
CompileMode::Build,
|
||||
UserIntent::Build,
|
||||
)?,
|
||||
cli_features: opts.cli_features.clone(),
|
||||
spec: ops::Packages::Packages(Vec::new()),
|
||||
|
@ -29,7 +29,7 @@ use std::ffi::{OsStr, OsString};
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub use crate::core::compiler::CompileMode;
|
||||
pub use crate::core::compiler::UserIntent;
|
||||
pub use crate::{CliError, CliResult, GlobalContext};
|
||||
pub use clap::{value_parser, Arg, ArgAction, ArgMatches};
|
||||
|
||||
@ -723,7 +723,7 @@ Run `{cmd}` to see possible targets."
|
||||
fn compile_options(
|
||||
&self,
|
||||
gctx: &GlobalContext,
|
||||
mode: CompileMode,
|
||||
mode: UserIntent,
|
||||
workspace: Option<&Workspace<'_>>,
|
||||
profile_checking: ProfileChecking,
|
||||
) -> CargoResult<CompileOptions> {
|
||||
@ -887,7 +887,7 @@ Run `{cmd}` to see possible targets."
|
||||
fn compile_options_for_single_package(
|
||||
&self,
|
||||
gctx: &GlobalContext,
|
||||
mode: CompileMode,
|
||||
mode: UserIntent,
|
||||
workspace: Option<&Workspace<'_>>,
|
||||
profile_checking: ProfileChecking,
|
||||
) -> CargoResult<CompileOptions> {
|
||||
|
@ -5,12 +5,11 @@ use std::fs;
|
||||
use std::io::Read;
|
||||
use std::process::Stdio;
|
||||
|
||||
use cargo::{
|
||||
core::compiler::CompileMode,
|
||||
core::{Shell, Workspace},
|
||||
ops::CompileOptions,
|
||||
GlobalContext,
|
||||
};
|
||||
use cargo::core::compiler::UserIntent;
|
||||
use cargo::core::Shell;
|
||||
use cargo::core::Workspace;
|
||||
use cargo::ops::CompileOptions;
|
||||
use cargo::GlobalContext;
|
||||
use cargo_test_support::compare::assert_e2e;
|
||||
use cargo_test_support::paths::root;
|
||||
use cargo_test_support::prelude::*;
|
||||
@ -665,7 +664,7 @@ fn cargo_compile_api_exposes_artifact_paths() {
|
||||
let shell = Shell::from_write(Box::new(Vec::new()));
|
||||
let gctx = GlobalContext::new(shell, env::current_dir().unwrap(), paths::home());
|
||||
let ws = Workspace::new(&p.root().join("Cargo.toml"), &gctx).unwrap();
|
||||
let compile_options = CompileOptions::new(ws.gctx(), CompileMode::Build).unwrap();
|
||||
let compile_options = CompileOptions::new(ws.gctx(), UserIntent::Build).unwrap();
|
||||
|
||||
let result = cargo::ops::compile(&ws, &compile_options).unwrap();
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
//! Tests for workspace member errors.
|
||||
|
||||
use cargo::core::compiler::UserIntent;
|
||||
use cargo::core::resolver::ResolveError;
|
||||
use cargo::core::{compiler::CompileMode, Shell, Workspace};
|
||||
use cargo::core::Shell;
|
||||
use cargo::core::Workspace;
|
||||
use cargo::ops::{self, CompileOptions};
|
||||
use cargo::util::{context::GlobalContext, errors::ManifestError};
|
||||
use cargo_test_support::paths;
|
||||
@ -155,7 +157,7 @@ fn member_manifest_version_error() {
|
||||
paths::cargo_home(),
|
||||
);
|
||||
let ws = Workspace::new(&p.root().join("Cargo.toml"), &gctx).unwrap();
|
||||
let compile_options = CompileOptions::new(&gctx, CompileMode::Build).unwrap();
|
||||
let compile_options = CompileOptions::new(&gctx, UserIntent::Build).unwrap();
|
||||
let member_bar = ws.members().find(|m| &*m.name() == "bar").unwrap();
|
||||
|
||||
let error = ops::compile(&ws, &compile_options).map(|_| ()).unwrap_err();
|
||||
|
Loading…
x
Reference in New Issue
Block a user