Skip to content

Commit 9930ea8

Browse files
authored
Merge pull request #4193 from ttuegel/nix
Nix integration improvements
2 parents 19d9738 + 10dc4ab commit 9930ea8

File tree

5 files changed

+54
-24
lines changed

5 files changed

+54
-24
lines changed

Cabal.nix renamed to Cabal/default.nix

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
{ mkDerivation, array, base, binary, bytestring, containers
2-
, deepseq, directory, exceptions, filepath, old-time, pretty
3-
, process, QuickCheck, regex-posix, stdenv, tagged, tasty
4-
, tasty-hunit, tasty-quickcheck, time, transformers, unix
2+
, deepseq, directory, filepath, pretty, process, QuickCheck, stdenv
3+
, tagged, tasty, tasty-hunit, tasty-quickcheck, time, unix
54
}:
65
mkDerivation {
76
pname = "Cabal";
87
version = "1.25.0.0";
9-
src = ./Cabal;
8+
src = ./.;
109
libraryHaskellDepends = [
1110
array base binary bytestring containers deepseq directory filepath
1211
pretty process time unix
1312
];
1413
testHaskellDepends = [
15-
array base bytestring containers directory exceptions filepath
16-
old-time pretty process QuickCheck regex-posix tagged tasty
17-
tasty-hunit tasty-quickcheck time transformers unix
14+
array base containers directory filepath pretty QuickCheck tagged
15+
tasty tasty-hunit tasty-quickcheck
1816
];
1917
doCheck = false;
2018
homepage = "http://www.haskell.org/cabal/";

Cabal/doc/nix-integration.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ To enable Nix integration, simply pass the ``--enable-nix`` global option when y
1212
1313
nix: True
1414
15-
If the package (which must be locally unpacked) provides a ``shell.nix`` file, this flag will cause ``cabal`` to run most commands through ``nix-shell``. The following commands are affected:
15+
If the package (which must be locally unpacked) provides a ``shell.nix`` or ``default.nix`` file, this flag will cause ``cabal`` to run most commands through ``nix-shell``. If both expressions are present, ``shell.nix`` is preferred. The following commands are affected:
1616

1717
- ``cabal configure``
1818
- ``cabal build``
@@ -23,7 +23,7 @@ If the package (which must be locally unpacked) provides a ``shell.nix`` file, t
2323
- ``cabal gen-bounds``
2424
- ``cabal run``
2525

26-
If the package does not provide a ``shell.nix``, ``cabal`` runs normally.
26+
If the package does not provide an expression, ``cabal`` runs normally.
2727

2828
Creating Nix Expressions
2929
------------------------
@@ -34,6 +34,15 @@ The Nix package manager is based on a lazy, pure, functional programming languag
3434
3535
$ cabal2nix --shell ./. >shell.nix
3636
37+
Nix Expression Evaluation
38+
-------------------------
39+
40+
(This section describes for advanced users how Nix expressions are evaluated.)
41+
42+
First, the Nix expression (``shell.nix`` or ``default.nix``) is instantiated with ``nix-instantiate``. The ``--add-root`` and ``--indirect`` options are used to create an indirect root in the Cabal build directory, preventing Nix from garbage collecting the derivation while in use. The ``IN_NIX_SHELL`` environment variable is set so that ``builtins.getEnv`` works as it would in ``nix-shell``.
43+
44+
Next, the commands above are run through ``nix-shell`` using the instantiated derivation. Again, ``--add-root`` and ``--indirect`` are used to prevent Nix from garbage collecting the packages in the environment. The child ``cabal`` process reads the ``CABAL_IN_NIX_SHELL`` environment variable to prevent it from spawning additional child shells.
45+
3746
Further Reading
3847
----------------
3948

cabal-install/Distribution/Client/Nix.hs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,20 @@ module Distribution.Client.Nix
1414
import Control.Applicative ((<$>))
1515
#endif
1616

17-
import Control.Exception (catch)
17+
import Control.Exception (bracket, catch)
1818
import Control.Monad (filterM, when, unless)
1919
import System.Directory
2020
( createDirectoryIfMissing, doesDirectoryExist, doesFileExist
2121
, makeAbsolute, removeDirectoryRecursive, removeFile )
22-
import System.Environment (getExecutablePath, getArgs, lookupEnv)
22+
import System.Environment (getArgs, getExecutablePath)
2323
import System.FilePath
2424
( (</>), (<.>), replaceExtension, takeDirectory, takeFileName )
2525
import System.IO (IOMode(..), hClose, openFile)
2626
import System.IO.Error (isDoesNotExistError)
2727
import System.Process (showCommandForUser)
2828

29+
import Distribution.Compat.Environment
30+
( lookupEnv, setEnv, unsetEnv )
2931
import Distribution.Compat.Semigroup
3032

3133
import Distribution.Verbosity
@@ -70,6 +72,18 @@ findNixExpr globalFlags config = do
7072
else return Nothing
7173

7274

75+
-- set IN_NIX_SHELL so that builtins.getEnv in Nix works as in nix-shell
76+
inFakeNixShell :: IO a -> IO a
77+
inFakeNixShell f =
78+
bracket (fakeEnv "IN_NIX_SHELL" "1") (resetEnv "IN_NIX_SHELL") (\_ -> f)
79+
where
80+
fakeEnv var new = do
81+
old <- lookupEnv var
82+
setEnv var new
83+
return old
84+
resetEnv var = maybe (unsetEnv var) (setEnv var)
85+
86+
7387
nixInstantiate
7488
:: Verbosity
7589
-> FilePath
@@ -98,8 +112,9 @@ nixInstantiate verb dist force globalFlags config =
98112
removeGCRoots verb dist
99113
touchFile timestamp
100114

101-
_ <- getDbProgramOutput verb prog progdb
102-
[ "--add-root", shellDrv, "--indirect", shellNix ]
115+
_ <- inFakeNixShell
116+
(getDbProgramOutput verb prog progdb
117+
[ "--add-root", shellDrv, "--indirect", shellNix ])
103118
return ()
104119

105120

@@ -128,6 +143,9 @@ nixShell verb dist globalFlags config go = do
128143

129144
cabal <- getExecutablePath
130145

146+
-- alreadyInShell == True in child process
147+
setEnv "CABAL_IN_NIX_SHELL" "1"
148+
131149
-- Run cabal with the same arguments inside nix-shell.
132150
-- When the child process reaches the top of nixShell, it will
133151
-- detect that it is running inside the shell and fall back
@@ -151,7 +169,7 @@ gcrootPath dist = dist </> "nix" </> "gcroots"
151169

152170

153171
inNixShell :: IO Bool
154-
inNixShell = maybe False (const True) <$> lookupEnv "IN_NIX_SHELL"
172+
inNixShell = maybe False (const True) <$> lookupEnv "CABAL_IN_NIX_SHELL"
155173

156174

157175
removeGCRoots :: Verbosity -> FilePath -> IO ()

cabal-install.nix renamed to cabal-install/default.nix

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
{ mkDerivation, array, async, base, base16-bytestring, binary
22
, bytestring, Cabal, containers, cryptohash-sha256, deepseq
3-
, directory, filepath, hackage-security, hashable, HTTP, mtl
4-
, network, network-uri, pretty, pretty-show, process, QuickCheck
5-
, random, regex-posix, stdenv, stm, tagged, tar, tasty, tasty-hunit
6-
, tasty-quickcheck, time, unix, zlib
3+
, directory, echo, edit-distance, filepath, hackage-security
4+
, hashable, HTTP, mtl, network, network-uri, pretty, pretty-show
5+
, process, QuickCheck, random, regex-posix, stdenv, stm, tagged
6+
, tar, tasty, tasty-hunit, tasty-quickcheck, time, unix, zlib
77
}:
88
mkDerivation {
99
pname = "cabal-install";
1010
version = "1.25.0.0";
11-
src = ./cabal-install;
11+
src = ./.;
1212
isLibrary = false;
1313
isExecutable = true;
1414
setupHaskellDepends = [ base Cabal filepath process ];
1515
executableHaskellDepends = [
1616
array async base base16-bytestring binary bytestring Cabal
17-
containers cryptohash-sha256 deepseq directory filepath
18-
hackage-security hashable HTTP mtl network network-uri pretty
19-
process random stm tar time unix zlib
17+
containers cryptohash-sha256 deepseq directory echo edit-distance
18+
filepath hackage-security hashable HTTP mtl network network-uri
19+
pretty process random stm tar time unix zlib
2020
];
2121
testHaskellDepends = [
2222
array async base base16-bytestring binary bytestring Cabal
@@ -25,6 +25,7 @@ mkDerivation {
2525
pretty-show process QuickCheck random regex-posix stm tagged tar
2626
tasty tasty-hunit tasty-quickcheck time unix zlib
2727
];
28+
doCheck = false;
2829
postInstall = ''
2930
mkdir $out/etc
3031
mv bash-completion $out/etc/bash_completion.d

default.nix

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ let
1616
in
1717
haskellPackages.override {
1818
overrides = self: super: {
19-
Cabal = filterSource (self.callPackage ./Cabal.nix {});
20-
cabal-install = filterSource (lib.dontCheck (self.callPackage ./cabal-install.nix {}));
19+
Cabal =
20+
filterSource (self.callPackage ./Cabal {});
21+
cabal-install =
22+
filterSource (lib.dontCheck (self.callPackage ./cabal-install {}));
23+
hackage-security =
24+
lib.dontCheck super.hackage-security;
2125
};
2226
}

0 commit comments

Comments
 (0)