Source directory was modified by build.rs

Hello

I have a project with a build.rs which creates bindings inside my src/ folder

When I run cargo publish, i encounter the error

Source directory was modified by build.rs during cargo publish. Build scripts should not modify anything outside of OUT_DIR.

Is there a way - like in docs.rs with the env DOCS_RS to skip the build script on publish ??

Currently I do

if env::var("DOCS_RS").is_ok() {
    // do nothing on docs.rs 
    return Ok(());
}

I would like to do

if env::var("DOCS_RS").is_ok() || env::var("CARGO_PUBLISH").is_ok() {
    // do nothing on docs.rs or during publish
    return Ok(());
}

Thanks!

I can do cargo publish --no-verify but I would like to just do cargo publish

Your build script is incorrect, and Cargo is checking this so that you don’t publish a broken package.

Build scripts may save any output files or intermediate artifacts in the directory specified in the OUT_DIR environment variable. Scripts should not modify any files outside of that directory.

Build Scripts - The Cargo Book

Build scripts must not write to other locations, especially src, because there is no guarantee that the build script won’t be run twice concurrently (from two different Cargo builds having the same dependency), overwriting files, possibly in the middle of rustc trying to read those files. This can cause compilations to crash or misbehave. Cargo ensures that OUT_DIR is either distinct or accessed with file locking sufficient to avoid this problem.[1]

Change your build script so that it writes only to OUT_DIR. To use the generated files, use an include!(concat!(env!("OUT_DIR"), "/bindings.rs")) or #[path = concat!(env!("OUT_DIR"), "/bindings.rs")].


  1. It is also possible that a future version of Cargo or a non-Cargo package manager might make src read-only via file permissions or sandboxing, so writing to src would not work at all. ↩︎

8 Likes

Hi

Okay thanks

I thought that, since the written files were the same at each time, I could just write them in src (and to also have them in my git repo).

Thanks!

If they are in your repository and in your package, then the build script does not need to generate them and should not be touching them. Pick one or the other strategy, but not both.

2 Likes

In this case, I do code gen in tests and use a snapshotting library to verify (CI) or update (local) code gen output.

3 Likes

For the sake of completeness: There is at least one way to check if cargo publish is running and there is also a way to use a build script to modify the published package at publish time.

See the following old blog post of mine for details.

(Obvious disclaimer: You shouldn't do this as it's rather hacky, not guaranteed to work, and not guaranteed to continue working in future rust versions)

1 Like