pre-RFC: let build scripts talk to cargo via a native Rust API instead of string printing

Currently build script tell Cargo what to do by printing cargo:foo= directives for things like library linking, relevant env vars, warnings, and custom key/value variables. And they get inputs via env vars.

It gets the job done, but it's a "stringly-typed" API and it misses out on things that Rust APIs can provide.

Here's an alternative idea: abstract this away behind a Rust crate. Let build scripts use a native Rust API to set these things.

Details of naming and API structure are up to bikeshedding, that's just to give a general idea:

extern crate buildscript; // some build-in crate or prelude

fn main() {
    let mut build = buildscript::new();

    build.link("foolibrary").search_path(path); // real Path
    build.warning("multiple\nlines\nhey!");
    build.set_metadata("key", "value");
   
    // helper to automatically mark as rerun-if-env-changed=FOO
    if let Some(var) = build.env_var("FOO") {
    }

    let out = build.out_dir();

    // future ideas
    if build.rust_newer_than("1.75.1") {
    }
}

I know this currently can be provided by a crate (and the API should be prototyped and ironed out as a crate), But having this as a first-party crate would allow keeping the stringly-printed protocol as an implementation detail between Cargo and its Rust API, thus allowing it be extensible. Also authors of build scripts may not want to pull in a 3rd party crates-io crate for a task that isn't strictly necessary, but when that is a built-in officially blessed API, there's no excuse.

15 Likes
1 Like

I like this idea. If there would be an RPC mechanism between cargo and your crate, I could say rerun in Rust.

Maybe I could even put in my Cargo.toml: build-permisions = [] // no execs .

So existing crates for this

Personally, I would like to see two blessed crates

  • Access to cargo-set env variables
  • Build script API

Granted, I'm also of the opinion we should bless cargo_metadata more than it currently is...

3 Likes

Also vergen — Rust build util // Lib.rs.

1 Like

I'd also love to have target prefix and build prefix available. cc crate has a huge match for that today which isn't exposed and I happen to have a use cases for running target objcopy and for compilint host C binary and running it.

Another issue: errors from build scripts aren't spanned. I had had to use codespan-reporting crate for my own with forced color output. It works fine but a built-in solution would be nicer.