diff --git a/flake.nix b/flake.nix index 770381b..b6cc99f 100644 --- a/flake.nix +++ b/flake.nix @@ -110,74 +110,68 @@ let drv = hprev.mkDerivation args; in if (args.pname or "") == "inter-hub-models" then drv.overrideAttrs (old: { - # 8-way split: ~15 entities per TypesPart → ~144 MB .hi each. - # Root cause: any re-export hub for 119 IHP entities produces - # a .hi file ≥ 287 MB (the GHC 9.10.3 Data.Binary.Get limit). - # Generated.Types is replaced with an empty stub and removed - # from exposed-modules; inter-hub-lib imports TypesPart1-8 directly. - # -O0 strips unfoldings/specialisations for additional size reduction. - configureFlags = (old.configureFlags or []) ++ [ "--ghc-option=-O0" ]; + # Root cause: "module M" re-export syntax in IHP-generated hubs + # causes GHC to embed the FULL interface of M into the hub's .hi. + # Generated.ActualTypes uses "module M" for 61 sub-modules; the + # resulting ActualTypes.hi hits the GHC 9.10.3 Data.Binary.Get + # 274 MB limit (crashes at position 287686318: not enough bytes) + # when WidgetVersionInclude reads it back. Same pattern applied to + # Generated.Types (119 entity re-exports) — made into empty stub + # with direct imports in inter-hub-lib instead. + # Fix for ActualTypes: remove the explicit (module M, ...) export + # list so GHC stores compact name-reference entries in the .hi. + configureFlags = (old.configureFlags or []) ++ [ + "--ghc-option=-O0" + "--ghc-option=-fomit-interface-pragmas" + ]; postUnpack = (old.postUnpack or "") + '' + # Strip "module M" re-export syntax from Generated.ActualTypes. + # With 61 "module M" entries GHC embeds every sub-interface + # into ActualTypes.hi, producing a file that hits the GHC 9.10.3 + # Data.Binary.Get 274 MB limit (crashes at position 287686318) + # when WidgetVersionInclude reads it. Removing the explicit + # export list keeps the module semantically identical (all + # imports are still re-exported) but forces GHC to use + # compact name-reference entries instead of embedded copies. + _actual="$sourceRoot/build/Generated/ActualTypes.hs" + awk '/^module Generated\.ActualTypes /{print "module Generated.ActualTypes where"; next} {print}' \ + "$_actual" > "$_actual.new" && mv "$_actual.new" "$_actual" + _types="$sourceRoot/build/Generated/Types.hs" - - # Create TypesPart1-8: 8-way split, ~15 entities each, ~144 MB .hi - for _k in 1 2 3 4 5 6 7 8; do - awk -v K=$_k 'BEGIN{n=0; N=8} - /^import Generated\./{n++; mods[n]=$2} - END{ - q_prev = (K==1) ? 0 : int((K-1)*n/N)+1 - q_curr = (K==N) ? n : int(K*n/N)+1 - s = q_prev+1; e = q_curr - print "module Generated.TypesPart" K " (" - for(i=s;i<=e;i++){ - if(i "$sourceRoot/build/Generated/TypesPart''${_k}.hs" - done - - # Empty stub: Generated.Types is NOT a re-export hub. - # Re-exporting all 119 entities would produce ~1.1 GB .hi, - # crashing GHC when any downstream module reads it. - # inter-hub-lib imports TypesPart1-8 directly instead. printf '%s\n' 'module Generated.Types () where' > "$_types" - # Update cabal: add TypesPart1-8, remove bare Generated.Types - # (empty stub is kept as a file but not exposed/compiled). - # 8-space indent required — 4-space is a new stanza field. + # Remove Generated.Types from exposed-modules: + # reduces HPT entry count by 1 (476 instead of 477). _cabal=$(ls "$sourceRoot"/*.cabal | head -1) - if ! grep -q 'Generated\.TypesPart1' "$_cabal"; then - awk '/Generated\.Types$/ && !/TypesPart/{next} - /^ exposed-modules:/{ - print " ghc-options: -O0" - print; next - } - /Generated\.LearningInsightInclude/{ - print - for(k=1;k<=8;k++) print " Generated.TypesPart" k - next - } - {print}' "$_cabal" > "$_cabal.new" - mv "$_cabal.new" "$_cabal" - fi + awk '/Generated\.Types$/ && !/TypesPart/{next} {print}' \ + "$_cabal" > "$_cabal.new" + mv "$_cabal.new" "$_cabal" ''; }) else if (args.pname or "") == "inter-hub-lib" then drv.overrideAttrs (old: { - # Generated.Types is an empty stub in models (no re-export hub). - # Replace every bare `import Generated.Types` with 8 TypesPart imports - # so app modules get all entity types without touching a huge .hi file. + # Generated.Types is an empty stub in models — no re-export hub. + # Replace every bare `import Generated.Types` with direct imports + # of all 119 individual entity modules (read from the original + # Generated/Types.hs before it was replaced in models postUnpack — + # each package gets its own unpacked sourceRoot, so Types.hs is + # still intact here). Individual entity .hi files are ~9 MB each. postUnpack = (old.postUnpack or "") + '' - find "$sourceRoot" -name "*.hs" | while read _f; do + _types="$sourceRoot/build/Generated/Types.hs" + _imp=$(mktemp) + awk '/^import Generated\./{print "import " $2}' "$_types" > "$_imp" + find "$sourceRoot" -name "*.hs" | while IFS= read -r _f; do if grep -qE "^import Generated\.Types$" "$_f"; then - awk '/^import Generated\.Types$/{ - for(k=1;k<=8;k++) print "import Generated.TypesPart" k + awk -v imp="$_imp" ' + /^import Generated\.Types$/{ + while ((getline ln < imp) > 0) print ln + close(imp) next - }{print}' "$_f" > "$_f.new" && mv "$_f.new" "$_f" + } + { print }' "$_f" > "$_f.new" && mv "$_f.new" "$_f" fi done + rm -f "$_imp" ''; }) else drv;