{ nixpkgs }: with nixpkgs; with nixpkgs.lib; let # provided by .envrc root = builtins.getEnv "BIZ_ROOT"; # general functions to put in a lib lines = s: strings.splitString "\n" s; removeNull = ls: builtins.filter (x: x != null) ls; depsToPackageSet = packageSet: deps: attrsets.attrVals deps packageSet; # returns true if a is a subset of b, where a and b are attrsets subset = a: b: builtins.all (x: builtins.elem x b) a; allDeps = import ./deps.nix; in { buildGhc = main: let relpath = builtins.replaceStrings ["${root}/"] [""] (builtins.toString main); module = builtins.replaceStrings ["/" ".hs"] ["." ""] relpath; content = builtins.readFile main; exe = builtins.head (lists.flatten (removeNull (map (builtins.match "^-- : exe ([[:alnum:]._-]*)$") (lines content)))); deps = lists.flatten (removeNull (map (builtins.match "^-- : dep ([[:alnum:]._-]*)$") (lines content))); ghc = pkgs.haskell.packages.ghc865.ghcWithHoogle (hp: if (subset deps allDeps) then depsToPackageSet hp deps else throw ("missing from deps.nix: ${toString (lib.lists.subtractLists allDeps deps)}") ); in stdenv.mkDerivation { name = module; version = "0"; src = ./.; nativeBuildInputs = [ ghc ]; strictDeps = true; buildPhase = '' mkdir -p $out/{bin,static} ${baseNameOf relpath} # compile with ghc ${ghc}/bin/ghc -Werror -i. \ --make ${main} \ -main-is ${module} \ -o $out/bin/${exe} ''; # the install process was handled above installPhase = "exit 0"; } // { env = ghc; }; buildGhcjs = main: let relpath = builtins.replaceStrings ["${root}/"] [""] (builtins.toString main); module = builtins.replaceStrings ["/" ".hs"] ["." ""] relpath; content = builtins.readFile main; exe = builtins.head (lists.flatten (seq (map (builtins.match "^-- : exe ([[:alnum:]._-]*)$") (lines content)))); deps = lists.flatten (seq (map (builtins.match "^-- : dep ([[:alnum:]._-]*)$") (lines content))); ghcjs = ghcjs_.ghcWithPackages (hp: depsToPackageSet hp deps); in stdenv.mkDerivation { name = module; version = "0"; src = ./.; nativeBuildInputs = [ ghcjs ]; strictDeps = true; buildPhase = '' mkdir -p $out/{bin,static} ${baseNameOf relpath} # compile with ghcjs ${ghcjs}/bin/ghcjs -Werror -i. \ --make ${main} \ -main-is ${module} \ -o ${exe} # optimize js output ${pkgs.closurecompiler}/bin/closure-compiler \ ${exe}.jsexe/all.js > $out/static/${exe} ''; installPhase = "exit 0"; } // { env = ghcjs; }; globalGhc = pkgs.haskell.packages.ghc865.ghcWithHoogle (hp: depsToPackageSet hp allDeps); }