-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Add workspaces to Cargo #1525
Conversation
Improve Cargo's story around multi-crate single-repo project management by introducing the concept of workspaces. All packages in a workspace will share `Cargo.lock` and an output directory for artifacts. Cargo will infer workspaces where possible, but it will also have knobs for explicitly controlling what crates belong to which workspace.
If I have a manually configured workspace, how will cargo figure out that a crate that I'm compiling belongs to a workspace? Will I have had to have built the workspace root first? |
When Cargo constructs a workspace it's built upon the condition that all crates in a workspace can transitively reach all others. This means that for any workspace (manually configured or not) any crate can find its way to the root quickly. In that sense it won't matter if you've built the workspace root first or not, Cargo will be able to build any crate in the workspace at any point in time into the workspace root's output folder. Does that make sense? Not sure if that answers your question... |
Are multi-repo workspaces too niche to be considered? I've been abusing local path overrides for a while now. It would be nice if "local" workspaces could incorporate that. Imagine two repos
I'd be happy if the "local" workspace could transparently change that to |
Let's say that I have a project structure like this:
|
That's an interesting idea! This doesn't currently consider multiple disjoint repositories beyond submodules. Using Ah yes for the workspace to be constructed there you'd need two bits of configuration, one as |
Ok cool, that makes sense. |
What happens if people don't set this up correctly? It seems a bit disappointing for such a common setup to require explicit configuration; I'm not sure what the alternative would be, though, except for having cargo trawl the git repo to look for things that depend on the current directory. (which...might be ok) Still, I think i might prefer to have a |
I asked:
But I think I get it now. If you don't include all the links, things just aren't considered to be in 1 workspace. |
I don't like the convention that this RFC suggests:
|
How does the proposed design work in a scenario when there are multiple equally important binaries and some common library? For example, client-server programs like my wcd may be structured like this. In wcd I have the following structure:
I think I would prefer both binaries to be built together (now it is not very convenient to test how client and server interact when something inside |
Man, I must have been tired when reading the RFC last night. I didn't really grok that it was suggesting that we should structure our repos in a nested fashion. So, e.g., for LALRPOP, where the main lalrpop crate (
and in this way, lalrpop would implicitly be the "workspace root"? This makes the name 'root' make more sense to me. :) I also never thought of structuring things in this way, but I can see that if I did so, then this RFC would allow for a lightweight (no annotation) setup. |
Ah yes, as you surmised the end result is that workspaces just continue to be disjoint (as they are today). If manual configuration is incorrect (e.g. a
One of the major motivational factors for this RFC is to have zero configuration in the conventional use case. A scheme such as you and @sfackler are proposing is certainly covered by this RFC (wish some configuration), but it's unclear to me how it could be the default. The requirement is to be able to go from any crate to all of its workspace crates quickly (eg can't walk the whole filesystem). Do you have something in mind, however, to alleviate this? To reiterate, this RFC doesn't preclude any source layout, it's just blessing one as the conventional way to organize crates where features work without extra configuration.
That's correct, but it's also why it's just a heuristic as part of this RFC. Any and all project layouts are supported, it's just a question of which require less configuration. Most projects usually have some sort of source repo at the top which is a good heuristic for probing (but that's it).
You'd basically choose one of your crates to be the root, and then you'd have to configure a few Do you think the configuration necessary to select one of the binaries as the root is too much, though? Is that a case in favor of some form of "virtual package"?
Yeah that sort of layout would require no extra configuration to benefit, but as @tomaka mentions it may not always make sense for projects. There may be another heuristic we could use to find a "root crate" without any extra configuration, but I'm drawing blanks... |
An alternative could be to separate workspaces from packages, and create another configuration file named for example If you want to have one crate per directory, you can just put a EDIT: Oops, that was already suggested :-/ |
Well, I'm not sure whether it is too much or not, but the whole concept, when applied to "equally important" binaries, seems wrong to me. I just dislike the need to choose one of the crates as a root arbitrarily. Maybe if a client-server application is not a convincing example, then something like coreutils is? It is a collection of lots of different binaries using a single common library, and I doubt that it makes any sense to select one of them as a workspace root. Something like cargo-edit also qualifies, I believe. So yes, I certainly think that virtual packages or some equivalent solution is needed here. |
I'm a little unclear on the implications of the 'workspace inference' rules, which are described abstractly but don't have any examples of what organizations they can infer. I think the standard way to organize a multi-crate project is this:
My understanding is that this structure will be inferred under the proposal and require no annotation. That sounds great. But will other structures be inferred? Like @tomaka mentioned, I think the practice of putting multiple crates inside of a |
Yes! Has anyone looked at Haskell's Stack http://docs.haskellstack.org? IMO whenever I develop multiple crates at once, the idea is almost always that while the libraries are easiest to develop together, they are still full fledged independent libraries:
As such a view If the crates are released/uploaded to crates.io separately, they should NOT be nested in the filesystem, otherwise we need to prune sub trees when uploading so one library doesn't contain others' source. |
The main problem I have stack's |
I think @netvl concern's basically boil down to "dependencies form a DAG, but nested crates form a tree". IMO that right there is the simplest reason that nesting crates is going to suck---simpler and better than the problem I described 2 comments previous :). |
Are you saying that the directory structure itself is confusing, or that the annotations one would need (under this RFC) to support it are confusing? I definitely think the RFC would be improved by specifying the expected directory layout. It makes the rules make much more sense. Do you know if this "nested" structure is in common use today? |
I don't know for the nested structure, but the non-nested structure is not uncommon:
|
The former. I expect everything inside |
Yeah this is certainly always possible (and is one of the alternatives in the RFC), but one of the key points here is that an idiomatic project structure should require zero extra configuration (including this extra manifest). Thanks for the examples! I can certainly see the desire to have a manually selected root location for the workspace, but I'm pretty hesitant to so easily add the concept of virtual crates or packages. It seems like a pretty significant feature that may not quite pull its weight if it's just used for workspaces. For now this could always be worked around with a "dummy package" that ends up being the root, which although not quite as elegant should at least serve as a vector in the interim. @wycats may have more thoughts on the "virtual package" idea, though. I believe he's thought about it more than I have. Could you clarify what you're finding hard to understand about how workspaces are constructed? It's described concretely because that's what'll end up being implemented (I tend to prefer that over a somewhat hand-wavy description). I can certainly add some examples though! I've seen lots of examples with a nested layout and also lots with a nothing-at-the-root layout. I wouldn't necessarily say one is more common than the other. As I mentioned in my reply to @tomaka, however, there's a fundamental problem of child crates still somehow need to quickly discover their parent. That tips the scales in favor (to me) much more in towards a something-should-be-at-the-root structure. I've tried to add some examples though which may help. |
Perhaps alternatives should include using |
An empty |
It's necessary that a concrete implementation be provided in the RFC for implementation, but some examples of the kinds of directory trees these rules infer and the kinds these rules cannot infer would help to understand how it impacts me as a user. |
Ok, the tools team discussed this RFC during its triage meeting the other day, and the conclusion was somewhat mixed. We did not decide to merge just yet, but were somewhat hesitant to do so. There was some pushback about this being an "instantly stable" feature in Cargo because Cargo does not have unstable features like the compiler, and there was also discussion about perhaps blocking this until that existed or somehow ensuring it doesn't reach the stable channel just yet. The question of unstable features in Cargo, however, is pretty weighty, so I'd prefer to not tackle it at this time if possible. I fear that this RFC was perhaps not well written which led to confusion in how it was interpreted. I've rewritten and reorganized the RFC in a format which I hope is much more clear and much simpler than before. Note, however, that there is no semantic change from the previous draft, just hopefully more understandable! cc @rust-lang/tools
We discussed this in the tools meeting, but I think that the current draft is more clear on this as well. There's only one way to put a package in a workspace,
To clarify, no workspace will exist unless
As pointed out by @Ericson2314 it's not possible for a crate to be a member of more than one workspace (it can only point to one root) As discussed in the tools triage meeting, the "we don't walk past VCS roots" part has been removed. There is no other VCS related portion of this RFC (to clarify), which I believe addresses your concerns!
The RFC has been changed slightly to account for this (which I think is simpler as well) to say that
Hm I think that the current draft may be a bit more understandable, does it help clear things up? I think it covers many of your points, but I'm not 100% certain. |
@alexcrichton the new revision of this RFC is awesome! Really clarifies things and the added explicitness will make things much easier to understand, imo. Definitely addresses my concerns at least! |
of crates pointing back to the root may not. If, however, this restriction were | ||
not in place then the set of crates in a workspace may differ depending on | ||
which crate it was viewed from. For example if workspace root A includes B then | ||
it will think B is in A's workspace. If, however, B does ont point back to A, |
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.
Typo: ont
should be not
.
(Please tell me if I'm not allowed to point out typos here)
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.
Thanks!
```toml | ||
# ws1/Cargo.toml | ||
[workspace] | ||
members = ["crate1", "crate2"] |
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.
Maybe "Note that members
aren't necessary ..." ?
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.
It is required here as the newly created manifest does not otherwise depend on the crates.
The tools team discussed this RFC during triage yesterday and the decision was to merge. Once this is implemented we're likely to reevaluate right before the next release to see if we want to let it ride the trains to stable, and we may, for one release, temporarily prevent that particular released version of Cargo from having workspaces. This'll all be based on our experience with workspaces up to that point, however! Thanks again for the discussion everyone! |
Improve Cargo's story around multi-crate single-repo project management by
introducing the concept of workspaces. All packages in a workspace will share
Cargo.lock
and an output directory for artifacts.Cargo will infer workspaces where possible, but it will also have knobs for
explicitly controlling what crates belong to which workspace.
Rendered