fix(build): rewrite ActualTypes hub with explicit T(..) re-exports
Some checks failed
Build and Deploy / build-push-deploy (push) Has been cancelled

Previous attempt (stubs + direct imports) broke qualified constructor
references like Generated.ActualTypes.WidgetVersion in Include files —
removing the hub from scope invalidated all qualified names through it.

New approach: rewrite Generated.ActualTypes.hs in postUnpack to replace
the `module M` export list with explicit T(..) re-exports. Explicit
re-exports store only name references in the .hi file (compact), while
`module M` embeds the full sub-interface (~287 MB for 61 modules). Hub
stays functional — consumers still qualify via Generated.ActualTypes.

Also deduplicate with sort -u in case PrimaryKeys and entity files both
declare the same ID type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 23:04:57 +02:00
parent fba86d845f
commit 1bdbce96e6

View File

@@ -100,10 +100,11 @@
# pkgs.ghc = haskellPackages.override { overrides = ihpOverrides }.
# 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).
# For inter-hub-models: stub Generated.ActualTypes + Generated.Types to
# empty modules; patch every importer with direct sub-module imports.
# For inter-hub-lib: same for both hubs (originals still intact in its
# sourceRoot — each package is unpacked independently).
# For inter-hub-models: rewrite ActualTypes.hs export list from (module N)
# syntax to explicit T(..) re-exports — keeps hub functional for qualified
# references (Generated.ActualTypes.T) while producing compact .hi.
# Generated.Types stubbed; inter-hub-lib replaces its import with direct
# entity imports (sourceRoot is per-package, originals intact there).
overlays = lib.mkAfter [
(final: prev: {
ghc = prev.ghc.extend (hfinal: hprev: {
@@ -113,9 +114,13 @@
then drv.overrideAttrs (old: {
# GHC 9.10.3 crash: `module M` re-export syntax in Generated.ActualTypes
# embeds 61 full sub-interfaces into ActualTypes.hi (~287 MB), exceeding
# GHC's 274 MB binary read limit. Fix: stub both hub files to empty
# modules (tiny .hi), patch every importer to use direct sub-module
# imports (same semantics, no embedded sub-interfaces in .hi).
# GHC's 274 MB binary read limit.
#
# Fix: rewrite the hub's export list from `module M` syntax to explicit
# T(..) re-exports. Explicit re-exports store only name references in
# the .hi file (compact); `module M` embeds the full sub-interface.
# Hub stays functional (consumers still qualify via Generated.ActualTypes),
# but .hi stays small.
configureFlags = (old.configureFlags or []) ++ [
"--ghc-option=-O0"
"--ghc-option=-fomit-interface-pragmas"
@@ -123,36 +128,38 @@
postUnpack = (old.postUnpack or "") + ''
_actual="$sourceRoot/build/Generated/ActualTypes.hs"
# Collect direct sub-module imports before stubbing the hub
_act_imp=$(mktemp)
awk '/^import Generated\./{print}' "$_actual" > "$_act_imp"
# Rewrite hub export list: (module N, ...) (T(..), ...)
# Extract all data/newtype names from inner module files.
_types=$(
{
awk '/^data [A-Z]|^newtype [A-Z]/{print $2"(..)"}' \
"$sourceRoot/build/Generated/Enums.hs"
find "$sourceRoot/build/Generated/ActualTypes" -name "*.hs" | \
sort | while IFS= read -r _m; do
awk '/^data [A-Z]|^newtype [A-Z]/{print $2"(..)"}' "$_m"
done
} | sort -u
)
_exports=$(echo "$_types" | \
awk 'NR==1{printf " %s", $0; next} {printf "\n , %s", $0} END{printf "\n"}')
_imports=$(awk '/^import Generated\./{print}' "$_actual")
{
printf 'module Generated.ActualTypes\n ( %s ) where\n' "$_exports"
printf '%s\n' "$_imports"
} > "$_actual.new" && mv "$_actual.new" "$_actual"
# Stub both re-export hubs empty modules tiny .hi files
printf '%s\n' 'module Generated.ActualTypes () where' > "$_actual"
# Stub Generated.Types (inter-hub-lib reads original from its sourceRoot)
printf '%s\n' 'module Generated.Types () where' \
> "$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"
then drv.overrideAttrs (old: {
# Both Generated.Types and Generated.ActualTypes are empty stubs in
# models. Replace every bare import with direct sub-module imports,
# reading the originals from this package's own sourceRoot (each
# package is unpacked independently, so originals are intact here).
# Generated.Types is an empty stub in models — hub removed to avoid
# module M re-export crash. Replace every bare `import Generated.Types`
# with direct imports of the 119 individual entity modules.
# Generated.ActualTypes hub is still functional (explicit T(..) exports),
# so no patching needed for ActualTypes imports in this package.
postUnpack = (old.postUnpack or "") + ''
_types="$sourceRoot/build/Generated/Types.hs"
_imp=$(mktemp)
@@ -169,22 +176,6 @@
fi
done
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;