summaryrefslogtreecommitdiff
path: root/Biz/Bild/Builder.nix
diff options
context:
space:
mode:
Diffstat (limited to 'Biz/Bild/Builder.nix')
-rw-r--r--Biz/Bild/Builder.nix214
1 files changed, 112 insertions, 102 deletions
diff --git a/Biz/Bild/Builder.nix b/Biz/Bild/Builder.nix
index 2b62b89..a5a31c7 100644
--- a/Biz/Bild/Builder.nix
+++ b/Biz/Bild/Builder.nix
@@ -3,115 +3,125 @@ 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;
+{ analysisJSON, nixpkgs ? import ../Bild.nix {} }:
+with nixpkgs;
let
- srcs_ = (lib.strings.splitString " " srcs) ++ [main];
+ analysis = builtins.fromJSON analysisJSON;
+ build = _: target: let
+ name = target.out;
+ root = builtins.getEnv "BIZ_ROOT";
+ mainModule = target.mainModule;
+ compileLine =
+ lib.strings.concatStringsSep " " ([target.compiler] ++ target.compilerFlags);
- isEmpty = x: x == null || x == [];
+ allSources = target.srcs ++ [target.quapath];
- 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;
+ isEmpty = x: x == null || x == [];
- # clean up empty dirs
- postUnpack = "find . -type d -empty -delete";
+ skip = ["_" ".direnv"];
+ filter = file: type:
+ if lib.lists.elem (builtins.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 lib.trivial.pipe file
+ [ (f: lib.strings.removePrefix "${root}/" f)
+ (f: lib.lists.elem f allSources)
+ ]
+ else false;
- src = lib.sources.cleanSourceWith {inherit filter; src = lib.sources.cleanSource root;};
+ # clean up empty dirs
+ #postUnpack = "find $src -type d -empty -delete";
- langdeps_ =
- if isEmpty langdeps then
- []
- else
- private.selectAttrs (lib.strings.splitString " " langdeps) private.${packageSet};
- sysdeps_ =
- if isEmpty 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 = langdeps_ ++ sysdeps_;
- installPhase = "install -D ${name} $out/bin/${name}";
- buildPhase = compileLine;
- };
+ src = lib.sources.cleanSourceWith {inherit filter; src = lib.sources.cleanSource root;};
- haskell = stdenv.mkDerivation rec {
- inherit name src BIZ_ROOT postUnpack;
- buildInputs = sysdeps_ ++ [
- (private.ghcWith (p:
- (private.selectAttrs (lib.strings.splitString " " langdeps) p)
- ))
- ];
- installPhase = "install -D ${name} $out/bin/${name}";
- buildPhase = compileLine;
- };
+ langdeps_ =
+ if isEmpty target.langdeps then
+ []
+ else
+ lib.attrsets.attrVals
+ target.langdeps
+ (lib.attrsets.getAttrFromPath (lib.strings.splitString "." target.packageSet) bild);
+ sysdeps_ =
+ if isEmpty target.sysdeps then
+ []
+ else
+ lib.attrsets.attrVals target.sysdeps pkgs;
+ BIZ_ROOT = ".";
- c = stdenv.mkDerivation rec {
- inherit name src BIZ_ROOT postUnpack;
- buildInputs = langdeps_ ++ sysdeps_;
- installPhase = "install -D ${name} $out/bin/${name}";
- buildPhase = lib.strings.concatStringsSep " " [
- compileLine
- (if isEmpty langdeps then "" else
- "$(pkg-config --cflags ${langdeps})")
- (if isEmpty sysdeps then "" else
- "$(pkg-config --libs ${sysdeps})")
- ];
- };
+ builders = {
+ base = stdenv.mkDerivation rec {
+ inherit name src BIZ_ROOT;
+ buildInputs = langdeps_ ++ sysdeps_;
+ installPhase = "install -D ${name} $out/bin/${name}";
+ buildPhase = compileLine;
+ };
- python = buildPythonApplication rec {
- inherit name src BIZ_ROOT postUnpack;
- propagatedBuildInputs = [ (private.pythonWith (_: 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
- };
-}
+ haskell = stdenv.mkDerivation rec {
+ inherit name src BIZ_ROOT;
+ buildInputs = sysdeps_ ++ [
+ (bild.haskell.ghcWith (p:
+ (lib.attrsets.attrVals target.langdeps p)
+ ))
+ ];
+ installPhase = "install -D ${name} $out/bin/${name}";
+ buildPhase = compileLine;
+ };
+
+ c = stdenv.mkDerivation rec {
+ inherit name src BIZ_ROOT;
+ buildInputs = langdeps_ ++ sysdeps_;
+ installPhase = "install -D ${name} $out/bin/${name}";
+ buildPhase = lib.strings.concatStringsSep " " [
+ compileLine
+ (if isEmpty langdeps_ then "" else
+ "$(pkg-config --cflags ${lib.strings.concatStringsSep " " target.langdeps})")
+ (if isEmpty sysdeps_ then "" else
+ "$(pkg-config --libs ${lib.strings.concatStringsSep " " target.sysdeps})")
+ ];
+ };
+
+ python = bild.python.buildPythonApplication rec {
+ inherit name src BIZ_ROOT;
+ propagatedBuildInputs = [ (bild.python.pythonWith (_: langdeps_)) ] ++ sysdeps_;
+ buildInputs = sysdeps_;
+ checkInputs = [(bild.python.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 ${mainModule} 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} = ${mainModule}: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 = [mainModule]; # sanity check
+ };
+ };
+ in builders.${target.builder};
+# the caller gives us the Analysis type, which is a hashmap, but i need to
+# return a single drv, so just take the first one for now. ideally i would only
+# pass Target, one at a time, (perhaps parallelized in haskell land) and then i
+# wouldn't need all of this let nesting
+in builtins.head (lib.attrsets.mapAttrsToList build analysis)