(apologies if this has been discussed before, I couldn’t find anything)
I touched on this problem in [pre-pre-rfc?] Solving Crate Trust, but it’s something worth splitting out.
Currently, build scripts and compiler plugins (to a lesser degree) have unfettered power. They may end up doing whatever they want, and it’s hard to reason about them in the context of other build systems. There are a couple of things this impacts:
- Caching/artifact sharing: It’s hard to cache the results of crates compiled with build scripts because we don’t know if a different project’s compilation may result in a different output
- Integration in larger build systems: Most of the larger-build-system plans revolve around using cargo to generate the build plan, and then executing the build from the larger build system.
build.rs
gets in the way here and complicates things, especially if the build system would prefer to drive compilation of native libraries itself (see https://twitter.com/jsgf/status/1053732046948859904) - Security: It’s not great if the process of compilation itself has unfettered local access. This could be solved by sandboxing but it’s hard without knowing what each build script needs
I feel like a significant step in this direction would be some kind of optional Cargo.toml syntax for declaring what a build script can do:
- Some build scripts are “pure”: they basically read files from the package source tree and output files to the outdir (which the rust code presumably pulls in somehow). The outputs of these scripts are easy to cache, and can be integrated into a larger build system easily.
- Some build scripts may depend on a couple keys or environment variables but essentially do the same thing. If their dependencies can be declared beforehand, these can also be cached well
- Some build scripts look for or build a native library. This stuff can sometimes be cached, and sometimes not. It’s less so a pure function, and larger build systems may have very different opinions on what to do here. Worth declaring that they look for and/or build library X, and also mentioning how shareable the compilation is (will different environment vars change things?)
- anything (this is the default, maximum power)
Potentially you can ask cargo to disallow certain kinds of transitive dependencies based on build script capabilities (either in your Cargo.toml or whilst buildings), but the core of this feature is just having this information in Cargo.toml in some form so that other tools can use it. Cargo itself can also use it to share artifacts whenever possible.
I haven’t thought about this enough to have a pre-RFC, and I’m also probably not the right person to do this (my main stake in this topic is that I want to eventually have cross-project artifact sharing), but I feel this is a good place to start brainstorming.