@@ -4,13 +4,36 @@
44let reflex-platform = import ./dep/reflex-platform { inherit system; };
55 inherit (reflex-platform) hackGet;
66 pkgs = reflex-platform.nixpkgs;
7+in with pkgs.haskell.lib; with pkgs.lib;
8+let #TODO: Upstream
9+ # Modify a Haskell package to add completion scripts for the given
10+ # executable produced by it. These completion scripts will be picked up
11+ # automatically if the resulting derivation is installed, e.g. by
12+ # `nix-env -i`.
13+ addOptparseApplicativeCompletionScripts = exeName: pkg: overrideCabal pkg (drv: {
14+ postInstall = (drv.postInstall or "") + ''
15+ BASH_COMP_DIR="$out/share/bash-completion/completions"
16+ mkdir -p "$BASH_COMP_DIR"
17+ "$out/bin/${exeName}" --bash-completion-script "$out/bin/${exeName}" >"$BASH_COMP_DIR/ob"
18+
19+ ZSH_COMP_DIR="$out/share/zsh/vendor-completions"
20+ mkdir -p "$ZSH_COMP_DIR"
21+ "$out/bin/${exeName}" --zsh-completion-script "$out/bin/${exeName}" >"$ZSH_COMP_DIR/_ob"
22+
23+ FISH_COMP_DIR="$out/share/fish/vendor_completions.d"
24+ mkdir -p "$FISH_COMP_DIR"
25+ "$out/bin/${exeName}" --fish-completion-script "$out/bin/${exeName}" >"$FISH_COMP_DIR/ob.fish"
26+ '';
27+ });
28+
729 # The haskell environment used to build Obelisk itself, e.g. the 'ob' command
830 ghcObelisk = reflex-platform.ghc.override {
9− overrides = self: super: with pkgs.haskell.lib; {
10− #TODO: Eliminate this when https://github.com/phadej/github/pull/307 makes its way to reflex-platform
31+ overrides = composeExtensions addLibs (self: super: {
1132 mkDerivation = args: super.mkDerivation (args // {
1233 enableLibraryProfiling = profiling;
1334 });
35+
36+ #TODO: Eliminate this when https://github.com/phadej/github/pull/307 makes its way to reflex-platform
1437 github = overrideCabal super.github (drv: {
1538 src = pkgs.fetchFromGitHub {
1639 owner = "ryantrinkle";
@@ -24,44 +47,39 @@ let reflex-platform = import ./dep/reflex-platform { inherit system; };
2447 });
2548
2649 # Dynamic linking with split objects dramatically increases startup time (about 0.5 seconds on a decent machine with SSD)
27− obelisk-command = overrideCabal (justStaticExecutables (self.callCabal2nix "obelisk-command" ./lib/command {})) (drv: {
28− postInstall = (drv.postInstall or "") + ''
29− OB="$out/bin/ob"
30−
31− BASH_COMP="$out/share/bash-completion/completions"
32− mkdir -p "$BASH_COMP"
33− "$OB" --bash-completion-script "$OB" >"$BASH_COMP/ob"
34−
35− ZSH_COMP="$out/share/zsh/vendor-completions"
36− mkdir -p "$ZSH_COMP"
37− "$OB" --zsh-completion-script "$OB" >"$ZSH_COMP/_ob"
38−
39− FISH_COMP="$out/share/fish/vendor_completions.d"
40− mkdir -p "$FISH_COMP"
41− "$OB" --fish-completion-script "$OB" >"$FISH_COMP/ob.fish"
42− '';
43− });
50+ obelisk-command = addOptparseApplicativeCompletionScripts "ob" (justStaticExecutables super.obelisk-command);
4451
4552 optparse-applicative = self.callHackage "optparse-applicative" "0.14.0.0" {};
46− };
53+ });
54+ };
55+
56+ addLibs = self: super: {
57+ obelisk-asset-serve = self.callCabal2nix "obelisk-asset-serve" (hackGet ./lib/asset + "/serve") {};
58+ obelisk-asset-manifest = self.callCabal2nix "obelisk-asset-manifest" (hackGet ./lib/asset + "/manifest") {};
59+ obelisk-backend = self.callCabal2nix "obelisk-backend" ./lib/backend {};
60+ obelisk-snap = self.callCabal2nix "obelisk-snap" ./lib/snap {};
61+ obelisk-selftest = self.callCabal2nix "obelisk-selftest" ./lib/selftest {};
62+ obelisk-command = self.callCabal2nix "obelisk-command" ./lib/command {};
4763 };
4864in
4965with pkgs.lib;
5066rec {
5167 inherit reflex-platform;
5268 command = ghcObelisk.obelisk-command;
69+ selftest = pkgs.writeScript "selftest" ''
70+ #!/usr/bin/env bash
71+ set -euo pipefail
72+
73+ PATH="${ghcObelisk.obelisk-command}/bin:$PATH"
74+ export OBELISK_IMPL="${hackGet ./.}"
75+ "${justStaticExecutables ghcObelisk.obelisk-selftest}/bin/obelisk-selftest"
76+ '';
5377 #TODO: Why can't I build ./skeleton directly as a derivation? `nix-build -E ./.` doesn't work
5478 skeleton = pkgs.runCommand "skeleton" {
5579 dir = builtins.filterSource (path: type: builtins.trace path (baseNameOf path != ".obelisk")) ./skeleton;
5680 } ''
5781 ln -s "$dir" "$out"
5882 '';
59− haskellOverrides = self: super: {
60− obelisk-asset-serve = self.callCabal2nix "obelisk-asset-serve" (hackGet ./lib/asset + "/serve") {};
61− obelisk-asset-manifest = self.callCabal2nix "obelisk-asset-manifest" (hackGet ./lib/asset + "/manifest") {};
62− obelisk-backend = self.callCabal2nix "obelisk-backend" ./lib/backend {};
63− obelisk-snap = self.callCabal2nix "obelisk-snap" ./lib/snap {};
64− };
6583 nullIfAbsent = p: if pathExists p then p else null;
6684 #TODO: Avoid copying files within the nix store. Right now, obelisk-asset-manifest-generate copies files into a big blob so that the android/ios static assets can be imported from there; instead, we should get everything lined up right before turning it into an APK, so that copies, if necessary, only exist temporarily.
6785 processAssets = { src, packageName ? "static", moduleName ? "Static" }: pkgs.runCommand "asset-manifest" {
@@ -76,7 +94,7 @@ rec {
7694 obelisk-asset-manifest-generate "$src" "$haskellManifest" ${packageName} ${moduleName} "$symlinked"
7795 '';
7896 # An Obelisk project is a reflex-platform project with a predefined layout and role for each component
79− project = base: projectDefinition: reflex-platform.project (args@{ nixpkgs, ... }: with nixpkgs.haskell.lib;
97+ project = base: projectDefinition: reflex-platform.project (args@{ nixpkgs, ... }:
8098 let mkProject = { android ? null #TODO: Better error when missing
8199 , ios ? null #TODO: Better error when missing
82100 , packages ? {}
@@ -98,7 +116,7 @@ rec {
98116 heist = doJailbreak super.heist; #TODO: Move up to reflex-platform; create tests for r-p supported packages
99117 ${staticName} = dontHaddock (self.callCabal2nix "static" assets.haskellManifest {});
100118 };
101− overrides = composeExtensions haskellOverrides projectOverrides;
119+ overrides = composeExtensions addLibs projectOverrides;
102120 in {
103121 inherit overrides;
104122 packages = combinedPackages;