|
| 1 | +{ |
| 2 | + lib |
| 3 | +, haskellLib |
| 4 | +}: { |
| 5 | + devshell = final: prev: { |
| 6 | + devshell = let |
| 7 | + cabal-install = final.pkgs.buildPackages.haskell-nix.cabal-install.${final.args.compiler-nix-name}; |
| 8 | + inherit (final.pkgs.buildPackages) runCommand runtimeShell; |
| 9 | + cabalWrapper = runCommand "cabal" { inherit (cabal-install) meta; } '' |
| 10 | + mkdir -p $out/bin |
| 11 | + cat << EOF > $out/bin/cabal |
| 12 | + #!${runtimeShell} |
| 13 | + set -euo pipefail |
| 14 | +
|
| 15 | + find_up() { |
| 16 | + while [[ \$PWD != / ]] ; do |
| 17 | + if [[ -e "\$1" ]]; then |
| 18 | + echo "\$PWD" |
| 19 | + return |
| 20 | + fi |
| 21 | + cd .. |
| 22 | + done |
| 23 | + } |
| 24 | +
|
| 25 | + toplevel=\$(find_up "cabal.project") |
| 26 | +
|
| 27 | + if [[ -n "\$toplevel" ]]; then |
| 28 | + cabal_project="\$toplevel/cabal.project" |
| 29 | + nix_cabal_project=\$toplevel/.nix-cabal.project |
| 30 | + extra_cabal_opts=("--project-file=\$nix_cabal_project") |
| 31 | + awk ' |
| 32 | + # Add comment with explanation of file |
| 33 | + BEGIN { |
| 34 | + print "-- Generated from '"\$cabal_project"' by the wrapper script" |
| 35 | + print "-- ${placeholder "out"}/cabal" |
| 36 | + print "-- Add this file to your .gitignore\n" |
| 37 | + } |
| 38 | +
|
| 39 | + # Matches all section starts |
| 40 | + /^[^ ]/ { |
| 41 | + # Remember the section name (they can span multiple lines) |
| 42 | + section = \$0 |
| 43 | + } |
| 44 | + # Matches every line |
| 45 | + // { |
| 46 | + # Only print the line if it is not in the section we want to omit |
| 47 | + if (section != "source-repository-package") |
| 48 | + print \$0 |
| 49 | + } |
| 50 | + ' "\$cabal_project" > "\$nix_cabal_project" |
| 51 | + else |
| 52 | + extra_cabal_opts=() |
| 53 | + fi |
| 54 | +
|
| 55 | + cabal=${placeholder "out"}/bin/.cabal |
| 56 | + >&2 echo "\$cabal \''${extra_cabal_opts[@]} \$@" |
| 57 | + exec "\$cabal" "\''${extra_cabal_opts[@]}" "\$@" |
| 58 | + EOF |
| 59 | + cp -rn ${cabal-install}/* $out/ |
| 60 | + cp ${cabal-install}/bin/cabal $out/bin/.cabal |
| 61 | + chmod +x $out/bin/* |
| 62 | + ''; |
| 63 | + in { |
| 64 | + packages = final.shell.nativeBuildInputs; |
| 65 | + env = lib.mapAttrsToList lib.nameValuePair { |
| 66 | + inherit (final.shell) CABAL_CONFIG NIX_GHC_LIBDIR; |
| 67 | + }; |
| 68 | + commands = [ |
| 69 | + { |
| 70 | + package = cabalWrapper; |
| 71 | + category = "development"; |
| 72 | + } |
| 73 | + ]; |
| 74 | + }; |
| 75 | + }; |
| 76 | + |
| 77 | + projectComponents = final: prev: let |
| 78 | + packages = haskellLib.selectProjectPackages final.hsPkgs; |
| 79 | + # used to materialize `packages-exes.nix` (project packages and exes list) to avoid some evaluations: |
| 80 | + packagesExes = lib.genAttrs |
| 81 | + (lib.attrNames final.packages) |
| 82 | + (name: lib.attrNames final.hsPkgs.${name}.components.exes); |
| 83 | + collectExes = packagesExes: lib.listToAttrs (lib.concatLists (lib.mapAttrsToList |
| 84 | + (p: map (exe: lib.nameValuePair exe final.hsPkgs.${p}.components.exes.${exe})) packagesExes)); |
| 85 | + in { |
| 86 | + # local project packages: |
| 87 | + packages = haskellLib.selectProjectPackages final.hsPkgs; |
| 88 | + # set of all exes (as first level entries): |
| 89 | + exes = collectExes packagesExes; |
| 90 | + # set of all exes (as first level entries), mapped from a materialized set of packages and exes set (generated via `generatePackagesExes`): |
| 91 | + exesFrom = packagesExesMat: collectExes (import packagesExesMat); |
| 92 | + # `tests` are the test suites which have been built. |
| 93 | + tests = haskellLib.collectComponents' "tests" final.packages; |
| 94 | + # `benchmarks` (only built, not run). |
| 95 | + benchmarks = haskellLib.collectComponents' "benchmarks" final.packages; |
| 96 | + # `checks` collect results of executing the tests: |
| 97 | + checks = haskellLib.collectChecks' final.packages; |
| 98 | + |
| 99 | + generatePackagesExesMat = let |
| 100 | + nixFile = builtins.toFile "packages-exes.nix" (lib.generators.toPretty {} packagesExes); |
| 101 | + in final.pkgs.buildPackages.writeShellScript "generate-packages-exes" '' |
| 102 | + set -euo pipefail |
| 103 | +
|
| 104 | + TARGET="$1" |
| 105 | + TARGET_DIR="$(dirname "$TARGET")" |
| 106 | +
|
| 107 | + mkdir -p "$TARGET_DIR" |
| 108 | + rm -rf "$TARGET" |
| 109 | + cp -r ${nixFile} "$TARGET" |
| 110 | + chmod -R +w "$TARGET" |
| 111 | + ''; |
| 112 | + }; |
| 113 | + |
| 114 | +} |
0 commit comments