> We want a unified good build system for rust, not a ridiculous mess of difference package managers and build systems like in some other language ecosystems. Sometimes, conformity is a better approach, and I would be deeply saddened to see rust go that way.
I would like to disagree on this. I would prefer to see the Rust ecosystem play better with other build systems, instead of requiring all Rust to use Cargo. This becomes important when you are using Rust as part of a larger, multi-language code base. At my day job, we have Rust, Python and Typescript, and we use Bazel for much of the build, getting a bunch of advantages that Bazel brings to the table - remote caching, being able to query the dependency graph, selective testing and so on. These latter are not available in cargo, and would be significant work to re-implement infrastructure based on querying cargo instead of querying bazel.
I think there are 3 different things that Cargo tries to do, which would be better of with strong (and well documented) boundaries between them, so that users could mix and match each of these.
1. Compiling a crate - This is usually one rustc call. I'd venture saying that build.rs files are another layer, but I haven't thought about it enough. It is pretty common in Bazel-land to have build.rs wrapped in a `rust_binary` that is a dependency for the crate itself (usually `rust_library`). This is the easiest to plug into other build systems.
2. Compiling a set of crates/packages - Assuming a system where all the crates are on-disk, Cargo does the job of invoking rustc correctly with the dependencies passed and the right set of features selected. For Bazel, this is what rules_rust implements. The thing is, rules_rust has to figure this out by inspection of Cargo, instead of being able to rely on editions or compiler versions. (FYI, I've never used rules_rust. We have our own internal rules for Rust and we had to figure out things by inspection. Particularly Cargo specific environment variables that are not a part of the Rust language/stdlib, but are assumed to exist by libraries).
3. Package management - i.e. how to get dependencies from the network/someplace else onto disk. I'd suspect this is one place most large orgs would prefer not to rely on Cargo, because it necessarily locks them into some kind of delivery mechanism that is specific to the ecosystem, instead of having a dumb file server. i.e. we would need one for npm/yarn, one for pypi and so on, where each of these frontends know how to go from the "language package name" to the file on disk. I much prefer Bazel here where external dependencies are specified just by HTTP URLs and a sha256 hash to verify contents.
I'm almost _not_ on board with each language building their own compiler driver and package manager, because they end up duplicating so much work - some kind of caching mechanism, some kind of toolchain mechanism, some kind of resolver mechanism and so on...