Skip to content

Commit

Permalink
cargo: allow dashes in lib.name
Browse files Browse the repository at this point in the history
Change the cargo TOML parser to allow dashes in `lib.name`.

Cargo currently refuses explicit library names if they contain a dash.
However, if no library name is specified, the package-name will be used,
which itself can contain dashes. This leads to packages with `lib.name`
containing dashes, if their package-name contains dashes.

Drop this requirement and allow explicit `lib.name` configurations to
contain dashes.

The current ecosystem clearly allows `lib.name` to contain dashes,
given that `cargo metadata` already reports such names for any package
with a dash. It looks like an oversight that any explicit configuration
is not allowed to include dashes.

All consumers of `lib.name` already use `Target.crate_name()` rather
than `Target.name()` if a sanitized name is required. Therefore, they
already replace dashes with underscores.

Last but not least, the current documentation is simply wrong in stating
that `lib.name` defaults to the package-name with dashes replaced by
underscores. Cargo never replaces dashes for `lib.name`, and `cargo
metadata` and friends already happily show `lib.name` with dashes. Cargo
merely replaces dashes with underscores to retrieve the crate-name of a
target, which is then used as stem for library artifacts.
  • Loading branch information
dvdhrm committed Sep 7, 2023
1 parent 8230b46 commit 27dda17
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 50 deletions.
16 changes: 4 additions & 12 deletions src/cargo/util/toml/targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,10 @@ fn clean_lib(
) -> CargoResult<Option<Target>> {
let inferred = inferred_lib(package_root);
let lib = match toml_lib {
Some(lib) => {
if let Some(ref name) = lib.name {
// XXX: other code paths dodge this validation
if name.contains('-') {
anyhow::bail!("library target names cannot contain hyphens: {}", name)
}
}
Some(TomlTarget {
name: lib.name.clone().or_else(|| Some(package_name.to_owned())),
..lib.clone()
})
}
Some(lib) => Some(TomlTarget {
name: lib.name.clone().or_else(|| Some(package_name.to_owned())),
..lib.clone()
}),
None => inferred.as_ref().map(|lib| TomlTarget {
name: Some(package_name.to_string()),
path: Some(PathValue(lib.clone())),
Expand Down
13 changes: 7 additions & 6 deletions src/doc/src/reference/cargo-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,15 @@ required-features = [] # Features required to build this target (N/A for lib).

### The `name` field

The `name` field specifies the name of the target, which corresponds to the
filename of the artifact that will be generated. For a library, this is the
crate name that dependencies will use to reference it.
The `name` field specifies the name of the target. For a binary it corresponds
to the filename of the artifact that will be generated. For a library, with any
dashes replaced with underscores, it corresponds to the stem used in the
produced library artifact, as well as the name that dependencies will use to
reference the library crate.

For the `[lib]` and the default binary (`src/main.rs`), this defaults to the
name of the package, with any dashes replaced with underscores. For other
[auto discovered](#target-auto-discovery) targets, it defaults to the
directory or file name.
name of the package. For other [auto discovered](#target-auto-discovery)
targets, it defaults to the directory or file name.

This is required for all targets except `[lib]`.

Expand Down
32 changes: 0 additions & 32 deletions tests/testsuite/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3496,38 +3496,6 @@ fn dashes_to_underscores() {
assert!(p.bin("foo-bar").is_file());
}

#[cargo_test]
fn dashes_in_crate_name_bad() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[lib]
name = "foo-bar"
"#,
)
.file("src/lib.rs", "")
.file("src/main.rs", "extern crate foo_bar; fn main() {}")
.build();

p.cargo("build -v")
.with_status(101)
.with_stderr(
"\
[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`
Caused by:
library target names cannot contain hyphens: foo-bar
",
)
.run();
}

#[cargo_test]
fn rustc_env_var() {
let p = project().file("src/lib.rs", "").build();
Expand Down

0 comments on commit 27dda17

Please sign in to comment.