Skip to content

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 the PPC.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)
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information