diff --git a/crates/cargo-test-support/src/lib.rs b/crates/cargo-test-support/src/lib.rs index c0df4ea10c5..0d61d5931d9 100644 --- a/crates/cargo-test-support/src/lib.rs +++ b/crates/cargo-test-support/src/lib.rs @@ -806,9 +806,14 @@ impl Execs { p.build_command() } - pub fn masquerade_as_nightly_cargo(&mut self) -> &mut Self { + /// Enables nightly features for testing + /// + /// The list of reasons should be why nightly cargo is needed. If it is + /// becuase of an unstable feature put the name of the feature as the reason, + /// e.g. `&["print-im-a-teapot"]` + pub fn masquerade_as_nightly_cargo(&mut self, reasons: &[&str]) -> &mut Self { if let Some(ref mut p) = self.process_builder { - p.masquerade_as_nightly_cargo(); + p.masquerade_as_nightly_cargo(reasons); } self } @@ -1139,17 +1144,20 @@ fn _process(t: &OsStr) -> ProcessBuilder { /// Enable nightly features for testing pub trait ChannelChanger { - fn masquerade_as_nightly_cargo(self) -> Self; + /// The list of reasons should be why nightly cargo is needed. If it is + /// becuase of an unstable feature put the name of the feature as the reason, + /// e.g. `&["print-im-a-teapot"]`. + fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self; } impl ChannelChanger for &mut ProcessBuilder { - fn masquerade_as_nightly_cargo(self) -> Self { + fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self { self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly") } } impl ChannelChanger for snapbox::cmd::Command { - fn masquerade_as_nightly_cargo(self) -> Self { + fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self { self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly") } } diff --git a/crates/resolver-tests/src/lib.rs b/crates/resolver-tests/src/lib.rs index eae6469545d..fd190fe6b3b 100644 --- a/crates/resolver-tests/src/lib.rs +++ b/crates/resolver-tests/src/lib.rs @@ -12,7 +12,7 @@ use std::time::Instant; use cargo::core::dependency::DepKind; use cargo::core::resolver::{self, ResolveOpts, VersionPreferences}; -use cargo::core::source::{GitReference, SourceId}; +use cargo::core::source::{GitReference, QueryKind, SourceId}; use cargo::core::Resolve; use cargo::core::{Dependency, PackageId, Registry, Summary}; use cargo::util::{CargoResult, Config, Graph, IntoUrl}; @@ -128,11 +128,15 @@ pub fn resolve_with_config_raw( fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), - fuzzy: bool, ) -> Poll> { for summary in self.list.iter() { - if fuzzy || dep.matches(summary) { + let matched = match kind { + QueryKind::Exact => dep.matches(summary), + QueryKind::Fuzzy => true, + }; + if matched { self.used.insert(summary.package_id()); f(summary.clone()); } diff --git a/src/bin/cargo/commands/add.rs b/src/bin/cargo/commands/add.rs index 32c7699e775..1ff2aad1944 100644 --- a/src/bin/cargo/commands/add.rs +++ b/src/bin/cargo/commands/add.rs @@ -7,6 +7,7 @@ use cargo::ops::cargo_add::add; use cargo::ops::cargo_add::AddOptions; use cargo::ops::cargo_add::DepOp; use cargo::ops::cargo_add::DepTable; +use cargo::ops::resolve_ws; use cargo::util::command_prelude::*; use cargo::util::interning::InternedString; use cargo::CargoResult; @@ -193,6 +194,12 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { }; add(&ws, &options)?; + if !dry_run { + // Reload the workspace since we've changed dependencies + let ws = args.workspace(config)?; + resolve_ws(&ws)?; + } + Ok(()) } diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index e409d85fc86..8416cdfa57c 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -55,7 +55,10 @@ pub fn cli() -> App { .arg(flag("no-track", "Do not save tracking information")) .arg_features() .arg_profile("Install artifacts with the specified profile") - .arg(flag("debug", "Build in debug mode instead of release mode")) + .arg(flag( + "debug", + "Build in debug mode (with the 'dev' profile) instead of release mode", + )) .arg_targets_bins_examples( "Install only the specified binary", "Install all binaries", diff --git a/src/bin/cargo/commands/rustc.rs b/src/bin/cargo/commands/rustc.rs index 84970185e5c..098fe6b1cee 100644 --- a/src/bin/cargo/commands/rustc.rs +++ b/src/bin/cargo/commands/rustc.rs @@ -39,7 +39,7 @@ pub fn cli() -> App { .arg(multi_opt( CRATE_TYPE_ARG_NAME, "CRATE-TYPE", - "Comma separated list of types of crates for the compiler to emit (unstable)", + "Comma separated list of types of crates for the compiler to emit", )) .arg_target_dir() .arg_manifest_path() @@ -88,9 +88,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { compile_opts.target_rustc_crate_types = if crate_types.is_empty() { None } else { - config - .cli_unstable() - .fail_if_stable_opt(CRATE_TYPE_ARG_NAME, 10083)?; Some(crate_types) }; ops::compile(&ws, &compile_opts)?; diff --git a/src/cargo/core/compiler/compile_kind.rs b/src/cargo/core/compiler/compile_kind.rs index 9f6271ce0a9..7ab19ae1ccf 100644 --- a/src/cargo/core/compiler/compile_kind.rs +++ b/src/cargo/core/compiler/compile_kind.rs @@ -2,7 +2,7 @@ use crate::core::Target; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; use crate::util::{Config, StableHasher}; -use anyhow::{bail, Context as _}; +use anyhow::Context as _; use serde::Serialize; use std::collections::BTreeSet; use std::fs; @@ -65,9 +65,6 @@ impl CompileKind { }; if !targets.is_empty() { - if targets.len() > 1 && !config.cli_unstable().multitarget { - bail!("specifying multiple `--target` flags requires `-Zmultitarget`") - } return dedup(targets); } diff --git a/src/cargo/core/compiler/future_incompat.rs b/src/cargo/core/compiler/future_incompat.rs index c814842dff7..61b2c47fd87 100644 --- a/src/cargo/core/compiler/future_incompat.rs +++ b/src/cargo/core/compiler/future_incompat.rs @@ -1,7 +1,7 @@ //! Support for future-incompatible warning reporting. use crate::core::compiler::BuildContext; -use crate::core::{Dependency, PackageId, Workspace}; +use crate::core::{Dependency, PackageId, QueryKind, Workspace}; use crate::sources::SourceConfigMap; use crate::util::{iter_join, CargoResult, Config}; use anyhow::{bail, format_err, Context}; @@ -293,7 +293,7 @@ fn get_updates(ws: &Workspace<'_>, package_ids: &BTreeSet) -> Option< Ok(dep) => dep, Err(_) => return false, }; - match source.query_vec(&dep) { + match source.query_vec(&dep, QueryKind::Exact) { Poll::Ready(Ok(sum)) => { summaries.push((pkg_id, sum)); false diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 2a9b32e8ca3..0400e89a1e4 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -86,7 +86,9 @@ //! `CliUnstable. Remove the `(unstable)` note in the clap help text if //! necessary. //! 2. Remove `masquerade_as_nightly_cargo` from any tests, and remove -//! `cargo-features` from `Cargo.toml` test files if any. +//! `cargo-features` from `Cargo.toml` test files if any. You can +//! quickly find what needs to be removed by searching for the name +//! of the feature, e.g. `print_im_a_teapot` //! 3. Update the docs in unstable.md to move the section to the bottom //! and summarize it similar to the other entries. Update the rest of the //! documentation to add the new feature. @@ -414,7 +416,7 @@ features! { (unstable, profile_rustflags, "", "reference/unstable.html#profile-rustflags-option"), // Allow specifying rustflags directly in a profile - (unstable, workspace_inheritance, "", "reference/unstable.html#workspace-inheritance"), + (stable, workspace_inheritance, "1.64", "reference/unstable.html#workspace-inheritance"), } pub struct Feature { @@ -720,6 +722,8 @@ const STABILISED_NAMESPACED_FEATURES: &str = "Namespaced features are now always const STABILIZED_TIMINGS: &str = "The -Ztimings option has been stabilized as --timings."; +const STABILISED_MULTITARGET: &str = "Multiple `--target` options are now always available."; + fn deserialize_build_std<'de, D>(deserializer: D) -> Result>, D::Error> where D: serde::Deserializer<'de>, @@ -920,7 +924,7 @@ impl CliUnstable { self.features = Some(feats); } "separate-nightlies" => self.separate_nightlies = parse_empty(k, v)?, - "multitarget" => self.multitarget = parse_empty(k, v)?, + "multitarget" => stabilized_warn(k, "1.64", STABILISED_MULTITARGET), "rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?, "terminal-width" => self.terminal_width = Some(parse_usize_opt(v)?), "sparse-registry" => self.sparse_registry = parse_empty(k, v)?, diff --git a/src/cargo/core/mod.rs b/src/cargo/core/mod.rs index df91808ccaf..e36c678c4cb 100644 --- a/src/cargo/core/mod.rs +++ b/src/cargo/core/mod.rs @@ -8,7 +8,7 @@ pub use self::package_id_spec::PackageIdSpec; pub use self::registry::Registry; pub use self::resolver::{Resolve, ResolveVersion}; pub use self::shell::{Shell, Verbosity}; -pub use self::source::{GitReference, Source, SourceId, SourceMap}; +pub use self::source::{GitReference, QueryKind, Source, SourceId, SourceMap}; pub use self::summary::{FeatureMap, FeatureValue, Summary}; pub use self::workspace::{ find_workspace_root, resolve_relative_path, MaybePackage, Workspace, WorkspaceConfig, diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index 9e9d1408432..0d788a05c43 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::task::Poll; use crate::core::PackageSet; -use crate::core::{Dependency, PackageId, Source, SourceId, SourceMap, Summary}; +use crate::core::{Dependency, PackageId, QueryKind, Source, SourceId, SourceMap, Summary}; use crate::sources::config::SourceConfigMap; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; @@ -19,14 +19,13 @@ pub trait Registry { fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), - fuzzy: bool, ) -> Poll>; - fn query_vec(&mut self, dep: &Dependency, fuzzy: bool) -> Poll>> { + fn query_vec(&mut self, dep: &Dependency, kind: QueryKind) -> Poll>> { let mut ret = Vec::new(); - self.query(dep, &mut |s| ret.push(s), fuzzy) - .map_ok(|()| ret) + self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|()| ret) } fn describe_source(&self, source: SourceId) -> String; @@ -327,7 +326,7 @@ impl<'cfg> PackageRegistry<'cfg> { .get_mut(dep.source_id()) .expect("loaded source not present"); - let summaries = match source.query_vec(dep)? { + let summaries = match source.query_vec(dep, QueryKind::Exact)? { Poll::Ready(deps) => deps, Poll::Pending => { deps_pending.push(dep_remaining); @@ -483,7 +482,7 @@ impl<'cfg> PackageRegistry<'cfg> { for &s in self.overrides.iter() { let src = self.sources.get_mut(s).unwrap(); let dep = Dependency::new_override(dep.package_name(), s); - let mut results = match src.query_vec(&dep) { + let mut results = match src.query_vec(&dep, QueryKind::Exact) { Poll::Ready(results) => results?, Poll::Pending => return Poll::Pending, }; @@ -575,8 +574,8 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), - fuzzy: bool, ) -> Poll> { assert!(self.patches_locked); let (override_summary, n, to_warn) = { @@ -671,11 +670,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { } f(lock(locked, all_patches, summary)) }; - return if fuzzy { - source.fuzzy_query(dep, callback) - } else { - source.query(dep, callback) - }; + return source.query(dep, kind, callback); } // If we have an override summary then we query the source @@ -694,11 +689,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { n += 1; to_warn = Some(summary); }; - let pend = if fuzzy { - source.fuzzy_query(dep, callback)? - } else { - source.query(dep, callback)? - }; + let pend = source.query(dep, kind, callback); if pend.is_pending() { return Poll::Pending; } @@ -889,7 +880,7 @@ fn summary_for_patch( // No summaries found, try to help the user figure out what is wrong. if let Some(locked) = locked { // Since the locked patch did not match anything, try the unlocked one. - let orig_matches = match source.query_vec(orig_patch) { + let orig_matches = match source.query_vec(orig_patch, QueryKind::Exact) { Poll::Pending => return Poll::Pending, Poll::Ready(deps) => deps, } @@ -914,7 +905,7 @@ fn summary_for_patch( // Try checking if there are *any* packages that match this by name. let name_only_dep = Dependency::new_override(orig_patch.package_name(), orig_patch.source_id()); - let name_summaries = match source.query_vec(&name_only_dep) { + let name_summaries = match source.query_vec(&name_only_dep, QueryKind::Exact) { Poll::Pending => return Poll::Pending, Poll::Ready(deps) => deps, } diff --git a/src/cargo/core/resolver/dep_cache.rs b/src/cargo/core/resolver/dep_cache.rs index 067f8f74f3e..79e44f6eba2 100644 --- a/src/cargo/core/resolver/dep_cache.rs +++ b/src/cargo/core/resolver/dep_cache.rs @@ -16,7 +16,9 @@ use crate::core::resolver::{ ActivateError, ActivateResult, CliFeatures, RequestedFeatures, ResolveOpts, VersionOrdering, VersionPreferences, }; -use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec, Registry, Summary}; +use crate::core::{ + Dependency, FeatureValue, PackageId, PackageIdSpec, QueryKind, Registry, Summary, +}; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; @@ -100,13 +102,9 @@ impl<'a> RegistryQueryer<'a> { } let mut ret = Vec::new(); - let ready = self.registry.query( - dep, - &mut |s| { - ret.push(s); - }, - false, - )?; + let ready = self.registry.query(dep, QueryKind::Exact, &mut |s| { + ret.push(s); + })?; if ready.is_pending() { self.registry_cache.insert(dep.clone(), Poll::Pending); return Poll::Pending; @@ -127,7 +125,7 @@ impl<'a> RegistryQueryer<'a> { dep.version_req() ); - let mut summaries = match self.registry.query_vec(dep, false)? { + let mut summaries = match self.registry.query_vec(dep, QueryKind::Exact)? { Poll::Ready(s) => s.into_iter(), Poll::Pending => { self.registry_cache.insert(dep.clone(), Poll::Pending); diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index 306da17ef6c..d75240df625 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -1,7 +1,7 @@ use std::fmt; use std::task::Poll; -use crate::core::{Dependency, PackageId, Registry, Summary}; +use crate::core::{Dependency, PackageId, QueryKind, Registry, Summary}; use crate::util::lev_distance::lev_distance; use crate::util::{Config, VersionExt}; use anyhow::Error; @@ -228,7 +228,7 @@ pub(super) fn activation_error( new_dep.set_version_req(all_req); let mut candidates = loop { - match registry.query_vec(&new_dep, false) { + match registry.query_vec(&new_dep, QueryKind::Exact) { Poll::Ready(Ok(candidates)) => break candidates, Poll::Ready(Err(e)) => return to_resolve_err(e), Poll::Pending => match registry.block_until_ready() { @@ -294,7 +294,7 @@ pub(super) fn activation_error( // Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing` // was meant. So we try asking the registry for a `fuzzy` search for suggestions. let mut candidates = loop { - match registry.query_vec(&new_dep, true) { + match registry.query_vec(&new_dep, QueryKind::Fuzzy) { Poll::Ready(Ok(candidates)) => break candidates, Poll::Ready(Err(e)) => return to_resolve_err(e), Poll::Pending => match registry.block_until_ready() { diff --git a/src/cargo/core/resolver/types.rs b/src/cargo/core/resolver/types.rs index 4617e3ea8e5..6ea5b796a31 100644 --- a/src/cargo/core/resolver/types.rs +++ b/src/cargo/core/resolver/types.rs @@ -119,11 +119,12 @@ impl ResolveBehavior { } } - pub fn to_manifest(&self) -> Option { + pub fn to_manifest(&self) -> String { match self { - ResolveBehavior::V1 => None, - ResolveBehavior::V2 => Some("2".to_string()), + ResolveBehavior::V1 => "1", + ResolveBehavior::V2 => "2", } + .to_owned() } } diff --git a/src/cargo/core/source/mod.rs b/src/cargo/core/source/mod.rs index 56dfcb902ae..229e6cdea0c 100644 --- a/src/cargo/core/source/mod.rs +++ b/src/cargo/core/source/mod.rs @@ -29,21 +29,16 @@ pub trait Source { fn requires_precise(&self) -> bool; /// Attempts to find the packages that match a dependency request. - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll>; - - /// Attempts to find the packages that are close to a dependency request. - /// Each source gets to define what `close` means for it. - /// Path/Git sources may return all dependencies that are at that URI, - /// whereas an `Index` source may return dependencies that have the same canonicalization. - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll>; - fn query_vec(&mut self, dep: &Dependency) -> Poll>> { + fn query_vec(&mut self, dep: &Dependency, kind: QueryKind) -> Poll>> { let mut ret = Vec::new(); - self.query(dep, &mut |s| ret.push(s)).map_ok(|_| ret) + self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|_| ret) } /// Ensure that the source is fully up-to-date for the current session on the next query. @@ -115,6 +110,15 @@ pub trait Source { fn block_until_ready(&mut self) -> CargoResult<()>; } +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum QueryKind { + Exact, + /// Each source gets to define what `close` means for it. + /// Path/Git sources may return all dependencies that are at that URI, + /// whereas an `Index` source may return dependencies that have the same canonicalization. + Fuzzy, +} + pub enum MaybePackage { Ready(Package), Download { url: String, descriptor: String }, @@ -142,17 +146,13 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box { } /// Forwards to `Source::query`. - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - (**self).query(dep, f) - } - - /// Forwards to `Source::query`. - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { - (**self).fuzzy_query(dep, f) + (**self).query(dep, kind, f) } fn invalidate_cache(&mut self) { @@ -216,16 +216,13 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T { (**self).requires_precise() } - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - (**self).query(dep, f) - } - - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { - (**self).fuzzy_query(dep, f) + (**self).query(dep, kind, f) } fn invalidate_cache(&mut self) { diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index b5d1da8a253..2adf13a5b1a 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -686,6 +686,8 @@ impl<'cfg> Workspace<'cfg> { })?; } + self.find_path_deps(&root_manifest_path, &root_manifest_path, false)?; + if let Some(default) = default_members_paths { for path in default { let normalized_path = paths::normalize_path(&path); @@ -716,7 +718,7 @@ impl<'cfg> Workspace<'cfg> { self.default_members.push(self.current_manifest.clone()) } - self.find_path_deps(&root_manifest_path, &root_manifest_path, false) + Ok(()) } fn find_path_deps( @@ -1702,10 +1704,17 @@ fn find_workspace_root_with_loader( mut loader: impl FnMut(&Path) -> CargoResult>, ) -> CargoResult> { // Check if there are any workspace roots that have already been found that would work - for (ws_root, ws_root_config) in config.ws_roots.borrow().iter() { - if manifest_path.starts_with(ws_root) && !ws_root_config.is_excluded(manifest_path) { - // Add `Cargo.toml` since ws_root is the root and not the file - return Ok(Some(ws_root.join("Cargo.toml").clone())); + { + let roots = config.ws_roots.borrow(); + // Iterate through the manifests parent directories until we find a workspace + // root. Note we skip the first item since that is just the path itself + for current in manifest_path.ancestors().skip(1) { + if let Some(ws_config) = roots.get(current) { + if !ws_config.is_excluded(manifest_path) { + // Add `Cargo.toml` since ws_root is the root and not the file + return Ok(Some(current.join("Cargo.toml"))); + } + } } } diff --git a/src/cargo/ops/cargo_add/manifest.rs b/src/cargo/ops/cargo_add/manifest.rs index b90b7808392..1c96b477062 100644 --- a/src/cargo/ops/cargo_add/manifest.rs +++ b/src/cargo/ops/cargo_add/manifest.rs @@ -238,8 +238,7 @@ impl str::FromStr for Manifest { impl std::fmt::Display for Manifest { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = self.data.to_string(); - s.fmt(f) + self.data.fmt(f) } } @@ -433,6 +432,12 @@ impl LocalManifest { } } +impl std::fmt::Display for LocalManifest { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.manifest.fmt(f) + } +} + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] enum DependencyStatus { None, diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index dff93e91b02..c584a03f858 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -19,6 +19,7 @@ use toml_edit::Item as TomlItem; use crate::core::dependency::DepKind; use crate::core::registry::PackageRegistry; use crate::core::Package; +use crate::core::QueryKind; use crate::core::Registry; use crate::core::Shell; use crate::core::Workspace; @@ -61,6 +62,7 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<( let manifest_path = options.spec.manifest_path().to_path_buf(); let mut manifest = LocalManifest::try_new(&manifest_path)?; + let original_raw_manifest = manifest.to_string(); let legacy = manifest.get_legacy_sections(); if !legacy.is_empty() { anyhow::bail!( @@ -141,6 +143,16 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<( } } + if options.config.locked() { + let new_raw_manifest = manifest.to_string(); + if original_raw_manifest != new_raw_manifest { + anyhow::bail!( + "the manifest file {} needs to be updated but --locked was passed to prevent this", + manifest.path.display() + ); + } + } + if options.dry_run { options.config.shell().warn("aborting add due to dry run")?; } else { @@ -443,8 +455,7 @@ fn get_latest_dependency( } MaybeWorkspace::Other(query) => { let possibilities = loop { - let fuzzy = true; - match registry.query_vec(&query, fuzzy) { + match registry.query_vec(&query, QueryKind::Fuzzy) { std::task::Poll::Ready(res) => { break res?; } @@ -485,8 +496,8 @@ fn select_package( } MaybeWorkspace::Other(query) => { let possibilities = loop { - let fuzzy = false; // Returns all for path/git - match registry.query_vec(&query, fuzzy) { + // Exact to avoid returning all for path/git + match registry.query_vec(&query, QueryKind::Exact) { std::task::Poll::Ready(res) => { break res?; } @@ -600,7 +611,7 @@ fn populate_available_features( MaybeWorkspace::Other(query) => query, }; let possibilities = loop { - match registry.query_vec(&query, true) { + match registry.query_vec(&query, QueryKind::Fuzzy) { std::task::Poll::Ready(res) => { break res?; } diff --git a/src/cargo/ops/common_for_install_and_uninstall.rs b/src/cargo/ops/common_for_install_and_uninstall.rs index 362a2d96450..08d5c908979 100644 --- a/src/cargo/ops/common_for_install_and_uninstall.rs +++ b/src/cargo/ops/common_for_install_and_uninstall.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use toml_edit::easy as toml; use crate::core::compiler::Freshness; -use crate::core::{Dependency, FeatureValue, Package, PackageId, Source, SourceId}; +use crate::core::{Dependency, FeatureValue, Package, PackageId, QueryKind, Source, SourceId}; use crate::ops::{self, CompileFilter, CompileOptions}; use crate::sources::PathSource; use crate::util::errors::CargoResult; @@ -540,7 +540,7 @@ where } let deps = loop { - match source.query_vec(&dep)? { + match source.query_vec(&dep, QueryKind::Exact)? { Poll::Ready(deps) => break deps, Poll::Pending => source.block_until_ready()?, } diff --git a/src/cargo/ops/resolve.rs b/src/cargo/ops/resolve.rs index 2570723ec57..f2c38b06ede 100644 --- a/src/cargo/ops/resolve.rs +++ b/src/cargo/ops/resolve.rs @@ -209,7 +209,7 @@ fn resolve_with_registry<'cfg>( Ok(resolve) } -/// Resolves all dependencies for a package using an optional previous instance. +/// Resolves all dependencies for a package using an optional previous instance /// of resolve to guide the resolution process. /// /// This also takes an optional hash set, `to_avoid`, which is a list of package diff --git a/src/cargo/ops/vendor.rs b/src/cargo/ops/vendor.rs index a5eeb68f3e9..1449581088a 100644 --- a/src/cargo/ops/vendor.rs +++ b/src/cargo/ops/vendor.rs @@ -60,7 +60,7 @@ struct VendorConfig { #[serde(rename_all = "lowercase", untagged)] enum VendorSource { Directory { - directory: PathBuf, + directory: String, }, Registry { registry: Option, @@ -298,7 +298,10 @@ fn sync( config.insert( merged_source_name.to_string(), VendorSource::Directory { - directory: opts.destination.to_path_buf(), + // Windows-flavour paths are valid here on Windows but Unix. + // This backslash normalization is for making output paths more + // cross-platform compatible. + directory: opts.destination.to_string_lossy().replace("\\", "/"), }, ); } else if !dest_dir_already_exists { diff --git a/src/cargo/sources/directory.rs b/src/cargo/sources/directory.rs index d6f96cc9003..e30755643a7 100644 --- a/src/cargo/sources/directory.rs +++ b/src/cargo/sources/directory.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use std::task::Poll; use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::sources::PathSource; use crate::util::errors::CargoResult; use crate::util::Config; @@ -46,28 +46,21 @@ impl<'cfg> Debug for DirectorySource<'cfg> { } impl<'cfg> Source for DirectorySource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - if !self.updated { - return Poll::Pending; - } - let packages = self.packages.values().map(|p| &p.0); - let matches = packages.filter(|pkg| dep.matches(pkg.summary())); - for summary in matches.map(|pkg| pkg.summary().clone()) { - f(summary); - } - Poll::Ready(Ok(())) - } - - fn fuzzy_query( + fn query( &mut self, - _dep: &Dependency, + dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { if !self.updated { return Poll::Pending; } let packages = self.packages.values().map(|p| &p.0); - for summary in packages.map(|pkg| pkg.summary().clone()) { + let matches = packages.filter(|pkg| match kind { + QueryKind::Exact => dep.matches(pkg.summary()), + QueryKind::Fuzzy => true, + }); + for summary in matches.map(|pkg| pkg.summary().clone()) { f(summary); } Poll::Ready(Ok(())) diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index 5a8849990d1..4644a3ac710 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -1,4 +1,4 @@ -use crate::core::source::{MaybePackage, Source, SourceId}; +use crate::core::source::{MaybePackage, QueryKind, Source, SourceId}; use crate::core::GitReference; use crate::core::{Dependency, Package, PackageId, Summary}; use crate::sources::git::utils::GitRemote; @@ -86,21 +86,14 @@ impl<'cfg> Debug for GitSource<'cfg> { } impl<'cfg> Source for GitSource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - if let Some(src) = self.path_source.as_mut() { - src.query(dep, f) - } else { - Poll::Pending - } - } - - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { if let Some(src) = self.path_source.as_mut() { - src.fuzzy_query(dep, f) + src.query(dep, kind, f) } else { Poll::Pending } diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs index fcbae46088e..78a66e098ec 100644 --- a/src/cargo/sources/path.rs +++ b/src/cargo/sources/path.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use std::task::Poll; use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::ops; use crate::util::{internal, CargoResult, Config}; use anyhow::Context as _; @@ -497,24 +497,21 @@ impl<'cfg> Debug for PathSource<'cfg> { } impl<'cfg> Source for PathSource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - self.update()?; - for s in self.packages.iter().map(|p| p.summary()) { - if dep.matches(s) { - f(s.clone()) - } - } - Poll::Ready(Ok(())) - } - - fn fuzzy_query( + fn query( &mut self, - _dep: &Dependency, + dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { self.update()?; for s in self.packages.iter().map(|p| p.summary()) { - f(s.clone()) + let matched = match kind { + QueryKind::Exact => dep.matches(s), + QueryKind::Fuzzy => true, + }; + if matched { + f(s.clone()) + } } Poll::Ready(Ok(())) } diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index 899c4e73c22..c17b822fd0f 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -176,7 +176,7 @@ use tar::Archive; use crate::core::dependency::{DepKind, Dependency}; use crate::core::source::MaybePackage; -use crate::core::{Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::sources::PathSource; use crate::util::hex; use crate::util::interning::InternedString; @@ -701,12 +701,18 @@ impl<'cfg> RegistrySource<'cfg> { } impl<'cfg> Source for RegistrySource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { + fn query( + &mut self, + dep: &Dependency, + kind: QueryKind, + f: &mut dyn FnMut(Summary), + ) -> Poll> { // If this is a precise dependency, then it came from a lock file and in // theory the registry is known to contain this version. If, however, we // come back with no summaries, then our registry may need to be // updated, so we fall back to performing a lazy update. - if dep.source_id().precise().is_some() && !self.ops.is_updated() { + if kind == QueryKind::Exact && dep.source_id().precise().is_some() && !self.ops.is_updated() + { debug!("attempting query without update"); let mut called = false; let pend = @@ -731,21 +737,16 @@ impl<'cfg> Source for RegistrySource<'cfg> { self.index .query_inner(dep, &mut *self.ops, &self.yanked_whitelist, &mut |s| { - if dep.matches(&s) { + let matched = match kind { + QueryKind::Exact => dep.matches(&s), + QueryKind::Fuzzy => true, + }; + if matched { f(s); } }) } - fn fuzzy_query( - &mut self, - dep: &Dependency, - f: &mut dyn FnMut(Summary), - ) -> Poll> { - self.index - .query_inner(dep, &mut *self.ops, &self.yanked_whitelist, f) - } - fn supports_checksums(&self) -> bool { true } diff --git a/src/cargo/sources/replaced.rs b/src/cargo/sources/replaced.rs index 0bbbd6f181f..2d8a2903d76 100644 --- a/src/cargo/sources/replaced.rs +++ b/src/cargo/sources/replaced.rs @@ -1,5 +1,5 @@ use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::util::errors::CargoResult; use std::task::Poll; @@ -42,32 +42,17 @@ impl<'cfg> Source for ReplacedSource<'cfg> { self.inner.requires_precise() } - fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> Poll> { - let (replace_with, to_replace) = (self.replace_with, self.to_replace); - let dep = dep.clone().map_source(to_replace, replace_with); - - self.inner - .query(&dep, &mut |summary| { - f(summary.map_source(replace_with, to_replace)) - }) - .map_err(|e| { - e.context(format!( - "failed to query replaced source {}", - self.to_replace - )) - }) - } - - fn fuzzy_query( + fn query( &mut self, dep: &Dependency, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { let (replace_with, to_replace) = (self.replace_with, self.to_replace); let dep = dep.clone().map_source(to_replace, replace_with); self.inner - .fuzzy_query(&dep, &mut |summary| { + .query(&dep, kind, &mut |summary| { f(summary.map_source(replace_with, to_replace)) }) .map_err(|e| { diff --git a/src/cargo/util/config/mod.rs b/src/cargo/util/config/mod.rs index 917ffbe5c84..dd3f6ae933e 100644 --- a/src/cargo/util/config/mod.rs +++ b/src/cargo/util/config/mod.rs @@ -2248,13 +2248,7 @@ impl BuildTargetConfig { }; let values = match &self.inner.val { BuildTargetConfigInner::One(s) => vec![map(s)], - BuildTargetConfigInner::Many(v) => { - if !config.cli_unstable().multitarget { - bail!("specifying an array in `build.target` config value requires `-Zmultitarget`") - } else { - v.iter().map(map).collect() - } - } + BuildTargetConfigInner::Many(v) => v.iter().map(map).collect(), }; Ok(values) } diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index ab63420ab24..58647e03f05 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1017,19 +1017,16 @@ pub enum MaybeWorkspace { impl MaybeWorkspace { fn resolve<'a>( self, - cargo_features: &Features, label: &str, get_ws_field: impl FnOnce() -> CargoResult, ) -> CargoResult { match self { MaybeWorkspace::Defined(value) => Ok(value), - MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => { - cargo_features.require(Feature::workspace_inheritance())?; - get_ws_field().context(format!( + MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => get_ws_field() + .context(format!( "error inheriting `{}` from workspace root manifest's `workspace.package.{}`", label, label - )) - } + )), MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: false }) => Err(anyhow!( "`workspace=false` is unsupported for `package.{}`", label, @@ -1345,7 +1342,7 @@ impl TomlManifest { .unwrap() .clone(); package.workspace = None; - package.resolver = ws.resolve_behavior().to_manifest(); + package.resolver = Some(ws.resolve_behavior().to_manifest()); if let Some(license_file) = &package.license_file { let license_file = license_file .as_defined() @@ -1592,7 +1589,7 @@ impl TomlManifest { let version = project .version .clone() - .resolve(&features, "version", || inherit()?.version())?; + .resolve("version", || inherit()?.version())?; project.version = MaybeWorkspace::Defined(version.clone()); @@ -1600,7 +1597,7 @@ impl TomlManifest { let edition = if let Some(edition) = project.edition.clone() { let edition: Edition = edition - .resolve(&features, "edition", || inherit()?.edition())? + .resolve("edition", || inherit()?.edition())? .parse() .with_context(|| "failed to parse the `edition` key")?; project.edition = Some(MaybeWorkspace::Defined(edition.to_string())); @@ -1625,7 +1622,7 @@ impl TomlManifest { let rust_version = if let Some(rust_version) = &project.rust_version { let rust_version = rust_version .clone() - .resolve(&features, "rust_version", || inherit()?.rust_version())?; + .resolve("rust_version", || inherit()?.rust_version())?; let req = match semver::VersionReq::parse(&rust_version) { // Exclude semver operators like `^` and pre-release identifiers Ok(req) if rust_version.chars().all(|c| c.is_ascii_digit() || c == '.') => req, @@ -1716,7 +1713,6 @@ impl TomlManifest { }; fn process_dependencies( - features: &Features, cx: &mut Context<'_, '_>, new_deps: Option<&BTreeMap>, kind: Option, @@ -1736,7 +1732,7 @@ impl TomlManifest { let mut deps: BTreeMap = BTreeMap::new(); for (n, v) in dependencies.iter() { - let resolved = v.clone().resolve(features, n, cx, || inherit())?; + let resolved = v.clone().resolve(n, cx, || inherit())?; let dep = resolved.to_dependency(n, cx, kind)?; validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?; cx.deps.push(dep); @@ -1747,7 +1743,6 @@ impl TomlManifest { // Collect the dependencies. let dependencies = process_dependencies( - &features, &mut cx, me.dependencies.as_ref(), None, @@ -1762,7 +1757,6 @@ impl TomlManifest { .as_ref() .or_else(|| me.dev_dependencies2.as_ref()); let dev_deps = process_dependencies( - &features, &mut cx, dev_deps, Some(DepKind::Development), @@ -1777,7 +1771,6 @@ impl TomlManifest { .as_ref() .or_else(|| me.build_dependencies2.as_ref()); let build_deps = process_dependencies( - &features, &mut cx, build_deps, Some(DepKind::Build), @@ -1793,7 +1786,6 @@ impl TomlManifest { Some(platform) }; let deps = process_dependencies( - &features, &mut cx, platform.dependencies.as_ref(), None, @@ -1809,7 +1801,6 @@ impl TomlManifest { .as_ref() .or_else(|| platform.build_dependencies2.as_ref()); let build_deps = process_dependencies( - &features, &mut cx, build_deps, Some(DepKind::Build), @@ -1825,7 +1816,6 @@ impl TomlManifest { .as_ref() .or_else(|| platform.dev_dependencies2.as_ref()); let dev_deps = process_dependencies( - &features, &mut cx, dev_deps, Some(DepKind::Development), @@ -1872,13 +1862,13 @@ impl TomlManifest { let exclude = project .exclude .clone() - .map(|mw| mw.resolve(&features, "exclude", || inherit()?.exclude())) + .map(|mw| mw.resolve("exclude", || inherit()?.exclude())) .transpose()? .unwrap_or_default(); let include = project .include .clone() - .map(|mw| mw.resolve(&features, "include", || inherit()?.include())) + .map(|mw| mw.resolve("include", || inherit()?.include())) .transpose()? .unwrap_or_default(); let empty_features = BTreeMap::new(); @@ -1895,67 +1885,63 @@ impl TomlManifest { description: project .description .clone() - .map(|mw| mw.resolve(&features, "description", || inherit()?.description())) + .map(|mw| mw.resolve("description", || inherit()?.description())) .transpose()?, homepage: project .homepage .clone() - .map(|mw| mw.resolve(&features, "homepage", || inherit()?.homepage())) + .map(|mw| mw.resolve("homepage", || inherit()?.homepage())) .transpose()?, documentation: project .documentation .clone() - .map(|mw| mw.resolve(&features, "documentation", || inherit()?.documentation())) + .map(|mw| mw.resolve("documentation", || inherit()?.documentation())) .transpose()?, readme: readme_for_project( package_root, project .readme .clone() - .map(|mw| mw.resolve(&features, "readme", || inherit()?.readme(package_root))) + .map(|mw| mw.resolve("readme", || inherit()?.readme(package_root))) .transpose()?, ), authors: project .authors .clone() - .map(|mw| mw.resolve(&features, "authors", || inherit()?.authors())) + .map(|mw| mw.resolve("authors", || inherit()?.authors())) .transpose()? .unwrap_or_default(), license: project .license .clone() - .map(|mw| mw.resolve(&features, "license", || inherit()?.license())) + .map(|mw| mw.resolve("license", || inherit()?.license())) .transpose()?, license_file: project .license_file .clone() - .map(|mw| { - mw.resolve(&features, "license", || { - inherit()?.license_file(package_root) - }) - }) + .map(|mw| mw.resolve("license", || inherit()?.license_file(package_root))) .transpose()?, repository: project .repository .clone() - .map(|mw| mw.resolve(&features, "repository", || inherit()?.repository())) + .map(|mw| mw.resolve("repository", || inherit()?.repository())) .transpose()?, keywords: project .keywords .clone() - .map(|mw| mw.resolve(&features, "keywords", || inherit()?.keywords())) + .map(|mw| mw.resolve("keywords", || inherit()?.keywords())) .transpose()? .unwrap_or_default(), categories: project .categories .clone() - .map(|mw| mw.resolve(&features, "categories", || inherit()?.categories())) + .map(|mw| mw.resolve("categories", || inherit()?.categories())) .transpose()? .unwrap_or_default(), badges: me .badges .clone() - .map(|mw| mw.resolve(&features, "badges", || inherit()?.badges())) + .map(|mw| mw.resolve("badges", || inherit()?.badges())) .transpose()? .unwrap_or_default(), links: project.links.clone(), @@ -2015,11 +2001,10 @@ impl TomlManifest { profiles.validate(&features, &mut warnings)?; } - let publish = project.publish.clone().map(|publish| { - publish - .resolve(&features, "publish", || inherit()?.publish()) - .unwrap() - }); + let publish = project + .publish + .clone() + .map(|publish| publish.resolve("publish", || inherit()?.publish()).unwrap()); project.publish = publish.clone().map(|p| MaybeWorkspace::Defined(p)); @@ -2479,7 +2464,6 @@ impl TomlDependency

{ impl TomlDependency { fn resolve<'a>( self, - cargo_features: &Features, label: &str, cx: &mut Context<'_, '_>, get_inheritable: impl FnOnce() -> CargoResult<&'a InheritableFields>, @@ -2492,7 +2476,6 @@ impl TomlDependency { features, optional, }) => { - cargo_features.require(Feature::workspace_inheritance())?; let inheritable = get_inheritable()?; inheritable.get_dependency(label).context(format!( "error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`", diff --git a/src/doc/contrib/src/SUMMARY.md b/src/doc/contrib/src/SUMMARY.md index 0d63295ffc8..bf0fb38e2b8 100644 --- a/src/doc/contrib/src/SUMMARY.md +++ b/src/doc/contrib/src/SUMMARY.md @@ -17,4 +17,5 @@ - [Running Tests](./tests/running.md) - [Writing Tests](./tests/writing.md) - [Benchmarking and Profiling](./tests/profiling.md) + - [Crater](./tests/crater.md) - [Design Principles](./design.md) diff --git a/src/doc/contrib/src/process/release.md b/src/doc/contrib/src/process/release.md index e6fbcaf8f78..b378be65821 100644 --- a/src/doc/contrib/src/process/release.md +++ b/src/doc/contrib/src/process/release.md @@ -28,6 +28,46 @@ and stable releases. [`dist` bootstrap module]: https://github.com/rust-lang/rust/blob/master/src/bootstrap/dist.rs +## Submodule updates + +Cargo is tracked in the [rust-lang/rust] repository using a [git submodule]. +It is updated manually about once a week by a Cargo team member. +However, anyone is welcome to update it as needed. + +[@ehuss] has a tool called [subup](https://github.com/ehuss/subup) to automate the process of updating the submodule, updating the lockfile, running tests, and creating a PR. +Running the tests ahead-of-time helps avoid long cycle times waiting for bors if there are any errors. +Subup will also provide a message to include in the PR with a list of all PRs it covers. +Posting this in the PR message also helps create reference links on each Cargo PR to the submodule update PR to help track when it gets merged. + +The following is an example of the command to run in a local clone of rust-lang/rust to run a certain set of tests of things that are likely to get broken by a Cargo update: + +```bash +subup --up-branch update-cargo \ + --commit-message "Update cargo" \ + --test="src/tools/linkchecker tidy \ + src/tools/cargo \ + src/tools/rustfmt \ + src/tools/rls" \ + src/tools/cargo +``` + +If doing a [beta backport](#beta-backports), the command is similar, but needs to point to the correct branches: + +```bash +subup --up-branch update-beta-cargo \ + --rust-branch beta \ + --set-config rust.channel=beta \ + --commit-message "[beta] Update cargo" \ + --test="src/tools/linkchecker tidy \ + src/tools/cargo \ + src/tools/rustfmt \ + src/tools/rls" \ + rust-1.63.0:src/tools/cargo +``` + +[@ehuss]: https://github.com/ehuss/ +[git submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules + ## Version updates Shortly after each major release, a Cargo team member will post a PR to update @@ -53,6 +93,23 @@ release**. It is rare that these get updated. Bumping these as-needed helps avoid churning incompatible version numbers. This process should be improved in the future! +[@ehuss] has a tool called [cargo-new-release] to automate the process of doing a version bump. +It runs through several steps: +1. Creates a branch +2. Updates the version numbers +3. Creates a changelog for anything on the master branch that is not part of beta +4. Creates a changelog for anything on the beta branch + +It opens a browser tab for every PR in order to review each change. +It places each PR in the changelog with its title, but usually every PR should be rewritten to explain the change from the user's perspective. +Each PR should also be categorized as an Addition, Change, Fix, or Nightly-only change. +Most PRs are deleted, since they are not relevant to users of Cargo. +For example, remove all PRs related to Cargo internals, infrastructure, documentation, error changes, refactorings, etc. +Usually about half of the PRs get removed. +This process usually takes @ehuss about an hour to finish. + +[@ehuss]: https://github.com/ehuss/ +[cargo-new-release]: https://github.com/ehuss/cargo-new-release [`crates/` directory]: https://github.com/rust-lang/cargo/tree/master/crates ## Docs publishing diff --git a/src/doc/contrib/src/tests/crater.md b/src/doc/contrib/src/tests/crater.md new file mode 100644 index 00000000000..2220cb0c886 --- /dev/null +++ b/src/doc/contrib/src/tests/crater.md @@ -0,0 +1,122 @@ +# Crater + +[Crater](https://github.com/rust-lang/crater) is a tool for compiling and running tests for _every_ crate on [crates.io](https://crates.io) (and a few on GitHub). +It is mainly used for checking the extent of breakage when implementing potentially breaking changes and ensuring lack of breakage by running beta vs stable compiler versions. + +Essentially it runs some `cargo` command on every crate twice; once against the "start" toolchain and again against the "end" toolchain. +For example, "start" could be the stable release, and "end" could be beta. +If it passes in "start" but fails with "end", then that is reported as a regression. + +There is a bot called [craterbot] which is used to run crater on hardware managed by the rust-lang organization. + +Crater is run by the release team during the beta cycle. +If there are any regressions that look like they are caused by Cargo, they should contact the Cargo team to decide how to handle it. + +## Running crater + +If you have a change that you want to test before the beta release, or you want to test behavior that is not normally exercised by crater, you can do a manual run of crater. +Roughly the steps are: + +1. Create a branch with your changes. + + In your clone of cargo, make the changes to incorporate whatever new thing you want to test and push it to a branch on your fork on GitHub. + +2. Get a clone of + +3. Create a branch in your rust-lang/rust clone to add your changes. + +4. Change the `src/tools/cargo` submodule to point to your new branch. + + Modify `.gitmodules` to point to your clone and branch of cargo with the changes you want to test. + For example: + + ```bash + git submodule set-url src/tools/cargo https://github.com/ehuss/cargo.git + git submodule set-branch --branch my-awesome-feature src/tools/cargo + git submodule update --remote src/tools/cargo + git add .gitmodules src/tools/cargo + git commit + ``` + +5. Create an PR on rust-lang/rust. + + Push your submodule changes to GitHub and make a PR. + Start the PR title with `[EXPERIMENT]` to make it clear what the PR is for and assign yourself or @ghost. + +6. Make a "try" build. + + A "try" build creates a full release of x86_64-unknown-linux-gnu and stores it on rust-lang servers. + This can be done with a comment `@bors try` on the PR (all Cargo team members should have permission to do this). + +7. Run crater. + + Look at the [craterbot] docs to determine the command that you want to run. + There are different modes like `check-only`, `build-and-test`, `rustdoc`, etc. + + You can also choose how many crates to run against. + If you are uncertain if your cargo changes will work correctly, it might be a good idea to run against `top-100` first to check its behavior. + This will run much faster. + You can do a full run afterwards. + + After the try build finishes (which should take a couple hours), ask someone to make a crater run. + The Cargo team does not have that permission, so just ask someone on Zulip. + They will need to write a comment to `@craterbot` with the command that you have specified. + +8. Wait. + + Crater can take anywhere from a few hours to a few weeks to run depending on how long the [craterbot queue](https://crater.rust-lang.org/) is and which mode you picked and the priority of your job. + When the crater run finishes, craterbot will post a comment to the PR with a link to a report of the results. + +9. Investigate the report. + + Look through the report which contains links to build logs for any regressions or errors. + +10. Close the PR. + + Whenever you are done doing crater runs, close your PR. + +[craterbot]: https://github.com/rust-lang/crater/blob/master/docs/bot-usage.md + + +## Advanced crater modes + +Crater only has a few built-in modes, such as running `cargo check` or `cargo test`. +You can pass extra flags with `+cargoflags`. + +More complex tests can be accomplished by customizing Cargo to perform whatever actions you want. +Since crater essentially runs `cargo check`, you can modify the `check` command to perform whichever actions you want. +For example, to test `cargo fix --edition`, [this commit](https://github.com/ehuss/cargo/commit/6901690a6f8d519efb4fabf48c1c2b94af0c3bd8) intercepted `cargo check` and modified it to instead: + +1. Only run on crates with the 2018 edition. +2. Run `cargo fix --edition`. +3. Modify the manifest to switch to the 2021 edition. +4. Run `cargo check` to verify. + +If you need to compare the before and after of a command that is not part of crater's built-in modes, that can be more difficult. +Two possible options: + +* Work with the infra team to add a new mode. +* Build two custom try builds. + Each one should modify the `cargo check` command as described above. + The "start" build should perform whichever action you want with an otherwise unmodified cargo. + The "end" build should perform whichever action you want with your modified cargo. + Then, in the `@craterbot` command, specify the start and end hashes of the two try builds. + +## Limitations + +There are some limitations of crater to consider when running Cargo: + +* A crater run without regressions is not a green light to move forward. + * A large portion of Rust code is not tested, such as closed-source projects or things otherwise not collected by crater. + * Many crates can't build in crater's environment or are otherwise broken. + * Some crates have flaky tests. +* Crater runs in an isolated environment. + * It only runs on Linux x86-64. + * It does not have network access. + * The crate source is in a read-only mount. +* Crater does several steps before running the test (using its own copy of the stable toolchain): + * It generates a lockfile using `generate-lockfile` and includes `-Zno-index-update` to prevent index updates (which makes it run much faster). + * All dependencies are downloaded ahead-of-time with `cargo fetch`. +* The built-in modes pass several flags to cargo such as `--frozen` or `--message-format=json`. + It will sometimes use `--all-targets` and sometimes not. + Check the [crater source](https://github.com/rust-lang/crater/blob/master/src/runner/test.rs) for more details on how it works. diff --git a/src/doc/contrib/src/tests/writing.md b/src/doc/contrib/src/tests/writing.md index 0516cce6661..8ff0117efd5 100644 --- a/src/doc/contrib/src/tests/writing.md +++ b/src/doc/contrib/src/tests/writing.md @@ -71,11 +71,11 @@ fn () { #### Testing Nightly Features If you are testing a Cargo feature that only works on "nightly" Cargo, then -you need to call `masquerade_as_nightly_cargo` on the process builder like -this: +you need to call `masquerade_as_nightly_cargo` on the process builder and pass +the name of the feature as the reason, like this: ```rust,ignore -p.cargo("build").masquerade_as_nightly_cargo() +p.cargo("build").masquerade_as_nightly_cargo(&["print-im-a-teapot"]) ``` If you are testing a feature that only works on *nightly rustc* (such as @@ -192,12 +192,12 @@ Be sure to check the snapshots to make sure they make sense. #### Testing Nightly Features If you are testing a Cargo feature that only works on "nightly" Cargo, then -you need to call `masquerade_as_nightly_cargo` on the process builder like -this: +you need to call `masquerade_as_nightly_cargo` on the process builder and pass +the name of the feature as the reason, like this: ```rust,ignore snapbox::cmd::Command::cargo() - .masquerade_as_nightly_cargo() + .masquerade_as_nightly_cargo(&["print-im-a-teapot"]) ``` If you are testing a feature that only works on *nightly rustc* (such as diff --git a/src/doc/man/cargo-bench.md b/src/doc/man/cargo-bench.md index f43e5b24f86..1155ac50b92 100644 --- a/src/doc/man/cargo-bench.md +++ b/src/doc/man/cargo-bench.md @@ -1,6 +1,7 @@ # cargo-bench(1) {{*set actionverb="Benchmark"}} {{*set nouns="benchmarks"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-build.md b/src/doc/man/cargo-build.md index e4dc63f5b28..3b71ae6a317 100644 --- a/src/doc/man/cargo-build.md +++ b/src/doc/man/cargo-build.md @@ -1,5 +1,6 @@ # cargo-build(1) {{*set actionverb="Build"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-check.md b/src/doc/man/cargo-check.md index 208cd273406..44a3d0fdc4d 100644 --- a/src/doc/man/cargo-check.md +++ b/src/doc/man/cargo-check.md @@ -1,5 +1,6 @@ # cargo-check(1) {{*set actionverb="Check"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-clean.md b/src/doc/man/cargo-clean.md index aa631563248..be1fa1fce45 100644 --- a/src/doc/man/cargo-clean.md +++ b/src/doc/man/cargo-clean.md @@ -1,5 +1,6 @@ # cargo-clean(1) {{*set actionverb="Clean"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-doc.md b/src/doc/man/cargo-doc.md index 5e33541395f..f8f517d9ae7 100644 --- a/src/doc/man/cargo-doc.md +++ b/src/doc/man/cargo-doc.md @@ -1,5 +1,6 @@ # cargo-doc(1) {{*set actionverb="Document"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-fetch.md b/src/doc/man/cargo-fetch.md index 601ddb248cd..69ce103cae3 100644 --- a/src/doc/man/cargo-fetch.md +++ b/src/doc/man/cargo-fetch.md @@ -1,6 +1,7 @@ # cargo-fetch(1) {{*set actionverb="Fetch"}} {{*set target-default-to-all-arch=true}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-fix.md b/src/doc/man/cargo-fix.md index 53dfb4cc622..e78ae34fd2e 100644 --- a/src/doc/man/cargo-fix.md +++ b/src/doc/man/cargo-fix.md @@ -1,5 +1,6 @@ # cargo-fix(1) {{*set actionverb="Fix"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-package.md b/src/doc/man/cargo-package.md index 1180df718ef..d7f35c6234c 100644 --- a/src/doc/man/cargo-package.md +++ b/src/doc/man/cargo-package.md @@ -1,6 +1,7 @@ # cargo-package(1) {{*set actionverb="Package"}} {{*set noall=true}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-publish.md b/src/doc/man/cargo-publish.md index 6033b238d4a..560e3c10472 100644 --- a/src/doc/man/cargo-publish.md +++ b/src/doc/man/cargo-publish.md @@ -1,5 +1,6 @@ # cargo-publish(1) {{*set actionverb="Publish"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-rustc.md b/src/doc/man/cargo-rustc.md index 32d3b0e5be7..3ce5c193ab0 100644 --- a/src/doc/man/cargo-rustc.md +++ b/src/doc/man/cargo-rustc.md @@ -1,5 +1,6 @@ # cargo-rustc(1) {{*set actionverb="Build"}} +{{*set multitarget=true}} ## NAME @@ -70,6 +71,19 @@ See the [the reference](../reference/profiles.html) for more details on profiles {{> options-timings }} +{{#option "`--crate-type` _crate-type_"}} +Build for the given crate type. This flag accepts a comma-separated list of +1 or more crate types, of which the allowed values are the same as `crate-type` +field in the manifest for configurating a Cargo target. See +[`crate-type` field](../reference/cargo-targets.html#the-crate-type-field) +for possible values. + +If the manifest contains a list, and `--crate-type` is provided, +the command-line argument value will override what is in the manifest. + +This flag only works when building a `lib` or `example` library target. +{{/option}} + {{/options}} ### Output Options @@ -123,5 +137,9 @@ See the [the reference](../reference/profiles.html) for more details on profiles cargo rustc --lib -- -Z print-type-sizes +3. Override `crate-type` field in Cargo.toml with command-line option: + + cargo rustc --lib --crate-type lib,cdylib + ## SEE ALSO {{man "cargo" 1}}, {{man "cargo-build" 1}}, {{man "rustc" 1}} diff --git a/src/doc/man/cargo-rustdoc.md b/src/doc/man/cargo-rustdoc.md index 2e4b6e21626..6c38780f324 100644 --- a/src/doc/man/cargo-rustdoc.md +++ b/src/doc/man/cargo-rustdoc.md @@ -1,5 +1,6 @@ # cargo-rustdoc(1) {{*set actionverb="Document"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/cargo-test.md b/src/doc/man/cargo-test.md index b948d91c24c..7419b532397 100644 --- a/src/doc/man/cargo-test.md +++ b/src/doc/man/cargo-test.md @@ -1,6 +1,7 @@ # cargo-test(1) {{*set actionverb="Test"}} {{*set nouns="tests"}} +{{*set multitarget=true}} ## NAME diff --git a/src/doc/man/generated_txt/cargo-bench.txt b/src/doc/man/generated_txt/cargo-bench.txt index 0203c082951..597c67d8bb6 100644 --- a/src/doc/man/generated_txt/cargo-bench.txt +++ b/src/doc/man/generated_txt/cargo-bench.txt @@ -208,7 +208,8 @@ OPTIONS Benchmark for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-build.txt b/src/doc/man/generated_txt/cargo-build.txt index 2fafce309fe..16cd5de9a95 100644 --- a/src/doc/man/generated_txt/cargo-build.txt +++ b/src/doc/man/generated_txt/cargo-build.txt @@ -140,7 +140,8 @@ OPTIONS Build for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-check.txt b/src/doc/man/generated_txt/cargo-check.txt index dee68368845..4489bdc6735 100644 --- a/src/doc/man/generated_txt/cargo-check.txt +++ b/src/doc/man/generated_txt/cargo-check.txt @@ -137,7 +137,8 @@ OPTIONS Check for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-clean.txt b/src/doc/man/generated_txt/cargo-clean.txt index a4888cfdfc4..76bdf3fef06 100644 --- a/src/doc/man/generated_txt/cargo-clean.txt +++ b/src/doc/man/generated_txt/cargo-clean.txt @@ -43,7 +43,8 @@ OPTIONS Clean for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-doc.txt b/src/doc/man/generated_txt/cargo-doc.txt index b127c7d88f3..3a2f31b94d4 100644 --- a/src/doc/man/generated_txt/cargo-doc.txt +++ b/src/doc/man/generated_txt/cargo-doc.txt @@ -115,7 +115,8 @@ OPTIONS Document for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-fetch.txt b/src/doc/man/generated_txt/cargo-fetch.txt index afd3fc37791..43aa77eae70 100644 --- a/src/doc/man/generated_txt/cargo-fetch.txt +++ b/src/doc/man/generated_txt/cargo-fetch.txt @@ -28,7 +28,8 @@ OPTIONS Fetch for the given architecture. The default is all architectures. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-fix.txt b/src/doc/man/generated_txt/cargo-fix.txt index 5688ff8b9d0..4cbd085d29a 100644 --- a/src/doc/man/generated_txt/cargo-fix.txt +++ b/src/doc/man/generated_txt/cargo-fix.txt @@ -210,7 +210,8 @@ OPTIONS Fix for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-package.txt b/src/doc/man/generated_txt/cargo-package.txt index c53e1bdd444..25312b39970 100644 --- a/src/doc/man/generated_txt/cargo-package.txt +++ b/src/doc/man/generated_txt/cargo-package.txt @@ -112,7 +112,8 @@ OPTIONS Package for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-publish.txt b/src/doc/man/generated_txt/cargo-publish.txt index a3e93e73274..1371bbc82b5 100644 --- a/src/doc/man/generated_txt/cargo-publish.txt +++ b/src/doc/man/generated_txt/cargo-publish.txt @@ -79,7 +79,8 @@ OPTIONS Publish for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-rustc.txt b/src/doc/man/generated_txt/cargo-rustc.txt index a09a266f9ba..ff3bed59c1d 100644 --- a/src/doc/man/generated_txt/cargo-rustc.txt +++ b/src/doc/man/generated_txt/cargo-rustc.txt @@ -131,7 +131,8 @@ OPTIONS Build for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . @@ -191,6 +192,19 @@ OPTIONS o json (unstable, requires -Zunstable-options): Emit machine-readable JSON information about timing information. + --crate-type crate-type + Build for the given crate type. This flag accepts a comma-separated + list of 1 or more crate types, of which the allowed values are the + same as crate-type field in the manifest for configurating a Cargo + target. See crate-type field + + for possible values. + + If the manifest contains a list, and --crate-type is provided, the + command-line argument value will override what is in the manifest. + + This flag only works when building a lib or example library target. + Output Options --target-dir directory Directory for all generated artifacts and intermediate files. May @@ -341,6 +355,10 @@ EXAMPLES cargo rustc --lib -- -Z print-type-sizes + 3. Override crate-type field in Cargo.toml with command-line option: + + cargo rustc --lib --crate-type lib,cdylib + SEE ALSO cargo(1), cargo-build(1), rustc(1) diff --git a/src/doc/man/generated_txt/cargo-rustdoc.txt b/src/doc/man/generated_txt/cargo-rustdoc.txt index c6a4a814b37..5c718d12546 100644 --- a/src/doc/man/generated_txt/cargo-rustdoc.txt +++ b/src/doc/man/generated_txt/cargo-rustdoc.txt @@ -131,7 +131,8 @@ OPTIONS Document for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/generated_txt/cargo-test.txt b/src/doc/man/generated_txt/cargo-test.txt index 7277e58a381..2170ed2e832 100644 --- a/src/doc/man/generated_txt/cargo-test.txt +++ b/src/doc/man/generated_txt/cargo-test.txt @@ -222,7 +222,8 @@ OPTIONS Test for the given architecture. The default is the host architecture. The general format of the triple is ---. Run rustc --print target-list for - a list of supported targets. + a list of supported targets. This flag may be specified multiple + times. This may also be specified with the build.target config value . diff --git a/src/doc/man/includes/options-target-triple.md b/src/doc/man/includes/options-target-triple.md index 9d91de66cea..bb180f53d7a 100644 --- a/src/doc/man/includes/options-target-triple.md +++ b/src/doc/man/includes/options-target-triple.md @@ -5,6 +5,7 @@ {{~/if}} The general format of the triple is `---`. Run `rustc --print target-list` for a list of supported targets. +{{~#if multitarget }} This flag may be specified multiple times. {{~/if}} This may also be specified with the `build.target` [config value](../reference/config.html). diff --git a/src/doc/src/commands/cargo-bench.md b/src/doc/src/commands/cargo-bench.md index 1e3e3d4a2fa..7a619d662f0 100644 --- a/src/doc/src/commands/cargo-bench.md +++ b/src/doc/src/commands/cargo-bench.md @@ -2,6 +2,7 @@ + ## NAME cargo-bench - Execute benchmarks of a package @@ -255,7 +256,7 @@ be specified multiple times, which enables all specified features.

--target triple
Benchmark for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-build.md b/src/doc/src/commands/cargo-build.md index 753cf9c4d62..444a3fef151 100644 --- a/src/doc/src/commands/cargo-build.md +++ b/src/doc/src/commands/cargo-build.md @@ -1,6 +1,7 @@ # cargo-build(1) + ## NAME cargo-build - Compile the current package @@ -182,7 +183,7 @@ be specified multiple times, which enables all specified features.

--target triple
Build for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-check.md b/src/doc/src/commands/cargo-check.md index ec713d3a742..e1a4b97f4b2 100644 --- a/src/doc/src/commands/cargo-check.md +++ b/src/doc/src/commands/cargo-check.md @@ -1,6 +1,7 @@ # cargo-check(1) + ## NAME cargo-check - Check the current package @@ -177,7 +178,7 @@ be specified multiple times, which enables all specified features.

--target triple
Check for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-clean.md b/src/doc/src/commands/cargo-clean.md index d2e46620471..eee69854dc6 100644 --- a/src/doc/src/commands/cargo-clean.md +++ b/src/doc/src/commands/cargo-clean.md @@ -1,6 +1,7 @@ # cargo-clean(1) + ## NAME cargo-clean - Remove generated artifacts @@ -59,7 +60,7 @@ Defaults to target in the root of the workspace.

--target triple
Clean for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-doc.md b/src/doc/src/commands/cargo-doc.md index eee17d3fd70..d11b01b9559 100644 --- a/src/doc/src/commands/cargo-doc.md +++ b/src/doc/src/commands/cargo-doc.md @@ -1,6 +1,7 @@ # cargo-doc(1) + ## NAME cargo-doc - Build a package's documentation @@ -155,7 +156,7 @@ be specified multiple times, which enables all specified features.

--target triple
Document for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-fetch.md b/src/doc/src/commands/cargo-fetch.md index 7cdd4543e13..9248fb98aeb 100644 --- a/src/doc/src/commands/cargo-fetch.md +++ b/src/doc/src/commands/cargo-fetch.md @@ -2,6 +2,7 @@ + ## NAME cargo-fetch - Fetch dependencies of a package from the network @@ -34,7 +35,7 @@ you plan to use Cargo without a network with the `--offline` flag.

--target triple
Fetch for the given architecture. The default is all architectures. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-fix.md b/src/doc/src/commands/cargo-fix.md index e1fcc76236f..de2a5436f6f 100644 --- a/src/doc/src/commands/cargo-fix.md +++ b/src/doc/src/commands/cargo-fix.md @@ -1,6 +1,7 @@ # cargo-fix(1) + ## NAME cargo-fix - Automatically fix lint warnings reported by rustc @@ -257,7 +258,7 @@ be specified multiple times, which enables all specified features.

--target triple
Fix for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-package.md b/src/doc/src/commands/cargo-package.md index bfae8c1691d..13d08741892 100644 --- a/src/doc/src/commands/cargo-package.md +++ b/src/doc/src/commands/cargo-package.md @@ -2,6 +2,7 @@ + ## NAME cargo-package - Assemble the local package into a distributable tarball @@ -133,7 +134,7 @@ single quotes or double quotes around each pattern.

--target triple
Package for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-publish.md b/src/doc/src/commands/cargo-publish.md index 133d7619bc5..9b8f47f8bc8 100644 --- a/src/doc/src/commands/cargo-publish.md +++ b/src/doc/src/commands/cargo-publish.md @@ -1,6 +1,7 @@ # cargo-publish(1) + ## NAME cargo-publish - Upload a package to the registry @@ -99,7 +100,7 @@ format.

--target triple
Publish for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-rustc.md b/src/doc/src/commands/cargo-rustc.md index ba42ca43e2e..fea0de2b57f 100644 --- a/src/doc/src/commands/cargo-rustc.md +++ b/src/doc/src/commands/cargo-rustc.md @@ -1,6 +1,7 @@ # cargo-rustc(1) + ## NAME cargo-rustc - Compile the current package, and pass extra options to the compiler @@ -169,7 +170,7 @@ be specified multiple times, which enables all specified features.

--target triple
Build for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the @@ -226,6 +227,17 @@ information about timing information. +

--crate-type crate-type
+
Build for the given crate type. This flag accepts a comma-separated list of +1 or more crate types, of which the allowed values are the same as crate-type +field in the manifest for configurating a Cargo target. See +crate-type field +for possible values.

+

If the manifest contains a list, and --crate-type is provided, +the command-line argument value will override what is in the manifest.

+

This flag only works when building a lib or example library target.

+ + ### Output Options @@ -412,5 +424,9 @@ details on environment variables that Cargo reads. cargo rustc --lib -- -Z print-type-sizes +3. Override `crate-type` field in Cargo.toml with command-line option: + + cargo rustc --lib --crate-type lib,cdylib + ## SEE ALSO [cargo(1)](cargo.html), [cargo-build(1)](cargo-build.html), [rustc(1)](https://doc.rust-lang.org/rustc/index.html) diff --git a/src/doc/src/commands/cargo-rustdoc.md b/src/doc/src/commands/cargo-rustdoc.md index 5ae475d7972..3e1a4b8615b 100644 --- a/src/doc/src/commands/cargo-rustdoc.md +++ b/src/doc/src/commands/cargo-rustdoc.md @@ -1,6 +1,7 @@ # cargo-rustdoc(1) + ## NAME cargo-rustdoc - Build a package's documentation, using specified custom flags @@ -174,7 +175,7 @@ be specified multiple times, which enables all specified features.
--target triple
Document for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/commands/cargo-test.md b/src/doc/src/commands/cargo-test.md index ca40d80f6ab..783523bb40f 100644 --- a/src/doc/src/commands/cargo-test.md +++ b/src/doc/src/commands/cargo-test.md @@ -2,6 +2,7 @@ + ## NAME cargo-test - Execute unit and integration tests of a package @@ -269,7 +270,7 @@ be specified multiple times, which enables all specified features.

--target triple
Test for the given architecture. The default is the host architecture. The general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>. Run rustc --print target-list for a -list of supported targets.

+list of supported targets. This flag may be specified multiple times.

This may also be specified with the build.target config value.

Note that specifying this flag makes Cargo run in a different mode where the diff --git a/src/doc/src/reference/config.md b/src/doc/src/reference/config.md index 552a0b5b820..ee330b6e198 100644 --- a/src/doc/src/reference/config.md +++ b/src/doc/src/reference/config.md @@ -363,7 +363,8 @@ Sets the executable to use for `rustc`. * Environment: `CARGO_BUILD_RUSTC_WRAPPER` or `RUSTC_WRAPPER` Sets a wrapper to execute instead of `rustc`. The first argument passed to the -wrapper is the path to the actual `rustc`. +wrapper is the path to the actual executable to use +(i.e., `build.rustc`, if that is set, or `"rustc"` otherwise). ##### `build.rustc-workspace-wrapper` * Type: string (program path) @@ -371,7 +372,8 @@ wrapper is the path to the actual `rustc`. * Environment: `CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER` or `RUSTC_WORKSPACE_WRAPPER` Sets a wrapper to execute instead of `rustc`, for workspace members only. -The first argument passed to the wrapper is the path to the actual `rustc`. +The first argument passed to the wrapper is the path to the actual +executable to use (i.e., `build.rustc`, if that is set, or `"rustc"` otherwise). It affects the filename hash so that artifacts produced by the wrapper are cached separately. ##### `build.rustdoc` @@ -382,16 +384,25 @@ It affects the filename hash so that artifacts produced by the wrapper are cache Sets the executable to use for `rustdoc`. ##### `build.target` -* Type: string +* Type: string or array of strings * Default: host platform * Environment: `CARGO_BUILD_TARGET` -The default target platform triple to compile to. +The default target platform triples to compile to. -This may also be a relative path to a `.json` target spec file. +This allows passing either a string or an array of strings. Each string value +is a target platform triple. The selected build targets will be built for each +of the selected architectures. + +The string value may also be a relative path to a `.json` target spec file. Can be overridden with the `--target` CLI option. +```toml +[build] +target = ["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"] +``` + ##### `build.target-dir` * Type: string (path) * Default: "target" diff --git a/src/doc/src/reference/environment-variables.md b/src/doc/src/reference/environment-variables.md index fc184e3b427..b1a5db4c4e4 100644 --- a/src/doc/src/reference/environment-variables.md +++ b/src/doc/src/reference/environment-variables.md @@ -21,15 +21,18 @@ system: * `RUSTC` — Instead of running `rustc`, Cargo will execute this specified compiler instead. See [`build.rustc`] to set via config. * `RUSTC_WRAPPER` — Instead of simply running `rustc`, Cargo will execute this - specified wrapper instead, passing as its command-line arguments the rustc - invocation, with the first argument being `rustc`. Useful to set up a build - cache tool such as `sccache`. See [`build.rustc-wrapper`] to set via config. -* `RUSTC_WORKSPACE_WRAPPER` — Instead of simply running `rustc`, Cargo will - execute this specified wrapper instead for workspace members only, passing + specified wrapper, passing as its command-line arguments the rustc + invocation, with the first argument being the path to the actual rustc. + Useful to set up a build cache tool such as `sccache`. See + [`build.rustc-wrapper`] to set via config. Setting this to the empty string + overwrites the config and resets cargo to not use a wrapper. +* `RUSTC_WORKSPACE_WRAPPER` — Instead of simply running `rustc`, for workspace + members Cargo will execute this specified wrapper, passing as its command-line arguments the rustc invocation, with the first argument - being `rustc`. It affects the filename hash so that artifacts produced by - the wrapper are cached separately. See [`build.rustc-workspace-wrapper`] - to set via config. + being the path to the actual rustc. It affects the filename hash + so that artifacts produced by the wrapper are cached separately. + See [`build.rustc-workspace-wrapper`] to set via config. Setting this to the empty string + overwrites the config and resets cargo to not use a wrapper for workspace members. * `RUSTDOC` — Instead of running `rustdoc`, Cargo will execute this specified `rustdoc` instance instead. See [`build.rustdoc`] to set via config. * `RUSTDOCFLAGS` — A space-separated list of custom flags to pass to all `rustdoc` diff --git a/src/doc/src/reference/future-incompat-report.md b/src/doc/src/reference/future-incompat-report.md index 703536ed35e..b72f117572a 100644 --- a/src/doc/src/reference/future-incompat-report.md +++ b/src/doc/src/reference/future-incompat-report.md @@ -1,24 +1,37 @@ ### Future incompat report -Cargo checks for future-incompatible warnings in all dependencies. These are warnings for +Cargo checks for future-incompatible warnings in all dependencies. These are warnings for changes that may become hard errors in the future, causing the dependency to stop building in a future version of rustc. If any warnings are found, a small notice is displayed indicating that the warnings were found, and provides instructions on how to display a full report. +For example, you may see something like this at the end of a build: + +```text +warning: the following packages contain code that will be rejected by a future + version of Rust: rental v0.5.5 +note: to see what the problems were, use the option `--future-incompat-report`, + or run `cargo report future-incompatibilities --id 1` +``` + A full report can be displayed with the `cargo report future-incompatibilities --id ID` command, or by running the build again with the `--future-incompat-report` flag. The developer should then update their dependencies to a version where the issue is fixed, or work with the developers of the dependencies to help resolve the issue. -This feature can be configured through a `[future-incompat-report]` -section in `.cargo/config`. Currently, the supported options are: +## Configuration -``` +This feature can be configured through a [`[future-incompat-report]`][config] +section in `.cargo/config.toml`. Currently, the supported options are: + +```toml [future-incompat-report] -frequency = FREQUENCY +frequency = "always" ``` -The supported values for `FREQUENCY` are `always` and `never`, which control +The supported values for the frequency are `"always"` and `"never"`, which control whether or not a message is printed out at the end of `cargo build` / `cargo check`. + +[config]: config.md#future-incompat-report diff --git a/src/doc/src/reference/profiles.md b/src/doc/src/reference/profiles.md index 6885f04ffd4..326be46fab2 100644 --- a/src/doc/src/reference/profiles.md +++ b/src/doc/src/reference/profiles.md @@ -246,7 +246,7 @@ whether or not [`rpath`] is enabled. #### dev The `dev` profile is used for normal development and debugging. It is the -default for build commands like [`cargo build`]. +default for build commands like [`cargo build`], and is used for `cargo install --debug`. The default settings for the `dev` profile are: diff --git a/src/doc/src/reference/registries.md b/src/doc/src/reference/registries.md index 45af03236f4..0289524b3d7 100644 --- a/src/doc/src/reference/registries.md +++ b/src/doc/src/reference/registries.md @@ -320,9 +320,10 @@ visit the registry's website to obtain a token, and Cargo can store the token using the [`cargo login`] command, or by passing the token on the command-line. -Responses use a 200 response code for both success and errors. Cargo looks at -the JSON response to determine if there was success or failure. Failure -responses have a JSON object with the following structure: +Responses use the 200 response code for success. +Errors should use an appropriate response code, such as 404. +Failure +responses should have a JSON object with the following structure: ```javascript { @@ -336,10 +337,10 @@ responses have a JSON object with the following structure: } ``` -Servers may also respond with a 404 response code to indicate the requested -resource is not found (for example, an unknown crate name). However, using a -200 response with an `errors` object allows a registry to provide a more -detailed error message if desired. +If the response has this structure Cargo will display the detailed message to the user, even if the response code is 200. +If the response code indicates an error and the content does not have this structure, Cargo will display to the user a + message intended to help debugging the server error. A server returning an `errors` object allows a registry to provide a more +detailed or user-centric error message. For backwards compatibility, servers should ignore any unexpected query parameters or JSON fields. If a JSON field is missing, it should be assumed to diff --git a/src/doc/src/reference/specifying-dependencies.md b/src/doc/src/reference/specifying-dependencies.md index f1188f6d6fb..36ddf0dbb5a 100644 --- a/src/doc/src/reference/specifying-dependencies.md +++ b/src/doc/src/reference/specifying-dependencies.md @@ -454,8 +454,44 @@ following to the above manifest: log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error! ``` +### Inheriting a dependency from a workspace + +Dependencies can be inherited from a workspace by specifying the +dependency in the workspace's [`[workspace.dependencies]`][workspace.dependencies] table. +After that add it to the `[dependencies]` table with `workspace = true`. + +Along with the `workspace` key, dependencies can also include these keys: +- [`optional`][optional]: Note that the`[workspace.dependencies]` table is not allowed to specify `optional`. +- [`features`][features]: These are additive with the features declared in the `[workspace.dependencies]` + +Other than `optional` and `features`, inherited dependencies cannot use any other +dependency key (such as `version` or `default-features`). + +Dependencies in the `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and +`[target."...".dependencies]` sections support the ability to reference the +`[workspace.dependencies]` definition of dependencies. + +```toml +[project] +name = "bar" +version = "0.2.0" + +[dependencies] +regex = { workspace = true, features = ["unicode"] } + +[build-dependencies] +cc.workspace = true + +[dev-dependencies] +rand = { workspace = true, optional = true } +``` + + [crates.io]: https://crates.io/ [dev-dependencies]: #development-dependencies +[workspace.dependencies]: workspaces.md#the-workspacedependencies-table +[optional]: features.md#optional-dependencies +[features]: features.md