[Pre-RFC] Development Build Scripts

I’ve been working on the following RFC off and on for a while now after running into a case where I really wanted a build script to be run for test code generation. The idea is pulled whole-sale from @alexcrichton’s comments on cargo issue #1581.

  • Feature Name: dev_build_script
  • Start Date: 2017-07-15
  • RFC PR: (leave this empty)
  • Rust Issue: (leave this empty)

Summary

This RFC proposes a development build script that would be run before tests, examples, and benchmarks are compiled.

Motivation

Build scripts are currently only run when doing a standard debug or release build, but there are many cases where it would be useful to have a build script run for tests, examples, or benchmarks as well. One common case is code generation only for tests.

Detailed design

[package]
# ...
dev-build = "build/test-gen.rs"

[dev-build-dependencies]
foo = "0.1"

A dev-build manifest entry similar to the build entry allowing a build script to be specified will be added. The dev-build script will be written in Rust, built as an executable, and will only be built and run before tests, examples, and benchmarks. This will be in addition to the normal build script, if one exists. The default name for the dev-build script would be dev-build.rs and if this file was found in the root directory of the crate it would be assumed to be a dev-build script. This parallels how build.rs is assumed to be a build script if found in the root directory of a crate.

In addition, a new top-level dependencies array, dev-build-dependencies, will be added to the manifest, paralleling build-dependencies. Only those dependencies listed under dev-build-dependencies will be linked to the dev-build script.

How We Teach This

The in-tree documentation for the manifest, specifying dependencies, and build scripts will be updated to include information on dev-build and dev-build- dependencies. This documentation will closely follow what already exists for build and build-dependencies.

In addition, this feature should be called out in the release notes for the version that it is made stable so as to make it known to existing users.

Drawbacks

Adding dev-build and dev-build-dependencies adds additional complexity to the manifest, the build process, and cargo.

A single development build script may not be granular enough if some but not all tests, examples, or benchmarks require a build script. This would add build time to all tests, examples, and benchmarks where only one item may require the additional work.

Alternatives

The existing build script could be built with --test, --example, or --bench flags before each respective build. This would utilize the current build script mechanism and manifest entries, but some existing build scripts are written assuming they are run only once per compilation and this would break those. In addition, the build script would always be linked dependencies that it might only need for test runs, increasing the number of things needed to be built for any single build, and by extension extending build times.

Unresolved questions

Are there any additional drawbacks to the proposal?

Should there be a way to override development build scripts, such as what is done with normal build scripts?

4 Likes

If you have a build script today that generates code for tests, doesn’t it get run before you can run tests? I thought the project gets built anyway when you cargo test?

Personally I fully agree with the general direction, but find the scope of this proposal too limiting: if we’re going to do general purpose build/test scripting, let’s also include post scripts and not only pre-scripts.

While I agree with you that post build scripts would be great, there has been push-back from the core team to post build scripts. Their general argument is that post build scripts are a slippery slope to becoming a general build manager, which is not the purpose of cargo. So, while I think post build and post dev build functionality should exist for various reasons, I decided to leave that fight to another day.

May be this resolution of this issue Need way to run some code before any of unit tests can solve part of this issue?

You can simply put part of code into function marked like #[test_setup].

Ok I see your point. But could it not be argued that this pre-RFC moves in that very same direction? By this I don’t mean to say that this is a bad proposal (if anything, I think Cargo should definitely provide hooks to service the ecosystem that is more general than Cargo/Rust, given that 1. Cargo tends to be present whenever Rust is and 2. Rust is actively gunning for the niche currently occupied by C and C++), but rather as a statement of fact.

Cargo will inevitably become a general-purpose build manager; the only question is whether it will happen on purpose and with a sensible design, or by accident and without any overarching design.

1 Like

That could be argued, but I think that is a weak argument as this extends the development tools available to the programmer while post build scripts and the like allow for cargo to do more than build, test, and manage crates.

I agree, but that is not the hill I wish to die on today. If I can get this or something that serves the same purpose I would be willing to try to push cargo to be a more general build manager, but that is for a future RFC.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.