Skip to content

Commit

Permalink
Auto merge of #14591 - epage:autolib, r=weihanglo
Browse files Browse the repository at this point in the history
feat(toml): Add `autolib`

### What does this PR try to resolve?

PR #5335 added `autobins`, etc for #5330.  Nowhere in there is
discussion of `autolib`.

Cargo script disables support for additional build-targets by disabling
discovery.
Except we don't have a way to disable discovery of `autolib`, leading to #14476.
By adding `autolib`, we can continue in that direction.

This also allows us to bypass inferring of libs on published packages,
like all other build-targets which were handled in #13849.

Fixes #14476

### How should we test and review this PR?

### Additional information

As this seems fairly low controversy, this insta-stabilizes the field.
In prior versions of Cargo, users will get an "unused manifest key"
warning.
For packages where this is set by `cargo publish`, the warning will be suppressed and things will work as normal.
For `cargo vendor`, the same except there will be some churn in the
vendored source as this field will now be set.
For local development, it should be rare to set `autolib` so the lack of
error by discovering a file when this is set shouldn't be a problem.
  • Loading branch information
bors committed Sep 27, 2024
2 parents a3b35a0 + 5e35e27 commit b396f2c
Show file tree
Hide file tree
Showing 19 changed files with 160 additions and 47 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ cargo-platform = { path = "crates/cargo-platform", version = "0.1.5" }
cargo-test-macro = { version = "0.3.0", path = "crates/cargo-test-macro" }
cargo-test-support = { version = "0.5.0", path = "crates/cargo-test-support" }
cargo-util = { version = "0.2.14", path = "crates/cargo-util" }
cargo-util-schemas = { version = "0.6.0", path = "crates/cargo-util-schemas" }
cargo-util-schemas = { version = "0.7.0", path = "crates/cargo-util-schemas" }
cargo_metadata = "0.18.1"
clap = "4.5.18"
clap_complete = { version = "4.5.29", features = ["unstable-dynamic"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/cargo-util-schemas/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cargo-util-schemas"
version = "0.6.1"
version = "0.7.0"
rust-version = "1.81" # MSRV:1
edition.workspace = true
license.workspace = true
Expand Down
2 changes: 2 additions & 0 deletions crates/cargo-util-schemas/src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ pub struct TomlPackage {
pub publish: Option<InheritableVecStringOrBool>,
pub workspace: Option<String>,
pub im_a_teapot: Option<bool>,
pub autolib: Option<bool>,
pub autobins: Option<bool>,
pub autoexamples: Option<bool>,
pub autotests: Option<bool>,
Expand Down Expand Up @@ -217,6 +218,7 @@ impl TomlPackage {
publish: None,
workspace: None,
im_a_teapot: None,
autolib: None,
autobins: None,
autoexamples: None,
autotests: None,
Expand Down
11 changes: 10 additions & 1 deletion src/cargo/util/toml/embedded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ use crate::GlobalContext;

const DEFAULT_EDITION: crate::core::features::Edition =
crate::core::features::Edition::LATEST_STABLE;
const AUTO_FIELDS: &[&str] = &["autobins", "autoexamples", "autotests", "autobenches"];
const AUTO_FIELDS: &[&str] = &[
"autolib",
"autobins",
"autoexamples",
"autotests",
"autobenches",
];

pub(super) fn expand_manifest(
content: &str,
Expand Down Expand Up @@ -289,6 +295,7 @@ path = "/home/me/test.rs"
autobenches = false
autobins = false
autoexamples = false
autolib = false
autotests = false
build = false
edition = "2021"
Expand Down Expand Up @@ -324,6 +331,7 @@ time = "0.1.25"
autobenches = false
autobins = false
autoexamples = false
autolib = false
autotests = false
build = false
edition = "2021"
Expand Down Expand Up @@ -359,6 +367,7 @@ time = "0.1.25"
autobenches = false
autobins = false
autoexamples = false
autolib = false
autotests = false
build = false
edition = "2021"
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ fn normalize_toml(
package_root,
&original_package.name,
edition,
original_package.autolib,
warnings,
)?;
normalized_toml.bin = Some(targets::normalize_bins(
Expand Down Expand Up @@ -624,6 +625,7 @@ fn normalize_package_toml<'a>(
.map(manifest::InheritableField::Value),
workspace: original_package.workspace.clone(),
im_a_teapot: original_package.im_a_teapot.clone(),
autolib: Some(false),
autobins: Some(false),
autoexamples: Some(false),
autotests: Some(false),
Expand Down
93 changes: 58 additions & 35 deletions src/cargo/util/toml/targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,48 +129,63 @@ pub fn normalize_lib(
package_root: &Path,
package_name: &str,
edition: Edition,
autodiscover: Option<bool>,
warnings: &mut Vec<String>,
) -> CargoResult<Option<TomlLibTarget>> {
let inferred = inferred_lib(package_root);
let lib = original_lib.cloned().or_else(|| {
inferred.as_ref().map(|lib| TomlTarget {
path: Some(PathValue(lib.clone())),
..TomlTarget::new()
})
});
let Some(mut lib) = lib else { return Ok(None) };
lib.name
.get_or_insert_with(|| package_name.replace("-", "_"));
if is_normalized(original_lib, autodiscover) {
let Some(lib) = original_lib.cloned() else {
return Ok(None);
};

// Check early to improve error messages
validate_lib_name(&lib, warnings)?;
// Check early to improve error messages
validate_lib_name(&lib, warnings)?;

validate_proc_macro(&lib, "library", edition, warnings)?;
validate_crate_types(&lib, "library", edition, warnings)?;
validate_proc_macro(&lib, "library", edition, warnings)?;
validate_crate_types(&lib, "library", edition, warnings)?;

if lib.path.is_none() {
if let Some(inferred) = inferred {
lib.path = Some(PathValue(inferred));
} else {
let name = name_or_panic(&lib);
let legacy_path = Path::new("src").join(format!("{name}.rs"));
if edition == Edition::Edition2015 && package_root.join(&legacy_path).exists() {
warnings.push(format!(
"path `{}` was erroneously implicitly accepted for library `{name}`,\n\
please rename the file to `src/lib.rs` or set lib.path in Cargo.toml",
legacy_path.display(),
));
lib.path = Some(PathValue(legacy_path));
Ok(Some(lib))
} else {
let inferred = inferred_lib(package_root);
let lib = original_lib.cloned().or_else(|| {
inferred.as_ref().map(|lib| TomlTarget {
path: Some(PathValue(lib.clone())),
..TomlTarget::new()
})
});
let Some(mut lib) = lib else { return Ok(None) };
lib.name
.get_or_insert_with(|| package_name.replace("-", "_"));

// Check early to improve error messages
validate_lib_name(&lib, warnings)?;

validate_proc_macro(&lib, "library", edition, warnings)?;
validate_crate_types(&lib, "library", edition, warnings)?;

if lib.path.is_none() {
if let Some(inferred) = inferred {
lib.path = Some(PathValue(inferred));
} else {
anyhow::bail!(
"can't find library `{name}`, \
let name = name_or_panic(&lib);
let legacy_path = Path::new("src").join(format!("{name}.rs"));
if edition == Edition::Edition2015 && package_root.join(&legacy_path).exists() {
warnings.push(format!(
"path `{}` was erroneously implicitly accepted for library `{name}`,\n\
please rename the file to `src/lib.rs` or set lib.path in Cargo.toml",
legacy_path.display(),
));
lib.path = Some(PathValue(legacy_path));
} else {
anyhow::bail!(
"can't find library `{name}`, \
rename file to `src/lib.rs` or specify lib.path",
)
)
}
}
}
}

Ok(Some(lib))
Ok(Some(lib))
}
}

#[tracing::instrument(skip_all)]
Expand Down Expand Up @@ -239,7 +254,7 @@ pub fn normalize_bins(
errors: &mut Vec<String>,
has_lib: bool,
) -> CargoResult<Vec<TomlBinTarget>> {
if is_normalized(toml_bins, autodiscover) {
if are_normalized(toml_bins, autodiscover) {
let toml_bins = toml_bins.cloned().unwrap_or_default();
for bin in &toml_bins {
validate_bin_name(bin, warnings)?;
Expand Down Expand Up @@ -526,7 +541,15 @@ fn to_bench_targets(
Ok(result)
}

fn is_normalized(toml_targets: Option<&Vec<TomlTarget>>, autodiscover: Option<bool>) -> bool {
fn is_normalized(toml_target: Option<&TomlTarget>, autodiscover: Option<bool>) -> bool {
are_normalized_(toml_target.map(std::slice::from_ref), autodiscover)
}

fn are_normalized(toml_targets: Option<&Vec<TomlTarget>>, autodiscover: Option<bool>) -> bool {
are_normalized_(toml_targets.map(|v| v.as_slice()), autodiscover)
}

fn are_normalized_(toml_targets: Option<&[TomlTarget]>, autodiscover: Option<bool>) -> bool {
if autodiscover != Some(false) {
return false;
}
Expand Down Expand Up @@ -579,7 +602,7 @@ fn normalize_targets_with_legacy_path(
legacy_path: &mut dyn FnMut(&TomlTarget) -> Option<PathBuf>,
autodiscover_flag_name: &str,
) -> CargoResult<Vec<TomlTarget>> {
if is_normalized(toml_targets, autodiscover) {
if are_normalized(toml_targets, autodiscover) {
let toml_targets = toml_targets.cloned().unwrap_or_default();
for target in &toml_targets {
// Check early to improve error messages
Expand Down
6 changes: 5 additions & 1 deletion src/doc/src/reference/cargo-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,14 @@ configuration tables, such as `[lib]`, `[[bin]]`, `[[test]]`, `[[bench]]`, or
standard directory layout.

The automatic target discovery can be disabled so that only manually
configured targets will be built. Setting the keys `autobins`, `autoexamples`,
configured targets will be built. Setting the keys `autolib`, `autobins`, `autoexamples`,
`autotests`, or `autobenches` to `false` in the `[package]` section will
disable auto-discovery of the corresponding target type.

```toml
[package]
# ...
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down Expand Up @@ -363,6 +364,9 @@ autobins = false
> is `false` if at least one target is manually defined in `Cargo.toml`.
> Beginning with the 2018 edition, the default is always `true`.
> **MSRV:** Respected as of 1.27 for `autobins`, `autoexamples`, `autotests`, and `autobenches`
> **MSRV:** Respected as of 1.83 for `autolib`
[Build cache]: ../guide/build-cache.md
[Rust Edition]: ../../edition-guide/index.html
Expand Down
1 change: 1 addition & 0 deletions src/doc/src/reference/manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Every manifest file consists of the following sections:
* [`publish`](#the-publish-field) --- Can be used to prevent publishing the package.
* [`metadata`](#the-metadata-table) --- Extra settings for external tools.
* [`default-run`](#the-default-run-field) --- The default binary to run by [`cargo run`].
* [`autolib`](cargo-targets.md#target-auto-discovery) --- Disables library auto discovery.
* [`autobins`](cargo-targets.md#target-auto-discovery) --- Disables binary auto discovery.
* [`autoexamples`](cargo-targets.md#target-auto-discovery) --- Disables example auto discovery.
* [`autotests`](cargo-targets.md#target-auto-discovery) --- Disables test auto discovery.
Expand Down
2 changes: 1 addition & 1 deletion src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -1314,7 +1314,7 @@ Inferred / defaulted manifest fields:

Disallowed manifest fields:
- `[workspace]`, `[lib]`, `[[bin]]`, `[[example]]`, `[[test]]`, `[[bench]]`
- `package.workspace`, `package.build`, `package.links`, `package.autobins`, `package.autoexamples`, `package.autotests`, `package.autobenches`
- `package.workspace`, `package.build`, `package.links`, `package.autolib`, `package.autobins`, `package.autoexamples`, `package.autotests`, `package.autobenches`

The default `CARGO_TARGET_DIR` for single-file packages is at `$CARGO_HOME/target/<hash>`:
- Avoid conflicts from multiple single-file packages being in the same directory
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/artifact_dep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2272,6 +2272,7 @@ name = "foo"
version = "0.1.0"
authors = []
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/features2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,7 @@ name = "a"
version = "0.1.0"
authors = ["Zzz"]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down
2 changes: 2 additions & 0 deletions tests/testsuite/features_namespaced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,7 @@ edition = "2015"
name = "foo"
version = "0.1.0"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down Expand Up @@ -1112,6 +1113,7 @@ edition = "2015"
name = "foo"
version = "0.1.0"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down
5 changes: 5 additions & 0 deletions tests/testsuite/inheritable_workspace_fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ include = [
"Cargo.toml",
]
publish = true
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down Expand Up @@ -394,6 +395,7 @@ name = "bar"
version = "0.2.0"
authors = []
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down Expand Up @@ -533,6 +535,7 @@ name = "bar"
version = "0.2.0"
authors = []
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down Expand Up @@ -793,6 +796,7 @@ include = [
"README.md",
]
publish = true
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down Expand Up @@ -966,6 +970,7 @@ name = "bar"
version = "0.2.0"
authors = []
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
Expand Down
Loading

0 comments on commit b396f2c

Please sign in to comment.