summaryrefslogtreecommitdiff
path: root/Biz/Bild
diff options
context:
space:
mode:
Diffstat (limited to 'Biz/Bild')
-rw-r--r--Biz/Bild/Builder.nix93
-rw-r--r--Biz/Bild/Example.py30
2 files changed, 104 insertions, 19 deletions
diff --git a/Biz/Bild/Builder.nix b/Biz/Bild/Builder.nix
index 04002d0..214c110 100644
--- a/Biz/Bild/Builder.nix
+++ b/Biz/Bild/Builder.nix
@@ -1,33 +1,88 @@
-{ srcs # list of files
+/*
+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
+, langdeps ? null # list of deps (as a string), split and passed to packageSet
+, sysdeps ? null
, name # exe name
-, buildPhase
+, compileLine ? "" # Target.compiler <> Target.compilerFlags
}:
with import (/. + root + "/Biz/Bild.nix") {};
with builtins;
let
- srcs_ = lib.strings.splitString " " srcs;
+ 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 srcsr
+ # 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 if type == "regular" then (builtins.elem file srcs_)
else false;
- deps = pkgset:
- if langDeps != null then
- private.selectAttrs (lib.strings.splitString " " langDeps) pkgset
- else
- [];
-in stdenv.mkDerivation rec {
- inherit name buildPhase;
+
+ # clean up empty dirs
+ postUnpack = "find . -type d -empty -delete";
+
src = lib.sources.cleanSourceWith {inherit filter; src = lib.sources.cleanSource root;};
- BIZ_ROOT = src;
- buildInputs = [ (private.${packageSet} deps) ];
- installPhase = ''
- mkdir -p $out/bin && cp ${name} $out/bin
- '';
+
+ 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 = ''
+ black --quiet --exclude 'setup\.py$' --check .
+ pylint --errors-only .
+ mypy --strict --no-error-summary --exclude 'setup\.py$' .
+ 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
+ };
}
diff --git a/Biz/Bild/Example.py b/Biz/Bild/Example.py
new file mode 100644
index 0000000..78a8a6a
--- /dev/null
+++ b/Biz/Bild/Example.py
@@ -0,0 +1,30 @@
+# : out example
+# : dep cryptography
+import sys
+from typing import List
+
+from cryptography.fernet import Fernet
+
+
+def cryptic_hello(name: str) -> str:
+ "Example taken from `cryptography` docs."
+ key = Fernet.generate_key()
+ f = Fernet(key)
+ token = f.encrypt(hello(name).encode("utf-8"))
+ ret = f.decrypt(token).decode("utf-8")
+ assert ret == hello(name)
+ return ret
+
+
+def hello(name: str) -> str:
+ return f"Hello {name}"
+
+
+def main() -> None:
+ if "test" in sys.argv:
+ print("testing success")
+ print(cryptic_hello("world"))
+
+
+if __name__ == "__main__":
+ main()