1
1
mirror of https://github.com/nmattia/snack.git synced 2024-10-26 04:29:51 +03:00

Add support for nested modules

This commit is contained in:
Nicolas Mattia 2018-02-14 00:56:23 +01:00
parent 51987daf76
commit 1000fc9a1a
15 changed files with 93 additions and 20 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
**/result

11
nix/default.nix Normal file
View File

@ -0,0 +1,11 @@
{ nixpkgs ? ./nixpkgs }:
import (import nixpkgs) {
config = { allowUnfree = true; };
overlays = [
(self: super: { snack-lib = import ../snack;} )
(self: super: { snack = self.writeScriptBin "snack"
''
${self.nix}/bin/nix-build snack.nix
''; })
];
}

6
nix/nixpkgs/default.nix Normal file
View File

@ -0,0 +1,6 @@
let
spec = builtins.fromJSON (builtins.readFile ./nixpkgs-src.json);
rev = spec.rev;
url = "https://github.com/${spec.owner}/${spec.repo}/archive/${spec.rev}.tar.gz";
in
builtins.fetchTarball url

View File

@ -5,8 +5,6 @@
# See https://gist.github.com/zimbatm/de5350245874361762b6a4dfe5366530
set -euo pipefail
cd "$(dirname "$0")" || exit 1
branch=master
owner=NixOS
@ -16,7 +14,7 @@ url=https://github.com/$owner/$repo/archive/$rev.tar.gz
release_sha256=$(nix-prefetch-url --unpack "$url")
cat <<NIXPKGS | tee src.json
cat <<NIXPKGS | tee nix/nixpkgs/nixpkgs-src.json
{
"owner": "$owner",
"repo": "$repo",

16
script/test Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash
#!nix-shell -I nixpkgs=./nix
#!nix-shell -p snack
#!nix-shell --pure
# vim: ft=sh sw=2 et
set -eux
pushd tests/flat
snack build
popd
pushd tests/nested
snack build
popd

View File

@ -1,8 +1,7 @@
# TODO: currently single out derivations append the PWD
let
# Use pinned packages
_nixpkgs = import <nixpkgs> {};
nixpkgs = _nixpkgs.fetchFromGitHub (_nixpkgs.lib.importJSON ./nix/src.json);
pkgs = import nixpkgs {config={}; overlays=[];};
pkgs = import (../nix) {};
# Takes a (string) filepath and creates a derivation for that file (and for
# that file only)
@ -13,17 +12,26 @@ let
topLevel = (builtins.toString base) + "/";
actual = (pkgs.lib.strings.removePrefix topLevel path);
expected = file;
in expected == actual;
in
(expected == actual) ||
(type == "directory" && (pkgs.lib.strings.hasPrefix actual expected));
mod = fileToModule file;
in pkgs.stdenv.mkDerivation {
name = file;
name = mod;
src = builtins.filterSource (pred file) base;
builder = pkgs.writeScript (file + "-builder")
builder = pkgs.writeScript (mod + "-builder")
# TODO: make sure the file actually exists and that there's only one
''
echo "Singling out module ${mod} (file is ${file})"
source $stdenv/setup
mkdir -p $out
cp -a $src/* $out/
echo "Running: cp $src/${file} $out/${file}"
echo "Listing $src"
ls $src/**/*
mkdir -p $(dirname $out/${file})
cp $src/${file} $out/${file}
echo "Done: Singling out module ${mod} (file is ${file})"
'';
};
@ -36,6 +44,13 @@ let
moduleToFile = mod:
(pkgs.lib.strings.replaceChars ["."] ["/"] mod) + ".hs";
moduleToObject = mod:
(pkgs.lib.strings.replaceChars ["."] ["/"] mod) + ".o";
fileToModule = file:
pkgs.lib.strings.removeSuffix ".hs"
(pkgs.lib.strings.replaceChars ["/"] ["."] file);
singleOutModule = base: mod: singleOut base (moduleToFile mod);
buildModule = base: mod:
@ -66,7 +81,7 @@ let
echo "Compiling module ${mod.moduleName}"
# Set a tmpdir we have control over, otherwise GHC fails, not sure why
mkdir -p tmp
ghc -tmpdir tmp/ ${mod.moduleName}.hs -c \
ghc -tmpdir tmp/ ${moduleToFile mod.moduleName} -c \
-outputdir $out \
2>&1
echo "Done building module ${mod.moduleName}"
@ -84,16 +99,17 @@ let
go = mod: attrs0:
let
objectName = x:
# TODO: can't use "moduleName.o" because some modules get
# renamed to "Main.o" :/
# Also, hard coding the object file based on the module name feels
# icky
if x.moduleIsMain
then "Main.o"
else x.moduleName + ".o";
else moduleToObject x.moduleName;
attrs1 = f attrs0 mod;
f = acc: elem:
if pkgs.lib.attrsets.hasAttr elem.moduleName acc
then acc
# TODO: module path instead of module name
# TODO: can't use "moduleName.o" because some modules get
# renamed to "Main.o"
else acc //
{ "${elem.moduleName}" =
"${buildModule base elem}/${objectName elem}";
@ -120,8 +136,8 @@ let
];
};
# TODO: use ghc -M for module dependencies
modB = makeModuleSpec "B" [] false;
modA = makeModuleSpec "A" [modB] true;
in linkModuleObjects ./. modA
## TODO: use ghc -M for module dependencies
in
{
inherit linkModuleObjects makeModuleSpec;
}

3
tests/flat/README.md Normal file
View File

@ -0,0 +1,3 @@
# Flat
Makes sure that two modules, `A.hs` and `B.hs`, can be built into an executable

6
tests/flat/snack.nix Normal file
View File

@ -0,0 +1,6 @@
# This "snack" passing is ugly, figure out a nice way of passing snack-lib
with (import ../../nix {}).snack-lib;
let
modB = makeModuleSpec "B" [] false;
modA = makeModuleSpec "A" [modB] true;
in linkModuleObjects ./. modA

3
tests/nested/Foo/A.hs Normal file
View File

@ -0,0 +1,3 @@
import Foo.B.C
main = putStrLn var

3
tests/nested/Foo/B/C.hs Normal file
View File

@ -0,0 +1,3 @@
module Foo.B.C where
var = "Hello, World!"

4
tests/nested/README.md Normal file
View File

@ -0,0 +1,4 @@
# Nested
Make sure that nested modules (e.g. `Foo.A` and `Foo.B.C`) can be built into an
executable

6
tests/nested/snack.nix Normal file
View File

@ -0,0 +1,6 @@
# This "snack" passing is ugly, figure out a nice way of passing snack-lib
with (import ../../nix {}).snack-lib;
let
modB = makeModuleSpec "Foo.B.C" [] false;
modA = makeModuleSpec "Foo.A" [modB] true;
in linkModuleObjects ./. modA