why Cargo.lock?
Can someone explain clearly to me what Cargo.lock is, and why it exists?
The guide (http://crates.io/faq.html#why-do-binaries-have-cargo.lock-in-version-control,-but-not-libraries?) says:
The purpose of a Cargo.lock is to describe the state of the world at the
time of a successful build. It is then used to provide deterministic
builds across whatever machine is building the project by ensuring that
the exact same dependencies are being compiled.
...but my cargo.toml has explicit versions in it:
[dev-dependencies.fixture]
git = "https://github.com/shadowmint/rust-fixture"
tag = "0.1.2"
There's no confusion here.
Why do you need a separate file that just stores a copy of exactly the same thing?
The guide seems to suggest that Cargo.lock stores the exact version of a dependency, while the Cargo.toml might only store a semver restriction (eg. >= 1.0).
So you can get absolutely repeatable builds using exact versions of libraries.
Fair enough I guess... but if I want that behaviour, I can just pin exact versions in my Cargo.toml.
...the guide also goes on to say:
This is precisely because a library should not be deterministically recompiled for all users of the library.
Well. I feel the same about this as above; if the library author requires that a specific version of dependencies of a library be present, just pin them in cargo.toml.
If the parent project wants to pin the dependencies of an arbitrary child library, why not put those details into the cargo.toml of project? eg.
[lock-dependencies.xml]
git = "https://github.com/netvl/rust-xml"
version = "1.0.2" <--- Lock any reference to rust-xml that is not explicit to this version
Another alternative would be to use the npm model where each build is only as deterministic as the package.json requires it to be.
Cargo.lock just feels like it's been inherited from ruby's bundler for no reason.
Can someone explain the thoughts behind it?
I'm happy to have my opinion of it changed if there are some good reasons, but at the moment the only time I ever hear anything about cargo.lock its people saying "Yes, add it to your gitignore".
Posted Oct 9, 2014, 1:36 AM UTC
Lockfiles are important for a variety of reasons: team collaboration, CI servers, debugging bugs on other systems, etc.
Usually you want to specify SemVer restrictions and not exact values, because you don't actually care about exact versions. You just want the latest stable version in the series you are working with. So you add ">=1.0, <2.0" to your Cargo.toml, update dependencies, build locally and it works great.
Push to Github, your CI server sees the git commit hook and performs a git pull, initiates a build and runs your test suite. Alas, there was an error! You can't seem to reproduce it locally, so you have to debug on the CI server itself (gross) and eventually realize it's a bug in one of your dependencies.
Why didn't you see this locally? Because in the time between your local build and the remote build, one of your dependencies updated and introduced a bug.
Lock files would have prevented this. Update dependencies locally whenever you feel like it. But remote builds (or other team members, whatever) can checkout the lock file and deterministically have the same deps as you.
There is nothing more maddening than trying to debug a problem which turns out to be mismatched dependencies.
Ok, fair enough.
So why isn't there a 'cargo lock' command to generate a Cargo.lock if you want one?
Is there meaningful benefit as having these (typically ignored and discarded) files hanging around by default? (esp for libraries where the advice is to ignore and delete these files and not keep them)
Your remote build fails?
Watch and see what happens.
(my feeling is that if this was an optional step, people wouldn't really use it much)
It's there, but not mentioned neither in the default short help nor in the guide.
(There is also a common puzzling error situation 「A Cargo.lock must exist before it is updated」 that I see people keep stumbling upon and wondering what to do next)
That's because
generate-lockfileisn't really supposed to be used, a lockfile represents a successful build. But we're in a weird moment with everyone on HEAD and not using real versions, so using it to fix questions like that one in IRC is okay, for now.The correct command to generate a lockfile is
cargo build.What u/xstr said.
For you they may be "typically ignored and discarded" but for other people they are frequently used.
Agreed. Which is why it would be a bad default :P
My opinion is that defaults (for any system) should be as safe as possible, and as introduce as few surprises as possible. This satisfies both. It provides the strongest deterministic guarantees and prevents strange bugs caused by mismatched dependencies.
If you don't want to use it...don't. Add it to your .gitignore (one command, ever) and forget about it. If the default was inverted, you would have to execute the
cargo generate-lockfilecommand every time something weird happens and check in the new lock file (two commands, repeatedly executed), presumably after you've already built/committed/pushed/built somewhere else/found bug.[deleted]
Should I add Cargo.lock to my VCS?