-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Rustpkg #4610
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
Rustpkg #4610
Conversation
…o workcache or dependency resolution yet)
Thanks, z0w0! This will take some time to review. |
First thoughts: \o/ \o/ I totally want this to land. Subsequent thoughts focus on the remainder of the conversation we were having over in the gist, when tav was asking for ever-fewer moving parts (from the user's side), and I sympathize with that. I like where you've gone with this but I think there might still be a few opportunities to file down extra stuff users have to do in the default case, without sacrificing the things you, me, pcwalton and others (rightly) want to keep possible in more-special cases. In particular, the two remaining "extra bits" I think we can remove by default are the
All these are, as I say, just minor concerns. I only raise them at this point in order to try to nudge things that may be harder to nudge the further down the road we get. This is definitely the road I want to be going down though, in general. It's great code and I'm glad to see it; did a quick read through all the files and would be happy to see this landing. |
@graydon your points are really good, but I haven't done it exactly the way you suggest for a few reasons. I'm completely open to having the URL be the unique ID. But I am really not happy at all with having it find crates to be used/installed just by walking down the directory. That really doesn't sound right to me. I like a central metadata format, because it allows us to have a central place to store data that might be needed in the future. I also think the central metadata declaring where the files is a better way to do it because there's no ambiguity to the logic of finding the files - whereas walking the directory is weak to things like localized filesystem sorting methods, if I'm not mistaken. Plus, if there's any external things that need to detect a package - for example, Travis CI - it is much easier for them to be sure that there will always be a I'm 100% dedicated to this, so if there's a solid concept to tweak towards, then I'm commited to changing it :). But I think this system also works really well. I guess what is really important right now is not to worry about the concept of it as much but rather let the users of the language itself try it out and see what they think could be better. Also good point about |
@z0w0: do you have a recommendation for how to test this? is there perhaps an example set up? I don't understand from the pull request how to establish dependencies to remote crates or packages. |
Just a note as per the whole 'local vs remote' thing: in Ruby world, bundler has a config option that manages this: http://gembundler.com/v1.2/whats_new.html#local-git-repos The structure is different, of course, but the idea is that on a per-project basis, you can say "Please override this with a local version instead" so that you can try out your local changes rather than the remote ones, without actually touching the file, which would cause issues when pushing it public. That said, this might be too different from the way things work now, I haven't looked into this. Packaging is really important, though, so it's mega important that Rust get this right. :) |
How about doing build logic lookup this way:
This allows three flavors of laziness in publishing a repo:
And it also allows the maintainer to 'upgrade' his crate definition without code breaking, so he can for example go from 'a giant *.rs file containing everything' over 'code neatly seperated into modules' to 'I need to use custom build logic' |
Sounds like sane logic to me. I'll add it later.
|
The scenario I'm hoping to streamline is the "throw a library on github that consists of a handful of source files and nothing terribly special about building them". So if you imagine creating a library
Would that be stable / deterministic enough? The main thing is to derive as much as possible through convention or information implied in the existing structure of a pile of source files. Including the inter-package dependency: an Anyway, as you say this is somewhat academic. I'm fine with the rest of the code. It's moving in the right direction, r+ (Also @Kimundi, keep in mind, |
We still use .rc files now because that is cargo's convention for locating the crate. |
Here are my initial notes from using rustpkg: The UI is very nice. Output is now in Trying to run
There are three commands involved here and the relationship isn't clear to me.
|
This design is committed to the approach of compiling a program How much does the design depend on this approach and will adding further features to the compiler require adding more syntax transformations? This sort of code can be frustrating to maintain and I don't want it getting out of control. At the least please make sure that all functions and type referenced by your generated code all live in the same module - dedicate Also please design these syntax transformations with the intent that they all fit into a syntax extension or compiler pass. |
@z0w0: Can you describe exactly what transformations rustpkg does to |
@z0w0: How do you propose to test rustpkg? Cargo had very few tests and occasionally broke without anybody noticing. |
The transformations it does as follows:
It's really hard to test a package manager. I'd suggest testing it by have a standard set of test projects that all the commands are run over to ensure they're still working. |
We talked about this some on IRC but here's my reason for wanting to put everything in Servo is a package with dependencies on a number of other packages. I maintain 4 different servo workspaces. In each workspace I might make conflicting changes to the subpackages that don't modify the version hash. If each workspace installs these different libraries to a global store then the versioning would need to be very precise to not cause conflicts. |
Well we don't need to put everything in |
I think the scheme @z0w0 proposes will work: The key is for builds to be "purely functional" in the sense of capturing all dependencies, which means the semvers fed in from local workspaces with their own diffs from a release tag should include a "patch level" encoding the git rev of the local workspace, because they're different sources: they produce a different artifact that the user might want to switch to using. Might also need to consider the toolchain used to build as a dependency. And probably a few other things too. Pure functional package management needs to be quite careful. |
@graydon yeah, I think it will work out well. I'll work on that now then. I don't quite understand the second part of your comment (although I get the gist - automatically append a generated patch thing to the semver tag), so I'll get you to elaborate next time we meet on #rust. |
I'm very opposed to putting stuff in Everyone is just going to reinvent something like RVM if we don't do this properly. |
As a data point, Cabal (the Haskell package manager) installs stuff into |
@pcwalton there are two things being conflated here. one is using Can you elaborate on what you object to? In very precise terms. Outline the failure scenario. I can see a bunch of possible concerns and I'm not sure which you're worried about. |
Hmm, well, I guess I'm worried about two things:
|
Multiple version coexistence (down to the source hash) is a necessary part of anything we do here. The only question I'm wondering is whether you're concerned that ... say, the mechanisms for managing multiple versions might be so fragile that users wind up wanting to isolate their work in subdirs just to work around the package manager being buggy about making multiple versions coexist. |
@graydon I am surprised you think we can extend the versioning scheme down to the patch level. That is even more difficult than the current scheme, which already doesn't work reliably. Each library is going to be dynamically linked to the exact binary that it encountered at build time. We might as well not have dlls at all. I anticipate many months of pain and frequently deleting all my rust libraries when something goes wrong. |
@graydon To be clear, I do think you are suggesting that the built libraries of dependent packages live in ~/.rustpkg. So when I build servo, I get copies of cairo, servo-gfx, and all the libraries it depends on in ~/.rustpkg. |
For development, @brson raises a good point. It sounds wrong to install development libraries for Servo in |
The built binaries and dependencies will be built into For the record, I've never heard anyone complain about Cabal or Rubygems.
|
We all clearly have strong feelings about this and are talking across purposes. Nobody wants to do anything that results in absurdity or breakage. Let's not block this pull (which includes such pedestrian matters as "renaming cargo to rustpkg and starting a new code lineage") on the issue of version collision, considering almost nothing else in the remaining infrastructure (from library naming to build caching) exists or works properly yet. My feeling is this is good enough to land (cargo didn't solve versions either) and we can continue to discuss. r+ from me, is anyone else too worried to let it proceed? |
I agree with @graydon. Most of the issues voiced here involve the backend. What's important is the frontend is right because the backend can easily be changed. I will definitely work on the |
@graydon No, go ahead. |
What's the status of this, @graydon? Not to rush you or anything, just wondering if everything is still cool. |
Rebased a number of times in my workspace, keep getting pulled away before landing. There were a number of minor errors. I'm hoping to land it this week. |
Continued over in #4799 -- closing this one. Thanks! |
Taking over where #4610 left off. Much rebasing and tidying.
Rustpkg is a revamp of Cargo for the Rust suite that I've been working on for the past week. It's a purely functional package manager that has no central sources of any kind,
but rather installs via URLs. It's similar to how Go's
go get
tool works, exceptrustpkg requires a central metadata file (
package.rs
) in the repository, archive or folderin order to figure out how to build the package. This is a side effect of rustpkg
allowing multiple crates to be defined in a single package (i.e. a package is defined
as a set of crates rather than a package being exactly the same as one crate).
The metadata is written in Rust. This is both good and bad. One con is that
Rust's syntax is going to be moderately unstable until v1.0 (as I was told),
so compiling an old package might spring up weird compiling errors. On the other hand,
you get to write the build process in Rust itself which is so incredibly meta and fun
and you get to use an awesome language to build projects in that same awesome language.
Rustpkg also doubles as a powerful build system that gives you two ways to
describe the build process of projects: declarative and imperative. The declarative
syntax allows you to declare the build process using Rust's attribute syntax.
A simplistic declarative package script (
package.rs
) would be somethinglike the following (Servo doesn't actually use rustpkg, it's just an example):
The imperative API is for when you need a more powerful build process, such
as probing the system for important configuration, running shell scripts (or
even autotools, which is a planned builtin feature that I want to add). A simple
example using the imperative API is as follows (rustpkg is automatically included):
When a package's crates are installed, they are stored under a unique name (Rust's library crates work like this out of the box) in
~/.rustpkg/bin
or~/.rustpkg/lib
. This allows packages to coexist in a purely functional manner. However, if you want to easilyuse a binary crate that has been installed from the
~/.rustpkg/bin
path (afteradding it to your
$PATH
) then rustpkg provides "preferring" functionalityto symlink a generic name for the crate into the binary directory (which
voids the purely functional label, which is why it's explicitly optional). For example, if you had a crate with the name
servo
and it's uniquely installed to~/.rustpkg/bin/servo-<hash>-0.5.6
thenrustpkg prefer servo
would link it to~/.rustpkg/bin/servo
which you can then easily run as justservo
if the binary directory is in your$PATH
.There's also
rustpkg do <cmd>
which allows you to create scripts callable by the user in the package script:There's more detailed per-command info in
rustpkg --help
.Preferring is currently pretty rusty, along with some of the other features. But that's to
be expected due to this being the initial implementation and I plan to perfect it
over time (including documentation). This pull request also adds
std::semver
, which is originally made by @erickt but I've ported it to the latest syntax and added it into std with his permission.I still really want to add the following but they're not important for the initial pull request:
std::workcache
for only compiling things that have changed