-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow build scripts to specify dependencies #2134
Conversation
r? @huonw (rust_highfive has picked a reviewer for you, use r? to override) |
This looks legit to me. 👍 |
What's the motivation for the directory case (I don't see it in the linked issue)? Are there other build systems that do this? I don't see tests for it, and it's admittedly buggy. Can it be excluded? |
Note that the build.rs script can do multiple things that each have independent dependencies. For example, one part of the build script might build a C library to be linked in, and another part might take a data file and generate Rust code from it. I don't use the Also, this feature seems dangerous as currently specified, as far as optimizing the build. In most cases, it would be better to be able to specify patterns of files that, if they are changed, do NOT cause a rebuild to be needed, with cargo by default assuming that any change does require the build script to get re-run. In particular, I expect it would be common for people to forget to manually update the list of dependencies as their build.rs dependencies change; the feature should be designed to do the safest thing when that happens. |
The directory case was motivated by my own intentions which is that I have a bunch of crates with vendored C source code and I was hoping to not reimplement walking the entire directory tree and printing all paths in those cases. That being said I would be fine leaving it out for now and just not traversing and looking at the mtime of the directory itself (which just won't be meaningful information). You're probably right about just not including something that's already broken. Yeah I would expect the case where multiple things are being done that Cargo would have to be informed about the union of the two and then the build script itself would have to worry about each individually (or just run I would also expect any build dependencies (e.g. |
8d2ad53
to
b920858
Compare
Currently Cargo is quite conservative in how it determines whether a build script should be run. The heuristic used is "did any file in the project directory change", but this is almost always guaranteed to be too coarse grained in situations like: * If the build script takes a long time to run it's advantageous to run it as few times as possible. Being able to inform Cargo about precisely when a build script should be run should provide more robust support here. * Build scripts may not always have all of their dependencies in-tree or in the crate root. Sometimes a dependency could be elsewhere in a repository and scripts need a method of informing Cargo about this (as currently these compiles don't happen then they should). This commit adds this support in build scripts via a new `rerun-if-changed` directive which can be printed to standard output (using the standard Cargo metadata format). The value for this key is a path relative to the crate root, and Cargo will only look at these paths when determining whether to rerun the build script. Any other file changes will not trigger the build script to be rerun. Future extensions could possibly include the usage of glob patterns in build script paths like the `include` and `exclude` features of `Cargo.toml`, but these should be backwards compatible to add in the future. Closes rust-lang#1162
b920858
to
7c97c5b
Compare
Updated with clarification of docs and removal of directory traversal |
My pocket-resources crate lists all the files in a directory and includes all them with |
@tomata Is that a suitable replacement for the directory feature, or are you suggesting the directory feature is needed because of what you are doing? |
Uh, @tomaka, sorry tomata. |
It's an illustration of how the directory feature could be useful. All my game projects contain a However you could reasonably argue that it's my crate that has a bad design and that should be changed, just like using |
Yeah I can see where directories can be useful from time to time, but @brson's point about depending on a directory being a little "inherently broken" (e.g. doesn't track file deletions) is pretty convincing to me that it shouldn't happen just yet. It's reasonably easy enough to traverse a directory in Rust and just print out all the files as well, so I'm fine with a "v1" of this just being that you have to manually print out files in a directory. I don't really expect every crate with a build script to start using this feature. Many build-dependency libraries will likely start working with this but there it's easy enough to implement traversal once and call it a day. |
If a build script doesn't print And if so, how do you write a build script that has no dependency at all? Do you have to use a hack like |
Yeah the current behavior is used if nothing is printed, and I guess some dummy file like that could be used yeah (or perhaps some directory in the source folder). A new directive could perhaps be added for "no input files" at some point in the future. |
👍 :bump: I'm eagerly waiting for this! |
By "dependencies" this means file dependencies, not |
Indeed! Should perhaps consider a better PR title... |
ping r? @brson |
@bors r+ |
📌 Commit 7c97c5b has been approved by |
Currently Cargo is quite conservative in how it determines whether a build script should be run. The heuristic used is "did any file in the project directory change", but this is almost always guaranteed to be too coarse grained in situations like: * If the build script takes a long time to run it's advantageous to run it as few times as possible. Being able to inform Cargo about precisely when a build script should be run should provide more robust support here. * Build scripts may not always have all of their dependencies in-tree or in the crate root. Sometimes a dependency could be elsewhere in a repository and scripts need a method of informing Cargo about this (as currently these compiles don't happen then they should). This commit adds this support in build scripts via a new `rerun-if-changed` directive which can be printed to standard output (using the standard Cargo metadata format). The value for this key is a path relative to the crate root, and Cargo will only look at these paths when determining whether to rerun the build script. Any other file changes will not trigger the build script to be rerun. Currently the printed paths may either be a file or a directory, and a directory is deeply traversed. The heuristic for trigger a rerun is detecting whether any input file has been modified since the build script was last run (determined by looking at the modification time of the output file of the build script). This current implementation means that if you depend on a directory and then delete a file within it the build script won't be rerun, but this is already the case and can perhaps be patched up later. Future extensions could possibly include the usage of glob patterns in build script paths like the `include` and `exclude` features of `Cargo.toml`, but these should be backwards compatible to add in the future. Closes #1162
☀️ Test successful - cargo-linux-32, cargo-linux-64, cargo-mac-32, cargo-mac-64, cargo-win-gnu-32, cargo-win-gnu-64, cargo-win-msvc-32, cargo-win-msvc-64 |
Currently Cargo is quite conservative in how it determines whether a build
script should be run. The heuristic used is "did any file in the project
directory change", but this is almost always guaranteed to be too coarse
grained in situations like:
few times as possible. Being able to inform Cargo about precisely when a build
script should be run should provide more robust support here.
crate root. Sometimes a dependency could be elsewhere in a repository and
scripts need a method of informing Cargo about this (as currently these
compiles don't happen then they should).
This commit adds this support in build scripts via a new
rerun-if-changed
directive which can be printed to standard output (using the standard Cargo
metadata format). The value for this key is a path relative to the crate root,
and Cargo will only look at these paths when determining whether to rerun the
build script. Any other file changes will not trigger the build script to be
rerun.
Currently the printed paths may either be a file or a directory, and a directory
is deeply traversed. The heuristic for trigger a rerun is detecting whether any
input file has been modified since the build script was last run (determined by
looking at the modification time of the output file of the build script). This
current implementation means that if you depend on a directory and then delete a
file within it the build script won't be rerun, but this is already the case and
can perhaps be patched up later.
Future extensions could possibly include the usage of glob patterns in build
script paths like the
include
andexclude
features ofCargo.toml
, butthese should be backwards compatible to add in the future.
Closes #1162