1
1
mirror of https://github.com/nmattia/snack.git synced 2024-11-28 12:27:41 +03:00
snack/snack-lib/hpack.nix
2019-02-27 21:47:51 +01:00

107 lines
3.7 KiB
Nix

{ lib
, glibcLocales
, callPackage
, writeText
, runCommand
, haskellPackages
, pkgDescriptionsFromPath
}:
with (callPackage ./lib.nix {});
with (callPackage ./modules.nix {});
with (callPackage ./package-spec.nix {});
let
y2j = runCommand "yaml2json"
{ buildInputs =
[ (haskellPackages.ghcWithPackages (ps: [ ps.aeson ps.yaml ])) glibcLocales ];
}
"ghc ${./YamlToJson.hs} -o $out";
fromYAML = text:
let json =
builtins.readFile (runCommand "y2j"
{ buildInputs = [ glibcLocales ]; }
"${y2j} ${writeText "y2j" text} > $out"
);
in builtins.fromJSON json;
in rec
{
pkgDescriptionsFromHPack = packageYaml:
let
package = fromYAML (builtins.readFile packageYaml);
base = builtins.dirOf packageYaml;
commonAttrs = component:
{ ghcOpts = topGhcOpts ++ (optAttr component "ghc-options" []);
extensions = topExtensions ++ (optAttr component "extensions" []);
src =
with { source-dirs = optAttr component "source-dirs" "."; };
if builtins.isList source-dirs
then builtins.map (sourceDir:
builtins.toPath "${builtins.toString base}/${sourceDir}"
) source-dirs
else
builtins.toPath "${builtins.toString base}/${source-dirs}";
};
# Snack drops the version bounds because here it has no meaning
dropVersionBounds =
map (x: lib.lists.head (lib.strings.splitString " " x));
mkDeps = obj: dropVersionBounds (optAttr obj "dependencies" []);
topDeps = mkDeps package;
topExtensions = optAttr package "default-extensions" [];
topGhcOpts = optAttr package "ghc-options" [];
libs = withAttr package "library" [] (component:
[ (commonAttrs component //
{ dependencies = topDeps ++ mkDeps component; }
)
]
);
exes =
withAttr package "executables" [] (lib.mapAttrsToList (k: v: mkExe k v)) ++
withAttr package "executable" [] (comp: [(mkExe package.name comp)] );
mkExe = nn: component:
with
{
depsAndPacks = lib.foldl
(acc: x:
if x == package.name then tap acc "packs" (ps: ps ++ libs)
else if lib.hasPrefix "./" x
then tap acc "packs" (ps:
ps ++
[
(lib.findSingle (x: ! (builtins.hasAttr "main" x))
(abort "Couldn't find library")
(abort "Found multiple libraries")
( pkgDescriptionsFromPath
"${builtins.toString base}/${x}"
)
)
]
)
else if lib.hasPrefix "/" x
then tap acc "packs" (ps:
ps ++
[
(lib.findSingle (x: ! (builtins.hasAttr "main" x))
(abort "Couldn't find library")
(abort "Found multiple libraries")
( pkgDescriptionsFromPath "${builtins.toString x}" )
)
]
)
else tap acc "deps" (ds: ds ++ [x])
) { deps = []; packs = []; } (optAttr component "dependencies" []);
};
commonAttrs component //
{ main = fileToModule component.main;
name = nn;
dependencies = topDeps ++ dropVersionBounds depsAndPacks.deps;
packages = depsAndPacks.packs;
};
in exes ++ libs;
}