GHC claims "compilation IS NOT required" but changes the .hi file when -fforce-recomp is used
I came across this while doing an incremental Hadrian build. The build log showed Hadrian attempted to recompile _build/stage0/compiler/build/RegAlloc/Linear/FreeRegs.hi
(which should output FreeRegs.o
and FreeRegs.hi
) but ghc simply claims "compilation IS NOT required". I then ran the same build command with -fforce-recomp
. Indeed FreeRegs.o
did not change, but FreeRegs.hi
did change! Here is the diff of FreeRegs.hi
before and after recompiling:
--- .../quickest_bfccd83278_clean/stage0/compiler/build/RegAlloc/Linear/FreeRegs.hi
+++ .../quickest_bfccd83278_incremental/stage0/compiler/build/RegAlloc/Linear/FreeRegs.hi
@@ -5,7 +5,7 @@
Way: Wanted [],
got []
interface RegAlloc.Linear.FreeRegs 8061
- interface hash: 44bcaf4a3b059b4973052b1bb40cfabe
+ interface hash: d07c1bca2cdccecfeb85e16d7a2ed7b2
ABI hash: cd601d548e70a39688a3a77e2ce482ac
export-list hash: 5447bdeacdb0192ac15216eb469001ca
orphan hash: 693e9af84d3dfcc71e640e005bdc5e2e
@@ -71,7 +71,7 @@
targetPlatform c93a28a2281286116b600ff2b699de82
import -/ GhcPrelude ccef3113c4534e009f25aa27f5682afe
exports: 55e5e86352162a4a65ad11ff340ab1fa
-import -/ PPC.Instr d50cae8643502ef198f4bfdb4bb0e501
+import -/ PPC.Instr 5ac93afc68bde2807df6aa6277c9d122
exports: 3a172344ba26f894a67768f4f144baed
maxSpillSlots 1574cd53026842ee42871eec27264bab
import -/ Panic 4b46ba8b84ff5091b8a99ff61b9a3e5f
Expected Behavior
I expected ghc not to claim "compilation IS NOT required", and instead recompile or at least update the .hi file.
Notes/Questions
- My guess is that ghc has correctly decided that the output .o will not change, but has not accounted for the .hi file changing, so does not update it.
- The
PPC.Instr
hash has changed, but thePPC.Instr exports:
hash has not. This means the recompilation checker is likely ignoring the prior. - Perhaps I'm mistaken and there is a valid reason to keep the old .hi file.
Recreation steps
I haven't distilled a simpler case yet. I discovered this while comparing build trees of clean and incremental hadrian builds. To recreate:
# Clear build directory
$ rm -rf _build
# Checkout Commit and do an initial build (keep the hadrian directory locked to 114b014f7e)
$ git checkout 0c6f7f7eb9
$ git checkout 114b014f7e -- hadrian
$ git submodule update --init
$ ./hadrian/build.sh -j -c
# Change some files by checking out another commit and do an incremental build (keep the hadrian directory locked to 114b014f7e)
$ git checkout bfccd83278
$ git checkout 114b014f7e -- hadrian
$ git submodule update --init
$ (./hadrian/build.sh -j -c --verbose 2>&1) | less
# ^^^ make sure to take note of the command, XXX, used to recompile stage0/compiler/build/RegAlloc/Linear/FreeRegs.o
# Copy files for later diffing
$ cp stage0/compiler/build/RegAlloc/Linear/FreeRegs.hi ./FreeRegs.hi_a
$ cp stage0/compiler/build/RegAlloc/Linear/FreeRegs.o ./FreeRegs.o_a
$ XXX
compilation IS NOT required
$ XXX -fforce-recomp
$ cp stage0/compiler/build/RegAlloc/Linear/FreeRegs.hi ./FreeRegs.hi_b
$ cp stage0/compiler/build/RegAlloc/Linear/FreeRegs.o ./FreeRegs.o_b
# See that .o files are the same
$ diff ./FreeRegs.o_a ./FreeRegs.o_b
# But the hi files differ.
$ diff -u --label a <(ghc --show-iface ./FreeRegs.hi_a) --label b <(ghc --show-iface ./FreeRegs.hi_b)