{ 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; seq = ls: builtins.filter (x: x!= null) ls; depsToPackageSet = packageSet: deps: map (s: builtins.getAttr s packageSet) deps; # do the build... claySrc = pkgs.fetchFromGitHub { owner = "sebastiaanvisser"; repo = "clay"; rev = "cc7729b1b42a79e261091ff7835f7fc2a7ae3cee"; sha256 = "1vd67976lvi5l4qq18zy6j44apynkl44ps04p8vwfx4gzr895dyp"; }; ghc865_ = pkgs.haskell.packages.ghc865.override (oldAttrs: { overrides = with pkgs.haskell.lib; self: super: { clay = self.callCabal2nix "clay" claySrc {}; wai-middleware-metrics = dontCheck super.wai-middleware-metrics; }; }); # ghcjs-8.6.0.1 ghcjs_ = pkgs.haskell.packages.ghcjs.override (oldAttrs: { overrides = with pkgs.haskell.lib; self: super: { QuickCheck = dontCheck super.QuickCheck; base-compat-batteries = dontCheck super.http-types; clay = dontCheck (self.callCabal2nix "clay" claySrc {}); comonad = dontCheck super.comonad; http-types = dontCheck super.http-types; network-uri= dontCheck super.network-uri; scientific = dontCheck super.scientific; # takes forever servant = dontCheck super.servant; tasty-quickcheck = dontCheck super.tasty-quickcheck; time-compat = dontCheck super.time-compat; }; }); 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 (seq (map (builtins.match "^-- : exe ([[:alnum:]._-]*)$") (lines content)))); deps = lists.flatten (seq (map (builtins.match "^-- : dep ([[:alnum:]._-]*)$") (lines content))); ghc = ghc865_.ghcWithHoogle (hp: depsToPackageSet hp 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; }; }