-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement renaming dependencies in the manifest #4953
Conversation
r? @matklad (rust_highfive has picked a reviewer for you, use r? to override) |
This may have already been discussed elsewhere, but I think it would be a bit less confusing to do something like this: [dependencies]
foo = "0.1"
bar = { version = "0.1", registry = "custom", name = "foo" }
baz = { git = "https://github.com/foo/bar", name = "foo" } It avoids the extra array, and makes it so that the set of names you're importing (modulo crate/lib naming differences) are all in the same place. |
Heh that's actually the first syntax I thought of as well, although it was changed due to rust-lang/rfcs#2126 (comment), namely:
For example today you actually specify package names as the key in That being said I also just realized something that can be troubling. How, for example, do we enable features for these dependencies? For example: [dependencies]
foo = [
{ version = "0.1" },
{ version = "0.1", registry = "custom", as = "bar" },
{ git = 'https://github.com/foo/bar', as = "baz" },
]
[features]
some-feature = ["foo/another-feature"] # what version of `foo`? This I think is much clearer with what @sfackler is thinking: [dependencies]
foo = "0.1"
bar = { version = "0.1", registry = "custom", name = "foo" }
baz = { git = "https://github.com/foo/bar", name = "foo" }
[features]
some-feature = ["foo/another-feature"] # aha, the crates.io version! That may tip my own opinion towards the latter! |
Oh yeah, good point. It's too bad you're allowed to set the library name separately from the crate name :( |
src/cargo/core/features.rs
Outdated
@@ -125,6 +125,9 @@ features! { | |||
|
|||
// Downloading packages from alternative registry indexes. | |||
[unstable] alternative_registries: bool, | |||
|
|||
// Downloading packages from alternative registry indexes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong comment
.filter_map(|d| d.rename()) | ||
.next(); | ||
|
||
v.push(name.unwrap_or(&dep.target.crate_name())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make this .unwrap_or
an utility method of something? Like fn crate_name(&self) -> String
, which deals with as
and, probably, with translating -
to _
as well.
tests/rename-deps.rs
Outdated
bar = [ | ||
{ version = "0.1.0" }, | ||
{ version = "0.2.0", as = "baz" }, | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm the syntax does not look too natural to me. Is the following a valid TOML?
[dependencies]
bar = "0.1.0"
bar = { version = "0.2.0", as = "baz"}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately TOML-the-spec doesn't allow for something like that b/c it's counted as a redefinition of an existing key :(
☔ The latest upstream changes (presumably #4844) made this pull request unmergeable. Please resolve the merge conflicts. |
0addcd2
to
6e90f36
Compare
☔ The latest upstream changes (presumably #4957) made this pull request unmergeable. Please resolve the merge conflicts. |
6e90f36
to
102ee8a
Compare
☔ The latest upstream changes (presumably #5011) made this pull request unmergeable. Please resolve the merge conflicts. |
If we wanted to make it clear where we're specifying the package name vs the crate name, perhaps we could do something like... [dependencies]
foo = "0.1"
bar = { version = "0.1", registry = "custom", package = "foo" }
baz = { git = "https://github.com/foo/bar", package = "foo" }
[features]
some-feature = ["foo/another-feature"] # aha, the crates.io version! |
@alexcrichton Great work on this. I think this feature is very much due. Funnily enough, I was just going to suggest the key It's also worth noting that this PR helps with rust-lang/rust#44660. Finally, maybe add a "fixes #1311" to your original PR message? |
102ee8a
to
3d7dcdf
Compare
@alexcrichton Yeah, that's fair enough. Anyway, the new semantics are with the alias on the LHS of the |
@alexreg, correct! |
Super. Hopefully @matklad can review soon and then we can get this merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are a couple of tests I think we could add
-
Using exactly the same library twice. This presumably should be an error
-
Renaming a package whose library name does not match the package namme
@@ -27,6 +27,7 @@ struct Inner { | |||
specified_req: bool, | |||
kind: Kind, | |||
only_match_name: bool, | |||
rename: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd call it package
, to be consistent with the package
in the surface syntax, and to make it more clear in which direction renaming goes (I.e, in theory you can have a crate foo which is renamed to pacakge baz, or, the other way around, a package baz which is renamed to crate foo).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh this is slightly different through b/c it's not actually the package, but rather what the dependency is renaming the crate to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, even though there's a one-to-one correspondence with the package
attribute, rename
probably makes more sense in code (perhaps with a comment?)... that's my thought, anyway.
This commit implements a new unstable feature for manifests which allows renaming a crate when depending on it. For example you can do: ```toml cargo-features = ["dependencies-as"] ... [dependencies] foo = "0.1" bar = { version = "0.1", registry = "custom", package = "foo" } baz = { git = "https://github.com/foo/bar", package = "foo" } ``` Here three crates will be imported but they'll be made available to the Rust source code via the names `foo` (crates.io), `bar` (the custom registry), and `baz` (the git dependency). The *package* name, however, will be `foo` for all of them. In other words the git repository here would be searched for a crate called `foo`. For example: ```rust extern crate foo; // crates.io extern crate bar; // registry `custom` extern crate baz; // git repository ``` The intention here is to enable a few use cases: * Enable depending on the same named crate from different registries * Allow depending on multiple versions of a crate from one registry * Removing the need for `extern crate foo as bar` syntactically in Rust source Currently I don't think we're ready to stabilize this so it's just a nightly feature, but I'm hoping we can continue to iterate on it!
3d7dcdf
to
79942fe
Compare
@matklad sure yeah, although for specifying one crate twice we're already pretty bad about that today unfortunately. For example something like: [dependencies]
foo = "0.1"
[target.'cfg(unix)'.dependencies]
foo = "0.1" is accepted and works, so I figure we can probably just let rustc sort it out if it's specified multiple times. |
@bors r+ |
📌 Commit 79942fe has been approved by |
Good work with this @alexcrichton! Thanks. 👍🏻 |
Implement renaming dependencies in the manifest This commit implements a new unstable feature for manifests which allows renaming a crate when depending on it. For example you can do: ```toml cargo-features = ["dependencies-as"] ... [dependencies] foo = "0.1" bar = { version = "0.1", registry = "custom", package = "foo" } baz = { git = "https://github.com/foo/bar", package = "foo" } ``` Here three crates will be imported but they'll be made available to the Rust source code via the names `foo` (crates.io), `bar` (the custom registry), and `baz` (the git dependency). The *package* name, however, will be `foo` for all of them. In other words the git repository here would be searched for a crate called `foo`. For example: ```rust extern crate foo; // crates.io extern crate bar; // registry `custom` extern crate baz; // git repository ``` The intention here is to enable a few use cases: * Enable depending on the same named crate from different registries * Allow depending on multiple versions of a crate from one registry * Removing the need for `extern crate foo as bar` syntactically in Rust source Currently I don't think we're ready to stabilize this so it's just a nightly feature, but I'm hoping we can continue to iterate on it! cc #1311
☀️ Test successful - status-appveyor, status-travis |
With this merged, does this mean that the item under rust-lang/rust#44931 should be updated? Apologies if this is the wrong place to ask about this |
Here's a curious (but not so improbable) edge case with proc macros. Wondering how should this be handled? (or am I misunderstanding something)
Now, if we use the derive proc macro in crate ^^^^^^ Could not find `foo` in `{{root}}` What would be a proper way to refer to it then?.. |
Here's a concrete example, using
cargo-features = ["rename-dependency"]
[package]
name = "rename-test"
version = "0.1.0"
edition = "2018"
[dependencies]
foo = { package = "num-traits", version = "0.2" }
num-derive = "0.2"
use num_derive::{FromPrimitive, ToPrimitive};
#[derive(FromPrimitive, ToPrimitive)]
enum Color { Red, Blue, Green } ... which results in...
|
@aldanor that's a general problem with hygiene and procedural macros, and most procedural macros only work if the corresponding library crate is imported with one precise name (and not renamed). There's no way, for example, to get importing the |
@alexcrichton Yea, I understand (and this is quite sad because most derive macros depend on some other crate; maybe there should be some crate-resolving syntax like With the example above though, if you revert back to 2015-edition way and remove renaming from the manifest, it does work with [dependencies]
num-traits = "0.2"
num-derive = "0.2" and extern crate num_traits as foo; // <--
#[macro_use] extern crate num_derive;
#[derive(FromPrimitive, ToPrimitive)]
enum Color { Red, Blue, Green } (because of Does it mean this particular case is a rename-dependency regression then? |
I don't think this is really a regression, you can always remove renaming in the manifest and have |
There is an issue open for this at rust-lang/rust#54363. |
Can this enable depending on the same version of a crate but using conflicting features at the same time (with different renaming of course)? |
@updogliu A package cannot have two dependencies to the same version of a crate. |
@ehuss What I am trying to achieve is using a crate of the same version but with conflicting features in two members of a workspace. Is that a valid motivation? |
If the two members are built separately, then they will each use a different copy of the dependent crate (with different features activated). If the two members are being linked together, then it will unify the features and use a single copy. Conflicting or mutually exclusive features aren't really supported. There are a number of issues in the tracker here to make this more flexible, but we're still in the design phase. |
Mutually exclusive features are not supported. |
@retep998 I understand that it is currently not supported. But since this nice renaming dependencies feature is added to support using different versions of a crate, maybe it can be augmented a bit to support exclusive features under different renaming as well? |
I presume cargo features only work on nightly installs |
This commit implements a new unstable feature for manifests which allows
renaming a crate when depending on it. For example you can do:
Here three crates will be imported but they'll be made available to the Rust
source code via the names
foo
(crates.io),bar
(the custom registry), andbaz
(the git dependency). The package name, however, will befoo
for allof them. In other words the git repository here would be searched for a crate
called
foo
. For example:The intention here is to enable a few use cases:
extern crate foo as bar
syntactically in Rust sourceCurrently I don't think we're ready to stabilize this so it's just a nightly
feature, but I'm hoping we can continue to iterate on it!
cc #1311