Skip to content

Commit

Permalink
Workaround for cabal trying to build dependencies in nix-shell
Browse files Browse the repository at this point in the history
For source-repository-package's, cabal tries to build them on its own, even
when all dependencies are already provided by Nix. Relevant issues:
- haskell/cabal#6049
- IntersectMBO/ouroboros-network#645
- haskell/cabal#5586 (comment)

This seems to be a problem even with a cabal that includes
haskell/cabal#6917 (see
input-output-hk/haskell.nix#720 (comment)
for how to test a cabal-install 3.4)

The only known workaround is to remove the source-repository-package
sections from cabal.project, but this should only be done for cabal when
used from a nix-shell, not from cabal without a nix-shell, and not outside
the nix-shell.

To make this work smoothly, the script `scripts/nix-setup` can be used,
which splits the source-repository-package sections into cabal.project.srcs,
which is then again included from here (to make the Nix setup still work).
Running the script again undoes it.
  • Loading branch information
infinisil committed Dec 15, 2020
1 parent 4dce3b3 commit 287f4da
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ dist-newstyle
.ghc.environment.*
cabal.project.local*
cabal.project.local~
cabal.project.srcs
dist/

stack.yaml.local.lock
Expand Down
11 changes: 6 additions & 5 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ let
sha256 = "sha256-kFLfYQ+8ogz4uycvriAszwP3Af7yqRGrxH6l6HmnKuc=";
})
{ inherit system; };
morphoPkgs = import ./nix/morpho-node.nix { inherit pkgs src haskellCompiler profile; };
shell = morphoPkgs.shellFor {
morphoPkgs = nixShell: import ./nix/morpho-node.nix { inherit pkgs src haskellCompiler nixShell profile; };
shell = (morphoPkgs true).shellFor {
packages = ps: with ps; [
morpho-checkpoint-node
];
Expand All @@ -39,8 +39,9 @@ let
# Systemd won't build on darwin, checking first we're not on a
# Darwin env.
(pkgs.stdenv.lib.optional (!pkgs.stdenv.isDarwin) pkgs.systemd);
#exactDeps = false;
exactDeps = true;
};
# Instantiate a package set using the generated file.
in
morphoPkgs // { inherit shell pkgs mantis; }
in morphoPkgs false // {
inherit shell pkgs mantis;
}
31 changes: 31 additions & 0 deletions nix/morpho-node.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,44 @@
, src
, haskellCompiler ? "ghc865"
, profile
, nixShell
, ...
}:

pkgs.haskell-nix.cabalProject {
inherit src;
name = "morpho-checkpoint-node";
compiler-nix-name = haskellCompiler;

# For source-repository-package's, cabal tries to build them on its own, even
# when all dependencies are already provided by Nix. Relevant issues:
# - https://github.com/haskell/cabal/issues/6049
# - https://github.com/input-output-hk/ouroboros-network/pull/645
# - https://github.com/haskell/cabal/issues/5586#issuecomment-479576084
#
# This seems to be a problem even with a cabal that includes
# https://github.com/haskell/cabal/pull/6917 (see
# https://github.com/input-output-hk/haskell.nix/issues/720#issuecomment-745397468
# for how to test a cabal-install 3.4)
#
# The only known workaround is to remove the source-repository-package
# sections from cabal.project, but this should only be done for cabal when
# used from a nix-shell, not from cabal without a nix-shell, and not outside
# the nix-shell.
#
# To make this work smoothly, the script `scripts/nix-setup` can be used,
# which splits the source-repository-package sections into cabal.project.srcs,
# which is then again included from here (to make the Nix setup still work).
# Running the script again undoes it.
cabalProject =
let
exists = builtins.pathExists (../cabal.project.srcs);
standard = builtins.readFile (src + "/cabal.project");
sources = builtins.readFile (../cabal.project.srcs);
in if exists then standard + "\n" + sources
else if nixShell then throw "You need to run scripts/nix-setup first"
else standard;

pkg-def-extras = [
(hackage: {
packages = {
Expand Down
39 changes: 39 additions & 0 deletions scripts/nix-setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' exit

if [[ ! -f cabal.project.srcs ]]; then
# We later mark cabal.project as not having any changes, since we remove
# source-repository-package sections from it but don't want the user to commit that
# But if the user already has changes to it, that would make them not commit their own changes too
# So make the user either stage or commit the changes to prevent this
if ! git diff --exit-code --quiet cabal.project; then
echo "cabal.project has unstaged changes. Stage or commit them first to use this script" >&2
exit 1
fi
echo "Setting up cabal.project to work with nix-shell" >&2

# Splits the file at the first occurence of source-repository-package
csplit -s -f "$tmp/cabal.project.split." cabal.project /source-repository-package/
mv "$tmp/cabal.project.split.00" cabal.project
mv "$tmp/cabal.project.split.01" cabal.project.srcs

# Prevent modification of these files since we later mark them as not having any changes
chmod -w cabal.project cabal.project.srcs

# In order to prevent the user from committing the changes to cabal.project, tell git that it should assume it wasn't changed
git update-index --assume-unchanged cabal.project
else
echo "Undoing cabal.project setup for nix-shell" >&2

# Combine the split files into one again
cat cabal.project cabal.project.srcs > "$tmp/cabal.project"
chmod +w cabal.project cabal.project.srcs
rm cabal.project.srcs
mv "$tmp/cabal.project" cabal.project

# Tell git to track changes to cabal.project again
git update-index --no-assume-unchanged cabal.project
fi

0 comments on commit 287f4da

Please sign in to comment.