Encouraging cyclic dependencies on the other hand “because it is easy” seems like a lazy cop out.
Encouraging cyclic dependencies on the other hand “because it is easy” seems like a lazy cop out.
First, we allow sharing `Cargo.toml` fields across the workspace since 1.64.0 [0]. In the upcoming 1.71.0, we extend this so that `cargo new` will automatically inherit fields when creating new `Cargo.toml` files [1].
From a different angle, we are also adding support for single-file packages though this is more meant for binaries [2]
[0] https://doc.rust-lang.org/cargo/reference/workspaces.html#th...
That having been said, I think my bigger issue with this is that this actually gets to be annoying after you do it, not just while doing it. Go manages external dependencies on the module level, which is a level higher than packages. For Rust, it's crates. So a repo with many crates becomes pretty cumbersome. (And a bit moreso if you're trying to maintain a Nix package for said repo, but that's partly the fault of Nix. Only partly, because I actually think Rust's toolchain makes the job of Nix rather difficult...)
As far as I can tell, all or most of these requirements are met by Cargo lockfiles as well, so what is the gap that makes Cargo/Rust difficult to do well in Nix?
The other thing that's weird is that you have to embed the lockfile into the Nix derivative, at least in some cases. I actually can't remember why that has to be done, but presumably there is a good reason.
I think most multi-crate projects are only sorta accidentally including multiple versions of the same crate, which is why it's rather unfortunate that there isn't some abstraction between crate and module.
However, the Cargo team has been stretched a bit thin; back in April they added two new team members, and so things look like they're going in the right direction again: https://blog.rust-lang.org/inside-rust/2023/04/06/cargo-new-...
But is it so simple that it can be done often without having to go back to the docs and look up something, then making sure everything in the crate makes the build system happy? We get better at doing things the more often we do them, of course, so there's some inflection point where "often enough to remember how to do it" and "simple enough to be able to recall" cross.
With Go, making a new module is just creating a new directory, something programmers have done countless times, and requires no cooperation from the build tool. The only requirement is that files in directory have the same package declaration.
I've got other gripes with cargo.
- A go mod download equivalent would be nice so that we can actually reliably cache dependencies in ci. - More sane linking tooling when statically compiling, eg. Openssl. - Build.rs magic at compile time. - No good way to publish a workspace of crates without actually having to publish everything. - General workspace versioning unfriendliness. It is tricky to bump versions correctly in a workspace.
Probably some more. Most of these already have upstream issues but most have been stale for a while
A go mod download equivalent would be nice so that we can actually reliably
cache dependencies in ci.
What's wrong with caching the target and ~/.cargo directories?Basically you don't want a source change to invalidate your dependency fetching, which can occur if you use cargo fetch and just caching the target, especially with docker, as it doesn't have granular enough caching mechanisms.
Caching ~/.cargo is great tho =D
Its not.
with Go you have ONE go.mod file, at the module root. you may have 100 sub packages or sub sub sub packages, but still only ONE go.mod file. then any time you need to add a new import at ANY level, you just go "go mod tidy", and DONE. please dont try to compares apple and orange and say they are both apples.
Any of these subpackages, if they don't have a go.mod file, would require defining their dependencies top level as well, and when you go get the package you would need to pull everything, even if you only need a subpackage. Which usually isn't a problem, because golang is super fast to compile.
I get that they aren't identical, but tbh they are pretty close
What does go mod download do? cargo fetch/cargo vendor don't do the trick?
This is the upstream issue in question: https://github.com/rust-lang/cargo/issues/2644
Cargo fetch and/or cargo-chef kind of does these things, but not in a super intuitive and easy to use way.
For instance, if you make more crates and they all use the same dependency, you have to manage it all in the multiple Cargo.toml files.
But overall, they're just two different systems with two different tradeoffs. I prefer writing Rust and I prefer the way I specify deps in Rust, but I prefer the ergonomics of packages in Go.
I read it more as the maintenance overhead when publishing. You need to bump version, check dependency versions etc.
I'm speaking from personal experience here. The more I split my crates into sub-crates, the longer the release/publish process takes.
There are some parts you can automate with e.g. cargo-release but I now think a lot harder before cutting a release to crates.io.
I also have the gut feeling this is happening throughout the ecosystem.
I have a lot more overlays in my Cargo.tomls now than I used to, two years ago.
I.e. there are PRs and fixes in the repo. that you need but the author hasn't cut a release.
This may be coincidence ofc but I can't help but think there may be a connection.
I can't for example shove all of the definitions into single file then use it in other files without using sub-modules for no good reason, I much prefer "module = directory" approach to "module = file"
I much prefer "module = directory" approach to "module = file"
https://doc.rust-lang.org/reference/items/modules.html