mirror of
https://github.com/simplex-chat/haskell.nix.git
synced 2026-06-03 09:17:32 +00:00
* Add a custom error message for a missing stack resolver * Make mkCabalProjectPkgSet robust to missing Hackage patches * Add error for component prefix lookup * Add a custom error for a missing GHC
98 lines
3.3 KiB
Nix
98 lines
3.3 KiB
Nix
{ lib, haskellLib }:
|
|
|
|
with haskellLib;
|
|
|
|
{
|
|
# Within the package components, these are the attribute names of
|
|
# nested attrsets.
|
|
subComponentTypes = [
|
|
"sublibs"
|
|
"foreignlibs"
|
|
"exes"
|
|
"tests"
|
|
"benchmarks"
|
|
];
|
|
|
|
foldrAttrVals = f: z: attrs:
|
|
lib.foldr (g: acc: g acc) z (lib.mapAttrsToList (_name: f) attrs);
|
|
|
|
foldComponents = tys: f: z: conf:
|
|
let
|
|
comps = conf.components or {};
|
|
# ensure that comps.library exists and is not null.
|
|
libComp = acc: if (comps.library or null) != null then f comps.library acc else acc;
|
|
subComps = acc:
|
|
lib.foldr
|
|
(ty: acc': foldrAttrVals f acc' (comps.${ty} or {}))
|
|
acc
|
|
tys;
|
|
in libComp (subComps z);
|
|
|
|
getAllComponents = foldComponents subComponentTypes (c: acc: [c] ++ acc) [];
|
|
|
|
componentPrefix = {
|
|
# Are all of these right?
|
|
sublibs = "lib";
|
|
foreignlibs = "foreignlib";
|
|
exes = "exe";
|
|
tests = "test";
|
|
benchmarks = "bench";
|
|
};
|
|
|
|
applyComponents = f: config:
|
|
let
|
|
comps = config.components;
|
|
applyLibrary = cname: f { cname = config.package.identifier.name; ctype = "lib"; };
|
|
applySubComp = ctype: cname: f { inherit cname; ctype = componentPrefix.${ctype} or (throw "Missing component mapping for ${ctype}."); };
|
|
applyAllComp = f { cname = config.package.identifier.name; ctype = "all"; };
|
|
libComp = if comps.library == null then {} else lib.mapAttrs applyLibrary (removeAttrs comps (subComponentTypes ++ [ "all" ]));
|
|
subComps = lib.mapAttrs
|
|
(ctype: lib.mapAttrs (applySubComp ctype))
|
|
(builtins.intersectAttrs (lib.genAttrs subComponentTypes (_: null)) comps);
|
|
allComp = { all = applyAllComp comps.all; };
|
|
in subComps // libComp // allComp;
|
|
|
|
isLibrary = componentId: componentId.ctype == "lib";
|
|
isAll = componentId: componentId.ctype == "all";
|
|
isTest = componentId: componentId.ctype == "test";
|
|
isBenchmark = componentId: componentId.ctype == "bench";
|
|
|
|
# Format a componentId as it should appear as a target on the
|
|
# command line of the setup script.
|
|
componentTarget = componentId:
|
|
if componentId.ctype == "all" then ""
|
|
else "${componentId.ctype}:${componentId.cname}";
|
|
|
|
# Remove null or empty values from an attrset.
|
|
optionalHooks = lib.filterAttrs (_: hook: hook != null && hook != "");
|
|
|
|
# Avoid pkgs.callPackage for now. It does a lot of nonsense with OOP
|
|
# style programming that we should avoid until we know we want it.
|
|
|
|
# weakCallPackage: call a function or (importable expression)
|
|
# with scope + args.
|
|
#
|
|
# weakCallPackage scope f args
|
|
# will call f (scope // args)
|
|
#
|
|
# weakCallpackage scope ./path args
|
|
# will call the expression at ./path with (scope // args)
|
|
#
|
|
weakCallPackage = scope: f: args:
|
|
let f' = if lib.isFunction f then f else import f;
|
|
args' = (builtins.intersectAttrs (builtins.functionArgs f') scope) // args;
|
|
in f' args';
|
|
|
|
# Collect all (transitive) Haskell library dependencies of a
|
|
# component.
|
|
## flatLibDepends :: Component -> [Package]
|
|
flatLibDepends = component:
|
|
let
|
|
makePairs = map (p: rec { key="${val}"; val=(p.components.library or p); });
|
|
closure = builtins.genericClosure {
|
|
startSet = makePairs component.depends;
|
|
operator = {val,...}: makePairs val.config.depends;
|
|
};
|
|
in map ({val,...}: val) closure;
|
|
}
|