generated from coulomb/repo-seed
fix(build): stub ActualTypes hub + patch importers to avoid 274 MB .hi crash
Some checks failed
Build and Deploy / build-push-deploy (push) Has been cancelled
Some checks failed
Build and Deploy / build-push-deploy (push) Has been cancelled
Generated.ActualTypes uses `module M` re-export syntax for 61 sub-modules; GHC 9.10.3 embeds all 61 full sub-interfaces into ActualTypes.hi (~287 MB), hitting the binary-deserialization limit at position 287686318. Revert Cabal sub-library split (did not help — models-inner also crashed with only 61 modules at the same invariant position). Apply the same fix already working for Generated.Types in inter-hub-lib: - inter-hub-models postUnpack: stub Generated.ActualTypes.hs + Generated.Types.hs to empty modules; patch every importer with direct sub-module imports (reads original ActualTypes.hs before stubbing to build the replacement import list) - inter-hub-lib postUnpack: same for both hubs (each package has its own sourceRoot with originals intact) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
205
flake.nix
205
flake.nix
@@ -91,18 +91,19 @@
|
|||||||
# PostgreSQL extensions
|
# PostgreSQL extensions
|
||||||
# services.postgres.extensions = extensions: [ extensions.postgis ];
|
# services.postgres.extensions = extensions: [ extensions.postgis ];
|
||||||
|
|
||||||
# GHC 9.10.3 crash fix: Generated.Types imports 119 modules, exceeding
|
# GHC 9.10.3 crash fix: Generated.ActualTypes uses `module M` re-export
|
||||||
# the ~287 MB interface-file binary-deserialization limit.
|
# syntax for 61 sub-modules; the resulting ActualTypes.hi exceeds GHC's
|
||||||
|
# ~274 MB binary-deserialization limit (crash at position 287686318).
|
||||||
#
|
#
|
||||||
# pkgs is built from `import nixpkgs { overlays = devenv.shells.default.overlays; }`.
|
# pkgs is built from `import nixpkgs { overlays = devenv.shells.default.overlays; }`.
|
||||||
# IHP adds ihp.overlays.default to this list, which sets
|
# IHP adds ihp.overlays.default to this list, which sets
|
||||||
# pkgs.ghc = haskellPackages.override { overrides = ihpOverrides }.
|
# pkgs.ghc = haskellPackages.override { overrides = ihpOverrides }.
|
||||||
# We extend pkgs.ghc with a mkDerivation override (lib.mkAfter ensures
|
# We extend pkgs.ghc with a mkDerivation override (lib.mkAfter ensures
|
||||||
# we run after IHP's overlay, so prev.ghc is already IHP's package set).
|
# we run after IHP's overlay, so prev.ghc is already IHP's package set).
|
||||||
# 2-way split (60 entities) still crashes — TypesPart1.hi itself hits 287 MB.
|
# For inter-hub-models: stub Generated.ActualTypes + Generated.Types to
|
||||||
# 4-way split (~30 entities, ~150 MB .hi each) stays safely under the limit.
|
# empty modules; patch every importer with direct sub-module imports.
|
||||||
# When pname == "inter-hub-models", postUnpack replaces the monolithic
|
# For inter-hub-lib: same for both hubs (originals still intact in its
|
||||||
# Types.hs → empty stub (not compiled); inter-hub-lib imports TypesPart1-8 directly.
|
# sourceRoot — each package is unpacked independently).
|
||||||
overlays = lib.mkAfter [
|
overlays = lib.mkAfter [
|
||||||
(final: prev: {
|
(final: prev: {
|
||||||
ghc = prev.ghc.extend (hfinal: hprev: {
|
ghc = prev.ghc.extend (hfinal: hprev: {
|
||||||
@@ -110,166 +111,48 @@
|
|||||||
let drv = hprev.mkDerivation args;
|
let drv = hprev.mkDerivation args;
|
||||||
in if (args.pname or "") == "inter-hub-models"
|
in if (args.pname or "") == "inter-hub-models"
|
||||||
then drv.overrideAttrs (old: {
|
then drv.overrideAttrs (old: {
|
||||||
# GHC 9.10.3 crash: Data.Binary.Get.runGet at position 287686318.
|
# GHC 9.10.3 crash: `module M` re-export syntax in Generated.ActualTypes
|
||||||
# Invariant regardless of flags. Workaround: split the 476-module
|
# embeds 61 full sub-interfaces into ActualTypes.hi (~287 MB), exceeding
|
||||||
# inter-hub-models into two Cabal library components so GHC runs
|
# GHC's 274 MB binary read limit. Fix: stub both hub files to empty
|
||||||
# two separate --make invocations instead of one giant one.
|
# modules (tiny .hi), patch every importer to use direct sub-module
|
||||||
#
|
# imports (same semantics, no embedded sub-interfaces in .hi).
|
||||||
# models-inner (~63 modules): Generated.ActualTypes.* + Enums.
|
|
||||||
# Pure type definitions; no inter-hub-models deps.
|
|
||||||
# main library (~413 modules): entity ops + Include instances.
|
|
||||||
# Depends on models-inner.
|
|
||||||
#
|
|
||||||
# Long-term intent: explicit module boundaries reduce build cost,
|
|
||||||
# isolate changes, and make diagnostics cheaper across the board.
|
|
||||||
configureFlags = (old.configureFlags or []) ++ [
|
configureFlags = (old.configureFlags or []) ++ [
|
||||||
"--ghc-option=-O0"
|
"--ghc-option=-O0"
|
||||||
"--ghc-option=-fomit-interface-pragmas"
|
"--ghc-option=-fomit-interface-pragmas"
|
||||||
];
|
];
|
||||||
postUnpack = (old.postUnpack or "") + ''
|
postUnpack = (old.postUnpack or "") + ''
|
||||||
_cabal=$(ls "$sourceRoot"/*.cabal | head -1)
|
_actual="$sourceRoot/build/Generated/ActualTypes.hs"
|
||||||
_pname=$(grep '^name:' "$_cabal" | awk '{print $2}')
|
|
||||||
|
|
||||||
# Classify exposed-modules into inner vs outer.
|
# Collect direct sub-module imports before stubbing the hub
|
||||||
# Inner: Generated.ActualTypes.X (capital X) and Generated.Enums
|
_act_imp=$(mktemp)
|
||||||
# — these have zero inter-hub-models dependencies.
|
awk '/^import Generated\./{print}' "$_actual" > "$_act_imp"
|
||||||
# Outer: everything else except Generated.Types (empty stub).
|
|
||||||
_inner=$(awk '
|
|
||||||
/^ exposed-modules:/{e=1;next}
|
|
||||||
e && /^ /{m=$1;
|
|
||||||
if (m~/^Generated\.ActualTypes\.[A-Z]/||m=="Generated.Enums")
|
|
||||||
print m;
|
|
||||||
next}
|
|
||||||
e{e=0}
|
|
||||||
' "$_cabal")
|
|
||||||
_outer=$(awk '
|
|
||||||
/^ exposed-modules:/{e=1;next}
|
|
||||||
e && /^ /{m=$1;
|
|
||||||
if (!(m~/^Generated\.ActualTypes\.[A-Z]/) &&
|
|
||||||
m!="Generated.Enums" && m!="Generated.Types")
|
|
||||||
print m;
|
|
||||||
next}
|
|
||||||
e{e=0}
|
|
||||||
' "$_cabal")
|
|
||||||
|
|
||||||
# Rewrite the cabal file with two library stanzas.
|
# Stub both re-export hubs → empty modules → tiny .hi files
|
||||||
# Hard-coded deps/extensions match IHP default.nix template
|
printf '%s\n' 'module Generated.ActualTypes () where' > "$_actual"
|
||||||
# (pinned flake — these won't drift without a flake update).
|
|
||||||
cat > "$_cabal" <<CABAL_EOF
|
|
||||||
cabal-version: 3.0
|
|
||||||
name: $_pname
|
|
||||||
version: 0.1.0
|
|
||||||
build-type: Simple
|
|
||||||
|
|
||||||
library models-inner
|
|
||||||
default-language: GHC2021
|
|
||||||
hs-source-dirs: build
|
|
||||||
build-depends:
|
|
||||||
base
|
|
||||||
, ihp
|
|
||||||
, basic-prelude
|
|
||||||
, text
|
|
||||||
, bytestring
|
|
||||||
, time
|
|
||||||
, uuid
|
|
||||||
, aeson
|
|
||||||
, postgresql-simple
|
|
||||||
, deepseq
|
|
||||||
, data-default
|
|
||||||
, scientific
|
|
||||||
, string-conversions
|
|
||||||
, hasql
|
|
||||||
, hasql-dynamic-statements
|
|
||||||
, hasql-implicits
|
|
||||||
, hasql-mapping
|
|
||||||
, hasql-postgresql-types
|
|
||||||
, hasql-pool
|
|
||||||
, unordered-containers
|
|
||||||
, postgresql-types
|
|
||||||
exposed-modules:
|
|
||||||
$(echo "$_inner" | sed 's/^/ /')
|
|
||||||
default-extensions:
|
|
||||||
OverloadedStrings
|
|
||||||
NoImplicitPrelude
|
|
||||||
ImplicitParams
|
|
||||||
TypeSynonymInstances
|
|
||||||
FlexibleInstances
|
|
||||||
FlexibleContexts
|
|
||||||
InstanceSigs
|
|
||||||
MultiParamTypeClasses
|
|
||||||
TypeFamilies
|
|
||||||
DataKinds
|
|
||||||
TypeOperators
|
|
||||||
UndecidableInstances
|
|
||||||
ConstraintKinds
|
|
||||||
StandaloneDeriving
|
|
||||||
DuplicateRecordFields
|
|
||||||
OverloadedLabels
|
|
||||||
OverloadedRecordDot
|
|
||||||
ghc-options: -Wno-unused-imports -Wno-dodgy-imports -Wno-unused-matches
|
|
||||||
|
|
||||||
library
|
|
||||||
default-language: GHC2021
|
|
||||||
hs-source-dirs: build
|
|
||||||
build-depends:
|
|
||||||
$_pname:models-inner
|
|
||||||
, base
|
|
||||||
, ihp
|
|
||||||
, basic-prelude
|
|
||||||
, text
|
|
||||||
, bytestring
|
|
||||||
, time
|
|
||||||
, uuid
|
|
||||||
, aeson
|
|
||||||
, postgresql-simple
|
|
||||||
, deepseq
|
|
||||||
, data-default
|
|
||||||
, scientific
|
|
||||||
, string-conversions
|
|
||||||
, hasql
|
|
||||||
, hasql-dynamic-statements
|
|
||||||
, hasql-implicits
|
|
||||||
, hasql-mapping
|
|
||||||
, hasql-postgresql-types
|
|
||||||
, hasql-pool
|
|
||||||
, unordered-containers
|
|
||||||
, postgresql-types
|
|
||||||
exposed-modules:
|
|
||||||
$(echo "$_outer" | sed 's/^/ /')
|
|
||||||
default-extensions:
|
|
||||||
OverloadedStrings
|
|
||||||
NoImplicitPrelude
|
|
||||||
ImplicitParams
|
|
||||||
TypeSynonymInstances
|
|
||||||
FlexibleInstances
|
|
||||||
FlexibleContexts
|
|
||||||
InstanceSigs
|
|
||||||
MultiParamTypeClasses
|
|
||||||
TypeFamilies
|
|
||||||
DataKinds
|
|
||||||
TypeOperators
|
|
||||||
UndecidableInstances
|
|
||||||
ConstraintKinds
|
|
||||||
StandaloneDeriving
|
|
||||||
DuplicateRecordFields
|
|
||||||
OverloadedLabels
|
|
||||||
OverloadedRecordDot
|
|
||||||
ghc-options: -Wno-unused-imports -Wno-dodgy-imports -Wno-unused-matches
|
|
||||||
CABAL_EOF
|
|
||||||
|
|
||||||
# Stub out Generated.Types (kept as file for inter-hub-lib)
|
|
||||||
printf '%s\n' 'module Generated.Types () where' \
|
printf '%s\n' 'module Generated.Types () where' \
|
||||||
> "$sourceRoot/build/Generated/Types.hs"
|
> "$sourceRoot/build/Generated/Types.hs"
|
||||||
|
|
||||||
|
# Patch every entity file that imports the hub → direct imports
|
||||||
|
find "$sourceRoot/build" -name "*.hs" | while IFS= read -r _f; do
|
||||||
|
if grep -qE "^import Generated\.ActualTypes$" "$_f"; then
|
||||||
|
awk -v imp="$_act_imp" '
|
||||||
|
/^import Generated\.ActualTypes$/{
|
||||||
|
while ((getline ln < imp) > 0) print ln
|
||||||
|
close(imp)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{ print }' "$_f" > "$_f.new" && mv "$_f.new" "$_f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
rm -f "$_act_imp"
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
else if (args.pname or "") == "inter-hub-lib"
|
else if (args.pname or "") == "inter-hub-lib"
|
||||||
then drv.overrideAttrs (old: {
|
then drv.overrideAttrs (old: {
|
||||||
# Generated.Types is an empty stub in models — no re-export hub.
|
# Both Generated.Types and Generated.ActualTypes are empty stubs in
|
||||||
# Replace every bare `import Generated.Types` with direct imports
|
# models. Replace every bare import with direct sub-module imports,
|
||||||
# of all 119 individual entity modules (read from the original
|
# reading the originals from this package's own sourceRoot (each
|
||||||
# Generated/Types.hs before it was replaced in models postUnpack —
|
# package is unpacked independently, so originals are intact here).
|
||||||
# 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 "") + ''
|
postUnpack = (old.postUnpack or "") + ''
|
||||||
_types="$sourceRoot/build/Generated/Types.hs"
|
_types="$sourceRoot/build/Generated/Types.hs"
|
||||||
_imp=$(mktemp)
|
_imp=$(mktemp)
|
||||||
@@ -286,6 +169,22 @@ CABAL_EOF
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
rm -f "$_imp"
|
rm -f "$_imp"
|
||||||
|
|
||||||
|
_actual="$sourceRoot/build/Generated/ActualTypes.hs"
|
||||||
|
_act_imp=$(mktemp)
|
||||||
|
awk '/^import Generated\./{print}' "$_actual" > "$_act_imp"
|
||||||
|
find "$sourceRoot" -name "*.hs" | while IFS= read -r _f; do
|
||||||
|
if grep -qE "^import Generated\.ActualTypes$" "$_f"; then
|
||||||
|
awk -v imp="$_act_imp" '
|
||||||
|
/^import Generated\.ActualTypes$/{
|
||||||
|
while ((getline ln < imp) > 0) print ln
|
||||||
|
close(imp)
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{ print }' "$_f" > "$_f.new" && mv "$_f.new" "$_f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
rm -f "$_act_imp"
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
else drv;
|
else drv;
|
||||||
|
|||||||
Reference in New Issue
Block a user