Recompilation across crates in workspace when there is a proc-macro dependency #15382
Labels
A-proc-macro
Area: compiling proc-macros
A-rebuild-detection
Area: rebuild detection and fingerprinting
C-bug
Category: bug
S-triage
Status: This issue is waiting on initial triage.
Problem
Hi,
I am attempting to get "hot reloading" working for a project, however a shared dependency that seemingly does not need to be recompiled is being recompiled. My project makes use of Bevy ECS, and the shared dependency is my "components" crate (components is an ECS term), which I do not which to be recompiled as this modifies the TypeId values of the structs contained within, confusing Bevy.
I've simplified down the project into the following hierarchy, and a link to this project can be found in the "steps" section of this issue:
In reality, "common" is bevy_reflect_derive - a proc-macro crate that is a dependency of a dependency, and thus I don't have much control over it. I've made "common" a proc-macro crate in my example.
"fnv" can be any crate as far as I'm aware, as long as it is present in both "common" and "game_bin". In reality for me it's the uuid crate, however I'm using fnv for this example as it is very simple, with no dependencies, to keep debugging easier.
If I compile
game_bin
and thenhot
, the dependencies are recompiled. Example output from cargo:If I look into the target/debug/.fingerprint directory I see duplicates of common, components and fnv. And if I run game_bin and a separate process that loads hot.dll and calls the exported function I get different TypeId values for each (I can provide a script to do this if required, but I don't think it'll be useful as we can just look at the presence of fingerprint files to determine if something was recompiled).
If I remove "fnv" from either game_bin or common, or make
common
no longer proc-macro, then nothing is recompiled:Steps
Possible Solution(s)
No response
Notes
To dig into the issue, I first set
CARGO_LOG="cargo::core::compiler::fingerprint=trace"
. Here's what is logged during thecargo b -p hot
call.I expected to see a fingerprint "DirtyReason" message - and in fact I did see a UnitDependencyInfoChanged message previously in a larger not-as-simplified example project, but not any longer. Perhaps that means it was a red herring?
Regardless, I attempted to see why different fingerprints were created. I'm not at all familiar with cargo's code, but I hacked in some code to print the various parts that make up the fingerprint.
It all came down to the
unit.profile
component of profile_hash:cargo/src/cargo/core/compiler/fingerprint/mod.rs
Line 1534 in adf9b6a
And breaking it down further, the only change was to
debuginfo
for "fnv". For game_bin it'sResolved(Full)
, and for hot it'sResolved(None)
. If I removeproc-macro=true
from common, then both areResolved(Full)
.Furthermore, it seems that the addition of
proc-macro=true
causescommon
to beResolved(None)
. I don't believe this causes the issue as it's the same for both game_bin and hot, but it's notable how it's different from the removed proc-macro version.That's as far as I've looked. I'm not sure what determines these profiles, or whether there's a way to work around this.
I am aware that if I run
cargo b -p game_bin -p hot
then everything is compiled together, but for my original purposes game_bin will be executing at the time I run that command, as I'm only interested in recompiling "hot" for the purposes of hot reloading.Version
The text was updated successfully, but these errors were encountered: