Skip to content
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

Files generated by build script into src/ are compiled twice #3076

Open
nipunn1313 opened this issue Sep 7, 2016 · 10 comments
Open

Files generated by build script into src/ are compiled twice #3076

nipunn1313 opened this issue Sep 7, 2016 · 10 comments
Labels
A-build-scripts Area: build.rs scripts A-rebuild-detection Area: rebuild detection and fingerprinting C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-triage Status: This issue is waiting on initial triage.

Comments

@nipunn1313
Copy link
Contributor

nipunn1313 commented Sep 7, 2016

Repro steps:

  1. Create build.rs and make appropriate entry in Cargo.toml
  2. Have build.rs conditionally generate a file src/foo.rs (eg generate file if it doesn't exist, or generate file if mtime is older than its configuration)
  3. cargo build --verbose (should run build script, generate file, and build foo.rs)
  4. cargo build --verbose again. This time, I would expect it to be a noop, but it rebuilds foo.rs
  5. cargo build --verbose again. This time it's a noop as expected.

I am running into this issue because I am compiling a .proto file into a protobuf rs file during the build.rs phase.

@alexcrichton
Copy link
Member

Ah yeah Cargo doesn't work well if files are generated into the source directory (due to its mtime checking). In that sense this is expected behavior.

Instead though it's intended that build scripts generate files into $OUT_DIR and then they're included in the normal Rust source via:

include!(concat!(env!("OUT_DIR"), "/foo.rs"));

Would that work for this use case?

@nipunn1313
Copy link
Contributor Author

It will work, but it's a little inconvenient because reading the generated code is generally useful. This just makes it a little trickier to locate.

@alexcrichton
Copy link
Member

Yeah that's true, although Cargo otherwise has no way to distinguish between build-script-generated files and normal Rust files (unless you configure ignore in Cargo.toml I believe)

@nipunn1313
Copy link
Contributor Author

Would it be possible to re-stat the mtime after running the build script? The issue here is that the build script generates a file (updating its mtime). Then during compile phase, cargo persists the old mtime, but compiles the new file.

Eg:

build.rs  (generates foo.rs from foo.proto)
proto/
- foo.proto
src/
-  foo.rs

If we update foo.proto to foo'.proto, cargo will compile the new foo'.rs, but persist the mtime from foo.rs

When you build a second time, the build script can recognize that foo.proto is up to date, but cargo thinks that foo'.rs needs to be recompiled since it's checking against the old mtime.

If you build a third time, things are fine.

@alexcrichton
Copy link
Member

We could do that I think, but I believe it'd break the case where if a file is edited normally during a build that it'd trigger a rebuild later (which has been asked for before). Cargo would have to differentiate from a file being generated/edited by a build script or a file edited during a build.

@SirVer
Copy link

SirVer commented Dec 8, 2016

I have the same problem and use case (compiling a proto in build.rs). Unfortunately include!(concat!(env!("OUT_DIR"), "/foo.rs")); does not work for me due to rust-lang/rfcs#752. I found mod_path which works, but since it is a compiler plugin it limits me to unstable which is not acceptable for the project I work on.

For now I am stumped on this. I work around the issue by checking in the manually generated .rs files next to the .proto files, which is suboptimal.

@nipunn1313, did you find an acceptable solution for yourself?
@alexcrichton Can you advise on another work around that would allow me to codegen the .rs file on build?

@alexcrichton
Copy link
Member

@SirVer you may be able to get by with cargo:rerun-if-changed output perhaps? Other than include! though I don't know how to include files from OUT_DIR

@nipunn1313
Copy link
Contributor Author

nipunn1313 commented Dec 9, 2016 via email

@SirVer
Copy link

SirVer commented Dec 10, 2016

@alexcrichton Thanks. I will wait for some conclusion to rust-lang/rfcs#752 and regenerate the code manually for now then.

@nipunn1313 Can I see this code somewhere? Would be interesting to see how you solved it.

@andrewbaxter
Copy link

Is there a more general issue about build.rs generated sources? The include! workaround brings along a number of other issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-build-scripts Area: build.rs scripts A-rebuild-detection Area: rebuild detection and fingerprinting C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-triage Status: This issue is waiting on initial triage.
Projects
None yet
Development

No branches or pull requests

6 participants