1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
/*
This is the library of nix builders. Some rules to follow:
- Keep this code as minimal as possible. I'd rather write Haskell than Nix,
wouldn't you?
- Try to reuse as much upstream Nix as possible.
- Path-like args such as 'srcs' should always be absolute paths.
*/
{ srcs ? "" # list of all source files, as a space-separated string
, main # the entrypoint or main module (not a path)
, root # path to git root
, packageSet # name mapped to private.${packageSet}, e.g. 'ghcWith'
, langdeps ? null # list of deps (as a string), split and passed to packageSet
, sysdeps ? null
, name # exe name
, compileLine ? "" # Target.compiler <> Target.compilerFlags
}:
with import (/. + root + "/Biz/Bild.nix") {};
with builtins;
let
srcs_ = (lib.strings.splitString " " srcs) ++ [main];
skip = ["_" ".direnv"];
filter = file: type:
if elem (baseNameOf file) skip then false
# TODO: this means any new directory will cause a rebuild. this bad. i
# should recurse into the directory and match against the srcs. for now I
# just use postUnpack to delete empty dirs
else if type == "directory" then true
else if type == "regular" then (builtins.elem file srcs_)
else false;
# clean up empty dirs
postUnpack = "find . -type d -empty -delete";
src = lib.sources.cleanSourceWith {inherit filter; src = lib.sources.cleanSource root;};
langdeps_ = pkgset:
if langdeps == null || langdeps == [] then
[]
else
private.selectAttrs (lib.strings.splitString " " langdeps) pkgset;
sysdeps_ =
if sysdeps == null || sysdeps == [] then
[]
else
private.selectAttrs (lib.strings.splitString " " sysdeps) private.nixpkgs.pkgs;
BIZ_ROOT = ".";
in {
base = stdenv.mkDerivation rec {
inherit name src BIZ_ROOT postUnpack;
buildInputs = [ (private.${packageSet} langdeps_) ] ++ sysdeps_;
installPhase = "install -D ${name} $out/bin/${name}";
buildPhase = compileLine;
};
python = buildPythonApplication rec {
inherit name src BIZ_ROOT postUnpack;
propagatedBuildInputs = [ (private.${packageSet} langdeps_) ] ++ sysdeps_;
buildInputs = sysdeps_;
checkInputs = [(private.pythonWith (p: with p; [black mypy pylint]))];
checkPhase = ''
check() {
$@ || { echo "fail: $name: $3"; exit 1; }
}
check python -m black --quiet --exclude 'setup\.py$' --check .
check python -m pylint --errors-only .
check python -m mypy --strict --no-error-summary --exclude 'setup\.py$' .
check python -m ${main} test
'';
preBuild = ''
# initialize possibly-empty subdirectories as python modules
find . -type d -exec touch {}/__init__.py \;
# generate a minimal setup.py
cat > setup.py << EOF
from setuptools import setup, find_packages
setup(
name='${name}',
entry_points={'console_scripts':['${name} = ${main}:main']},
version='0.0.0',
url='git://simatime.com/biz.git',
author='dev',
author_email='dev@simatime.com',
description='nil',
packages=find_packages(),
install_requires=[],
)
EOF
'';
pythonImportsCheck = [main]; # sanity check
};
}
|