mirror of
https://github.com/nmattia/snack.git
synced 2024-09-11 11:55:36 +03:00
Support extra packages in yaml
This commit is contained in:
parent
e8cef886cf
commit
f09f33fed4
@ -20,7 +20,7 @@ let
|
|||||||
"${y2j} ${writeText "y2j" text} > $out"
|
"${y2j} ${writeText "y2j" text} > $out"
|
||||||
);
|
);
|
||||||
in builtins.fromJSON json;
|
in builtins.fromJSON json;
|
||||||
in
|
in rec
|
||||||
{
|
{
|
||||||
# Returns an attribute set with two fields:
|
# Returns an attribute set with two fields:
|
||||||
# - library: a package spec
|
# - library: a package spec
|
||||||
@ -28,6 +28,19 @@ in
|
|||||||
pkgSpecsFromHPack = packageYaml:
|
pkgSpecsFromHPack = packageYaml:
|
||||||
let
|
let
|
||||||
package = fromYAML (builtins.readFile packageYaml);
|
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
|
# Snack drops the version bounds because here it has no meaning
|
||||||
dropVersionBounds =
|
dropVersionBounds =
|
||||||
@ -37,51 +50,43 @@ in
|
|||||||
topExtensions = optAttr package "default-extensions" [];
|
topExtensions = optAttr package "default-extensions" [];
|
||||||
topGhcOpts = optAttr package "ghc-options" [];
|
topGhcOpts = optAttr package "ghc-options" [];
|
||||||
libs = withAttr package "library" [] (component:
|
libs = withAttr package "library" [] (component:
|
||||||
[{
|
[ (commonAttrs component //
|
||||||
src =
|
{ dependencies = topDeps ++ mkDeps component; }
|
||||||
let
|
)
|
||||||
base = builtins.dirOf packageYaml;
|
]
|
||||||
source-dirs = optAttr component "source-dirs" ".";
|
|
||||||
in
|
|
||||||
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}";
|
|
||||||
dependencies = topDeps ++ mkDeps component;
|
|
||||||
extensions = topExtensions ++ (optAttr component "extensions" []);
|
|
||||||
ghcOpts = topGhcOpts ++ (optAttr component "ghc-options" []);
|
|
||||||
}]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
exes =
|
exes =
|
||||||
withAttr package "executables" [] (lib.mapAttrsToList (k: v: mkExe k v)) ++
|
withAttr package "executables" [] (lib.mapAttrsToList (k: v: mkExe k v)) ++
|
||||||
withAttr package "executable" [] (comp: [(mkExe package.name comp)] );
|
withAttr package "executable" [] (comp: [(mkExe package.name comp)] );
|
||||||
mkExe = nn: component:
|
mkExe = nn: component:
|
||||||
let
|
with
|
||||||
depOrPack =
|
{
|
||||||
lib.lists.partition
|
depsAndPacks = lib.foldl
|
||||||
(x: x == package.name)
|
(acc: x:
|
||||||
(optAttr component "dependencies" []);
|
if x == package.name then tap acc "packs" (ps: ps ++ libs)
|
||||||
in
|
else if lib.hasPrefix "./" x then tap acc "packs" (ps:
|
||||||
{ main = fileToModule component.main;
|
ps ++
|
||||||
name = nn;
|
# This is extremely brittle:
|
||||||
src =
|
# - there could be more than one package
|
||||||
let
|
# - this needs to make sure it only picks libraries
|
||||||
base = builtins.dirOf packageYaml;
|
# - it only works with "package.yaml"
|
||||||
source-dirs = optAttr component "source-dirs" ".";
|
[
|
||||||
in
|
(lib.head
|
||||||
if builtins.isList source-dirs
|
( pkgSpecsFromHPack
|
||||||
then builtins.map (sourceDir:
|
("${builtins.toString base}/${x}/package.yaml")
|
||||||
builtins.toPath "${builtins.toString base}/${sourceDir}"
|
)
|
||||||
) source-dirs
|
)
|
||||||
else
|
]
|
||||||
builtins.toPath "${builtins.toString base}/${source-dirs}";
|
)
|
||||||
dependencies = topDeps ++ dropVersionBounds depOrPack.wrong;
|
else tap acc "deps" (ds: ds ++ [x])
|
||||||
extensions = topExtensions ++ (optAttr component "extensions" []);
|
) { deps = []; packs = []; } (optAttr component "dependencies" []);
|
||||||
ghcOpts = topGhcOpts ++ (optAttr component "ghc-options" []);
|
};
|
||||||
packages = if lib.length depOrPack.right > 0 then libs else [];
|
commonAttrs component //
|
||||||
};
|
{ main = fileToModule component.main;
|
||||||
|
name = nn;
|
||||||
|
dependencies = topDeps ++ dropVersionBounds depsAndPacks.deps; # depOrPack.wrong;
|
||||||
|
packages = depsAndPacks.packs;
|
||||||
|
};
|
||||||
in exes ++ libs;
|
in exes ++ libs;
|
||||||
}
|
}
|
||||||
|
@ -50,4 +50,6 @@ withAttr = obj: attrName: def: f:
|
|||||||
optAttr = obj: attrName: def:
|
optAttr = obj: attrName: def:
|
||||||
if builtins.hasAttr attrName obj then obj.${attrName} else def;
|
if builtins.hasAttr attrName obj then obj.${attrName} else def;
|
||||||
|
|
||||||
|
tap = obj: attrName: f: obj // { "${attrName}" = f (obj.${attrName}) ; };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
name: snack-readme
|
name: any-paths
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- lens
|
- lens
|
||||||
@ -11,7 +11,7 @@ executable:
|
|||||||
main: Main.hs
|
main: Main.hs
|
||||||
source-dirs: ./app
|
source-dirs: ./app
|
||||||
dependencies:
|
dependencies:
|
||||||
- snack-readme
|
- any-paths
|
||||||
|
|
||||||
default-extensions:
|
default-extensions:
|
||||||
- OverloadedStrings
|
- OverloadedStrings
|
||||||
|
3
tests/packages-2/Main.hs
Normal file
3
tests/packages-2/Main.hs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import Lib (fromLib)
|
||||||
|
|
||||||
|
main = putStrLn fromLib
|
1
tests/packages-2/golden
Normal file
1
tests/packages-2/golden
Normal file
@ -0,0 +1 @@
|
|||||||
|
hello
|
4
tests/packages-2/lib/Lib.hs
Normal file
4
tests/packages-2/lib/Lib.hs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module Lib (fromLib) where
|
||||||
|
|
||||||
|
fromLib :: String
|
||||||
|
fromLib = "hello"
|
6
tests/packages-2/lib/package.yaml
Normal file
6
tests/packages-2/lib/package.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
name: snack-packages-2
|
||||||
|
|
||||||
|
# NOTE: should not fail if library is empty
|
||||||
|
# For some reason, Nix returns null as opposed to {}
|
||||||
|
library:
|
||||||
|
source-dirs: .
|
6
tests/packages-2/package.yaml
Normal file
6
tests/packages-2/package.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
name: snack-packages
|
||||||
|
|
||||||
|
executable:
|
||||||
|
main: Main.hs
|
||||||
|
dependencies:
|
||||||
|
- ./lib
|
19
tests/packages-2/test
Executable file
19
tests/packages-2/test
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# vim: ft=sh sw=2 et
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
|
||||||
|
test() {
|
||||||
|
$SNACK build
|
||||||
|
$SNACK run | diff golden -
|
||||||
|
|
||||||
|
TMP_FILE=$(mktemp)
|
||||||
|
|
||||||
|
capture_io "$TMP_FILE" main | $SNACK ghci
|
||||||
|
|
||||||
|
diff golden $TMP_FILE
|
||||||
|
rm $TMP_FILE
|
||||||
|
}
|
||||||
|
|
||||||
|
SNACK="snack --package-file ./package.yaml" test
|
Loading…
Reference in New Issue
Block a user