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

Reconsider RUSTFLAGS artifact caching. #8716

Closed
ehuss opened this issue Sep 19, 2020 · 15 comments · Fixed by #14830
Closed

Reconsider RUSTFLAGS artifact caching. #8716

ehuss opened this issue Sep 19, 2020 · 15 comments · Fixed by #14830
Labels
A-rebuild-detection Area: rebuild detection and fingerprinting A-rustflags Area: rustflags E-hard Experience: Hard S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

Comments

@ehuss
Copy link
Contributor

ehuss commented Sep 19, 2020

When RUSTFLAGS is changed between invocations, this can trigger a complete rebuild. This can be annoying, and the only workaround is to use a separate target directory for each RUSTFLAGS setting. I think we should revisit how this works, and see if there is a way to address the problems.

Motivation:

  • Changing RUSTFLAGS can be very expensive time-wise, and frustrating if your project relies on being able to swap between different settings.
  • Supporting a shared build directory cache would be thwarted any time someone changes RUSTFLAGS.

History:

Solutions?
I am uncertain what a good approach would be. Some rough ideas:

  • Go back to hashing RUSTFLAGS, but only in the -C extra-filename, and not -C metadata. This should (probably) avoid the PGO problems, since the symbols won't change. However, this could still cause problems with reproducible builds if the rlib filename somehow leaks into the resulting binary (I don't have a reason to think it does, but it seems risky).
  • Add a mechanism for specifying RUSTFLAGS so that the user can decide whether or not it gets hashed. (Maybe a separate env var, or some string in the current one, or a side setting?) I feel like there is a problem that specifying RUSTFLAGS is already too complicated (considering the multiple overrides) and at the same time not flexible enough.
  • Provide first-class support for some of the things that people use RUSTFLAGS for today. For example, Cargo could have a "reproducible" mode where it tries to create a reproducible build, making whatever sacrifices are necessary. First class support for remap-path-prefix and PGO could also alleviate some of the problems.
@ehuss ehuss added A-rebuild-detection Area: rebuild detection and fingerprinting A-rustflags Area: rustflags labels Sep 19, 2020
@jyn514
Copy link
Member

jyn514 commented Sep 19, 2020

Provide first-class support for some of the things that people use RUSTFLAGS for today.

My main pain point with RUSTFLAGS is xd009642/tarpaulin#416 (comment), which has some niche flags and wouldn't be helped much by this. AFAIK all of those flags are codegen/linking related though, and don't affect .rlibs.

Add a mechanism for specifying RUSTFLAGS so that the user can decide whether or not it gets hashed.

Maybe there can be a way for rustc itself to tell cargo whether an option requires a re-compile? Something like rustc -Z needs-recompile "$RUSTFLAGS". I agree this shouldn't be left up to the user, my main complaint about make other build systems is they require you to specify build dependencies yourself.

I don't know enough about -C metadata and -C extra-filename to have an opinion.

@alexcrichton
Copy link
Member

However, this could still cause problems with reproducible builds

I believe this does because the filenames of object files show up as the codegen unit names in dwarf debug info (and probably PDB?). I suspect that everything else in the binary will be the same, but builds differing only in extra-filename are likely to still produce different binaries.

Add a mechanism for specifying RUSTFLAGS so that the user can decide whether or not it gets hashed

I think this will work but I don't think it'll be too feasible if the default is to not hash RUSTFLAGS. The pain of rebuilding too much you only discover after-the-fact that you should have been hashing rustflags all along. I don't think we can hash-by-default though since it breaks the use cases you've mentioned.

Provide first-class support for some of the things that people use RUSTFLAGS for today

I do think a --reproducible flag or --pgo is something we should add to Cargo no matter what, regardless of how this RUSTFLAGS issue is settled.


Another possible solution could be adding a new variable like RUSTFLAGS_HASHED? That way if tooling sets it the weird env name is fine (maybe the case for tarpaulin?)

tony84727 added a commit to tony84727/youki that referenced this issue Jun 14, 2022
building static-linked runtimetest requires additional RUSTFLAGS env
var. Unfortunately, the additional env var invalids the build cache,
leading cargo rebuilding everytime.

See rust-lang/cargo#8716

A temporary solution is to build runtimetest in a seperate
`runtimetest-target` directory.

Signed-off-by: Tony Duan <[email protected]>
tony84727 added a commit to tony84727/youki that referenced this issue Jun 14, 2022
building static-linked runtimetest requires additional RUSTFLAGS env
var. Unfortunately, the additional env var invalids the build cache,
leading cargo rebuilding everytime.

See rust-lang/cargo#8716

A temporary solution is to build runtimetest in a seperate
`runtimetest-target` directory.

Signed-off-by: Tony Duan <[email protected]>
jschwe added a commit to jschwe/corrosion that referenced this issue Jul 12, 2022
For some scenarios it is better to not set Rustflags for all crates
in the dependency graph and instead only set it for the top-level
crate.
For example rust-lang/cargo#8716
can be avoided in some scenarios by setting the rustflags via
rustc, which allows for faster rebuilds in such cases.
jschwe added a commit to jschwe/corrosion that referenced this issue Sep 6, 2022
For some scenarios it is better to not set Rustflags for all crates
in the dependency graph and instead only set it for the top-level
crate.
For example rust-lang/cargo#8716
can be avoided in some scenarios by setting the rustflags via
rustc, which allows for faster rebuilds in such cases.
jschwe added a commit to jschwe/corrosion that referenced this issue Sep 7, 2022
For some scenarios it is better to not set Rustflags for all crates
in the dependency graph and instead only set it for the top-level
crate.
For example rust-lang/cargo#8716
can be avoided in some scenarios by setting the rustflags via
rustc, which allows for faster rebuilds in such cases.
jschwe added a commit to jschwe/corrosion that referenced this issue Sep 10, 2022
For some scenarios it is better to not set Rustflags for all crates
in the dependency graph and instead only set it for the top-level
crate.
For example rust-lang/cargo#8716
can be avoided in some scenarios by setting the rustflags via
rustc, which allows for faster rebuilds in such cases.
jschwe added a commit to jschwe/corrosion that referenced this issue Sep 10, 2022
For some scenarios it is better to not set Rustflags for all crates
in the dependency graph and instead only set it for the top-level
crate.
For example rust-lang/cargo#8716
can be avoided in some scenarios by setting the rustflags via
rustc, which allows for faster rebuilds in such cases.
luckysori added a commit to get10101/10101 that referenced this issue Mar 8, 2023
We've used a similar pattern in past projects.

One thing that has changed is that we use
`[target.'cfg(feature = "cargo-clippy")']` instead of `[build]`. This
allows us to enforce this lint configuration locally and not just on
CI.

Using `rustflags` does mean that devs might encounter unexpected full
rebuilds when switching between IDE and command line when using `cargo
clippy`. This is a known issue[1]. For emacs, I just solved this by
setting a different Cargo `target-directory` to the one used by
default. A similar approach should work for other IDEs.

[1]: rust-lang/cargo#8716.
luckysori added a commit to get10101/10101 that referenced this issue Mar 8, 2023
We've used a similar pattern in past projects.

One thing that has changed is that we use
`[target.'cfg(feature = "cargo-clippy")']` instead of `[build]`. This
allows us to enforce this lint configuration locally and not just on
CI.

Using `rustflags` does mean that devs might encounter unexpected full
rebuilds when switching between IDE and command line when using `cargo
clippy`. This is a known issue[1]. For emacs, I just solved this by
setting a different Cargo `target-directory` to the one used by
default. A similar approach should work for other IDEs.

[1]: rust-lang/cargo#8716.
@epage
Copy link
Contributor

epage commented Nov 15, 2024

Since #6503, we've tests for --remap-path-prefix. In that, we have a test that assumed -C extra-filename is the same as -C metadata and tests for -C extra-filename being stable across a RUSTFLAGS change to verify that -C metadata doesn't change.

// Ensure that --remap-path-prefix does not affect metadata hash.
let p = project().file("src/lib.rs", "").build();
p.cargo("build").run();
let rlibs = p
.glob("target/debug/deps/*.rlib")
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(rlibs.len(), 1);
p.cargo("clean").run();
let check_metadata_same = || {
let rlibs2 = p
.glob("target/debug/deps/*.rlib")
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(rlibs, rlibs2);
};

@ehuss or @weihanglo any thoughts on another way of testing for -C metadata stability?

github-merge-queue bot pushed a commit that referenced this issue Nov 16, 2024
…14826)

### What does this PR try to resolve?

We have
- `-C metadata`
- `-C extra-filename`
- Uniquifying build scripts
- Uniquifying scraped documentation

Currently, these are all the same value. For #8716, we might want to
have `-C metadata` and `-C extra-filename` hash different parts of the
`Unit`. I figured that this change helps to clarify intent so that even
if we don't change the definitions, this could still be worth it.

The last two I'm tracking as a `unit_id`.  As we evolve the first two
hashes, we can decide which would be a better fit for backing the
`unit_id`.
For scraping,  I could have treated this as
`-C extra-filename` but then we'd have a lot of `.expect()`s.

I moved the accessors from `CompilationFiles` to `MetaInfo` so we could
closely associate the documentation, API, and implementation. Making
`CompilationFiles::c_metadata` the main entry point that gets documented
would be weird because the hashing is associated with `MetaInfo`
(umbrella type, was private, now `Metadata`) or `Metadata` (agnostic of
each use, now `UnitHash`)

### How should we test and review this PR?

### Additional information
epage added a commit to epage/cargo that referenced this issue Nov 16, 2024
@epage
Copy link
Contributor

epage commented Nov 18, 2024

Terrible thought: run a regex on stderr to capture all -Cmetadata=<something> parameters and then compare those between runs.

epage added a commit to epage/cargo that referenced this issue Nov 20, 2024
…name

This unblocks experimenting with having these diverge for rust-lang#8716
epage added a commit to epage/cargo that referenced this issue Nov 20, 2024
…name

This unblocks experimenting with having these diverge for rust-lang#8716
epage added a commit to epage/cargo that referenced this issue Nov 21, 2024
…name

This unblocks experimenting with having these diverge for rust-lang#8716
github-merge-queue bot pushed a commit that referenced this issue Nov 21, 2024
…name (#14846)

### What does this PR try to resolve?

This unblocks experimenting with having these diverge for #8716

### How should we test and review this PR?

### Additional information
epage added a commit to epage/cargo that referenced this issue Nov 21, 2024
epage added a commit to epage/cargo that referenced this issue Nov 21, 2024
epage added a commit to epage/cargo that referenced this issue Nov 21, 2024
epage added a commit to epage/cargo that referenced this issue Nov 22, 2024
epage added a commit to epage/cargo that referenced this issue Nov 25, 2024
epage added a commit to epage/cargo that referenced this issue Nov 25, 2024
epage added a commit to epage/cargo that referenced this issue Nov 25, 2024
epage added a commit to epage/cargo that referenced this issue Nov 26, 2024
epage added a commit to epage/cargo that referenced this issue Nov 26, 2024
epage added a commit to epage/cargo that referenced this issue Nov 27, 2024
epage added a commit to epage/cargo that referenced this issue Dec 5, 2024
epage added a commit to epage/cargo that referenced this issue Dec 5, 2024
epage added a commit to epage/cargo that referenced this issue Dec 6, 2024
epage added a commit to epage/cargo that referenced this issue Dec 6, 2024
epage added a commit to epage/cargo that referenced this issue Dec 6, 2024
github-merge-queue bot pushed a commit that referenced this issue Dec 6, 2024
)

### What does this PR try to resolve?

Fixes #8716

This splits `-C metdata` and `-C extra-filename` and adds `RUSTFLAGS` to
`-C extra-filename` in the hope that we can still make PGO and
reproducible builds work while caching artifacts per RUSTFLAGS used.

### How should we test and review this PR?

### Additional information
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-rebuild-detection Area: rebuild detection and fingerprinting A-rustflags Area: rustflags E-hard Experience: Hard S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants