Skip to content

Commit 5884ab0

Browse files
authored
Overlays (#261)
The Overlays branch This is a major reorganization in how haskell.nix is used, and marks our 1.0 release. The branch doesn't build due to numerous issues that we believe to be with the CI and not this branch. We expect only very minor adjustments prior to calling this the official 1.0 release. * Move iohk-nix patches into haskell.nix This moves the customizations we did in iohk-nix into haskell.nix via overlays and config. Add bootPkgs logic this moves the nuking of bootPkgs where it belongs. This should eventually still be removed and replaced by a proper solution, that doesn't require the nuking of bootPkgs. Allow us to bootstrap binary ghcs and a cabal-install With this we can do the following: ``` $ nix repl compiler/old-ghc-nix nix-repl> :b (let pkgs = import <nixpkgs> {}; in with import ./. {}; import ./compiler/bootstrap/cabal-install.nix { inherit (pkgs) fetchurl stdenv zlib; inherit hackage ; ghc = ghc844; src = pkgs.fetchurl { url = "https://github.com/haskell/cabal/archive/Cabal-v3.0.0.0-rc3.tar.gz"; sha256 = "1zl2mgg8307ykq3v8nmafc6zdhhj1cw7w8ffpap16dsm6 5lbnx33"; }; }) ``` which wile it may look daunting, will allow us to bootstrap a cabal-install with a ghc. From that point onwards, we should be able to build any hackage package via haskell.nix. Pass through cabal-install version Better threading of arguments. Add bootstrap overlay Allow alex + happy to be built This still has a wart: we need nix-tools, and for that we use the ghc865 from nixpkgs. Ideally we'd build nix-tools against a specific ghc, but then we'd need a build expression for that. Make ghcjs work Building something like this: ``` nix build '(with import ./. { nixpkgs = ../nixpkgs; nixpkgsArgs = { crossSystem = { config = "js-unknown-ghcjs"; }; }; }; (haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2"; })).components.exes.hello' ``` will now work. Assuming `nixpkgs` has been appropriately patched to support the `js-unknown-ghcjs` triple. Also: this will need an additional `Cabal` patch, to make `Cabal` understand what it needs to do with: `dist/build/hello/hello: copyFile: does not exist (No such file or directory)` It needs to learn that `dist/build/hello/hello.jsexe` is what it wants to copy and that that is a directory. Luckily we do have some code in Cabal already that does this for `.exe` on windows. Build `js-unknown-ghcjs` packages with haskell.nix Using the following expression: ``` with import ./. { nixpkgs = ../nixpkgs; nixpkgsArgs = { crossSystem = { config = "js-unknown-ghcjs"; }; }; }; let Cabal = buildPackages.haskell-nix.hackage-package { name = "Cabal"; version = "2.4.1.0"; modules = [ { packages.Cabal.patches = [ ./Cabal-install-folder.diff ]; } ]; }; in (haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2"; modules = [ ({config, ... }:{ packages.hello.package.setup-depends = [ Cabal ]; }) ];}).components.exes.hello ``` in a `test.nix` file. And running ``` nix build -f ./test.nix ``` on it, will produce ``` ./result ├── bin │ └── hello.jsexe │ ├── all.js │ ├── all.js.externs │ ├── index.html │ ├── lib.js │ ├── manifest.webapp │ ├── out.frefs.js │ ├── out.frefs.json │ ├── out.js │ ├── out.stats │ ├── rts.js │ └── runmain.js └── share └── doc └── x86_64-linux-ghc-8.6.5 └── hello-1.0.0.2 └── LICENSE 6 directories, 12 files ```
1 parent 6ad351e commit 5884ab0

File tree

107 files changed

+33061
-443
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+33061
-443
lines changed

.gitattributes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
# Hide stuff that is generated by nix-tools plan-to-nix
33

44
nix-tools/.plan.nix/*.nix linguist-generated=true
5-
nix-tools/.plan-pkgs.nix linguist-generated=true
5+
nix-tools/pkgs.nix linguist-generated=true
66
.stack-to-nix.cache linguist-generated=true

README.org

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,53 @@
88
=haskell.nix= is an experimental new builder for Haskell packages.
99

1010
It works by automatically translating your Cabal or Stack project and
11-
its dependencies into Nix code. Most of your dependencies are already
12-
translated, so you generally won't have too much generated code.
11+
its dependencies into Nix code. It provides IFD (imports from derviation)
12+
functions that can minimize the amount of nix code you need to add.
1313

1414
For the documentation, see https://input-output-hk.github.io/haskell.nix/.
1515

1616
** Quickstart
1717

18-
This will download and build =nix-tools=.
18+
For =cabal.project= project add a =default.nix=:
1919

2020
#+begin_src sh
21-
nix build -f https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz nix-tools -o nt
22-
./nt/bin/stack-to-nix
21+
{ pkgs ? import <nixpkgs> (import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz))
22+
, haskellCompiler ? "ghc865"
23+
}:
24+
pkgs.haskell-nix.cabalProject {
25+
src = pkgs.haskell-nix.haskellLib.cleanGit { src = ./.; };
26+
ghc = pkgs.buildPackages.pkgs.haskell.compiler.${haskellCompiler};
27+
}
28+
#+end_src
29+
30+
For a =stack.yaml= project add a =default.nix=:
31+
32+
#+begin_src sh
33+
{ pkgs ? import <nixpkgs> (import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz))
34+
}:
35+
pkgs.haskell-nix.stackProject {
36+
src = pkgs.haskell-nix.haskellLib.cleanGit { src = ./.; };
37+
}
38+
#+end_src
39+
40+
To build the library component of a package in the project run:
41+
42+
#+begin_src sh
43+
nix build -f . your-package-name.components.library
44+
#+end_src
45+
46+
To build an executable:
47+
48+
#+begin_src sh
49+
nix build -f . your-package-name.components.exes.your-exe-name
50+
#+end_src
51+
52+
To open a shell for use with `cabal` run:
53+
54+
#+begin_src sh
55+
nix-shell -A shellFor
56+
cabal new-build your-package-name
57+
cabal new-repl your-package-name:library:your-package-name
2358
#+end_src
2459

2560
** Related repos

build.nix

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,32 @@
33
# It is separate from default.nix because that file is the public API
44
# of Haskell.nix, which shouldn't have tests, etc.
55

6-
{ pkgs ? import nixpkgs nixpkgsArgs
7-
, nixpkgs ? ./nixpkgs
6+
{ nixpkgs ? ./nixpkgs
87
# Provide args to the nixpkgs instantiation.
98
, system ? builtins.currentSystem
109
, crossSystem ? null
1110
, config ? {}
12-
, nixpkgsArgs ? { inherit system crossSystem config; }
11+
, nixpkgsArgs ? { inherit system crossSystem; }
1312
}:
1413

1514
let
16-
haskell = import ./default.nix { inherit pkgs; };
15+
haskellNixArgs = import ./default.nix;
16+
pkgs = import nixpkgs ({
17+
config = haskellNixArgs.config // config;
18+
overlays = haskellNixArgs.overlays ++
19+
[(self: super: {
20+
darcs = (self.haskell-nix.hackage-package {
21+
name = "darcs";
22+
version = "2.14.2";
23+
# Apply the latest darcs.net Setup.hs patches
24+
modules = [{packages.darcs.patches = [ ./patches/darcs-setup.patch ];}];
25+
}).components.exes.darcs;
26+
})]; } // nixpkgsArgs);
27+
haskell = pkgs.haskell-nix;
1728

1829
in {
1930
inherit (haskell) nix-tools source-pins;
20-
tests = import ./test/default.nix { inherit haskell; };
31+
tests = import ./test/default.nix { inherit nixpkgs nixpkgsArgs; };
2132

2233
# Scripts for keeping Hackage and Stackage up to date, and CI tasks.
2334
maintainer-scripts = pkgs.dontRecurseIntoAttrs {

builder/comp-builder.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ stdenv.mkDerivation ({
191191
buildPhase = ''
192192
runHook preBuild
193193
# https://gitlab.haskell.org/ghc/ghc/issues/9221
194-
$SETUP_HS build -j$(($NIX_BUILD_CORES > 4 ? 4 : $NIX_BUILD_CORES)) ${lib.concatStringsSep " " (component.setupBuildFlags ++ setupGhcOptions)}
194+
$SETUP_HS build ${haskellLib.componentTarget componentId} -j$(($NIX_BUILD_CORES > 4 ? 4 : $NIX_BUILD_CORES)) ${lib.concatStringsSep " " (component.setupBuildFlags ++ setupGhcOptions)}
195195
runHook postBuild
196196
'';
197197

builder/default.nix

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, buildGHC, fetchurl, pkgconfig, nonReinstallablePkgs, hsPkgs }:
1+
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, fetchurl, pkgconfig, nonReinstallablePkgs, hsPkgs }:
22

33
let
44
# Builds a single component of a package.
@@ -7,7 +7,7 @@ let
77
};
88

99
setup-builder = haskellLib.weakCallPackage pkgs ./setup-builder.nix {
10-
ghc = buildGHC;
10+
ghc = (ghc.passthru.buildGHC or ghc);
1111
hsPkgs = hsPkgs.buildPackages;
1212
inherit haskellLib nonReinstallablePkgs makeSetupConfigFiles;
1313
};
@@ -28,7 +28,7 @@ let
2828
# When building setup depends we need to use the build systems GHC and Packages
2929
makeSetupConfigFiles = haskellLib.weakCallPackage buildPackages ./make-config-files.nix {
3030
inherit haskellLib nonReinstallablePkgs;
31-
ghc = buildGHC;
31+
ghc = (ghc.passthru.buildGHC or ghc);
3232
};
3333

3434

@@ -57,7 +57,7 @@ in {
5757
# Build a Haskell package from its config.
5858
# TODO: this pkgs is the adjusted pkgs, but pkgs.pkgs is unadjusted
5959
build-package = haskellLib.weakCallPackage pkgs ./hspkg-builder.nix {
60-
inherit haskellLib ghc buildGHC comp-builder setup-builder;
60+
inherit haskellLib ghc comp-builder setup-builder;
6161
};
6262

6363
inherit shellFor;

builder/ghc-for-component-wrapper.nix

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ in runCommand "${componentName}-${ghc.name}" {
4040
rm -rf ${libDir}/*/
4141
# ... but retain the lib/ghc/bin directory. This contains `unlit' and friends.
4242
ln -s ${ghc}/lib/${ghcCommand}-${ghc.version}/bin ${libDir}
43+
# ... and the ghcjs shim's if they are available
44+
if [ -d ${ghc}/lib/${ghcCommand}-${ghc.version}/shims ]; then
45+
ln -s ${ghc}/lib/${ghcCommand}-${ghc.version}/shims ${libDir}
46+
fi
4347
# Replace the package database with the one from target package config.
4448
ln -s ${configFiles}/package.conf.d ${packageCfgDir}
4549

builder/hspkg-builder.nix

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, buildGHC, fetchurl, runCommand, comp-builder, setup-builder }:
1+
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, fetchurl, runCommand, comp-builder, setup-builder }:
22

33

44
{ flags
@@ -30,17 +30,17 @@ let
3030
import Distribution.Simple
3131
main = defaultMain
3232
'';
33-
defaultSetup = buildPackages.runCommand "default-Setup" { nativeBuildInputs = [buildGHC]; } ''
33+
defaultSetup = buildPackages.runCommand "default-Setup" { nativeBuildInputs = [(ghc.passthru.buildGHC or ghc)]; } ''
3434
cat ${defaultSetupSrc} > Setup.hs
3535
mkdir -p $out/bin
36-
${buildGHC.targetPrefix}ghc Setup.hs --make -o $out/bin/Setup
36+
${(ghc.passthru.buildGHC or ghc).targetPrefix}ghc Setup.hs --make -o $out/bin/Setup
3737
'';
3838

39-
setup = if package.buildType == "Simple"
39+
setup = if package.buildType == "Simple" && package.setup-depends == []
4040
then defaultSetup
4141
else setup-builder {
4242
setup-depends = package.setup-depends;
43-
inherit package name src flags;
43+
inherit package name src flags revision patches defaultSetupSrc;
4444
};
4545

4646
buildComp = componentId: component: comp-builder {

builder/make-config-files.nix

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ let
2828
# so we are dealing with a sublib. As we build sublibs separately, the above
2929
# query should be safe.
3030
echo "--dependency=''${name#z-${p}-z-}=$id" >> $out/configure-flags
31-
fi
31+
fi
3232
if ver=$(target-pkg ${pdbArg} field ${p} version --simple-output); then
3333
echo "constraint: ${p} == $ver" >> $out/cabal.config
3434
echo "constraint: ${p} installed" >> $out/cabal.config
@@ -105,6 +105,9 @@ in { identifier, component, fullName, flags ? {} }:
105105
#
106106
# TODO: Fix Cabal.
107107
# TODO: this is only needed if we do dynamic libraries.
108+
#
109+
# NOTE [ln -s -f]: we force link, as we may have dependencies that contain shared deps
110+
# (e.g. libiconv), and thus we don't want to fail, but just link it again.
108111
+ lib.optionalString stdenv.isDarwin ''
109112
# Work around a limit in the macOS Sierra linker on the number of paths
110113
# referenced by any one dynamic library:
@@ -114,7 +117,7 @@ in { identifier, component, fullName, flags ? {} }:
114117
local dynamicLinksDir="$out/lib/links"
115118
mkdir -p $dynamicLinksDir
116119
for d in $(grep dynamic-library-dirs "$out/package.conf.d/"*|awk '{print $2}'|sort -u); do
117-
ln -s "$d/"*.dylib $dynamicLinksDir
120+
ln -f -s "$d/"*.dylib $dynamicLinksDir
118121
done
119122
# Edit the local package DB to reference the links directory.
120123
for f in "$out/package.conf.d/"*.conf; do

builder/setup-builder.nix

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{ stdenv, lib, buildPackages, haskellLib, ghc, nonReinstallablePkgs, hsPkgs, makeSetupConfigFiles }:
22

3-
{ setup-depends, package, name, src, flags }:
3+
{ setup-depends, package, name, src, flags, revision, patches, defaultSetupSrc }:
44

55
let
66
component = {
@@ -34,7 +34,7 @@ let
3434

3535
in
3636
stdenv.lib.fix (drv:
37-
stdenv.mkDerivation {
37+
stdenv.mkDerivation ({
3838
name = "${fullName}";
3939
src = cleanSrc;
4040
nativeBuildInputs = [ghc];
@@ -45,8 +45,11 @@ in
4545
inherit configFiles cleanSrc;
4646
};
4747

48-
phases = ["unpackPhase" "buildPhase" "installPhase"];
48+
phases = ["unpackPhase" "patchPhase" "buildPhase" "installPhase"];
4949
buildPhase = ''
50+
if [[ ! -f ./Setup.hs && ! -f ./Setup.lhs ]]; then
51+
cat ${defaultSetupSrc} > Setup.hs
52+
fi
5053
for f in Setup.hs Setup.lhs; do
5154
if [ -f $f ]; then
5255
echo Compiling package $f
@@ -62,4 +65,6 @@ in
6265
mkdir -p $out/bin
6366
install ./Setup $out/bin/Setup
6467
'';
65-
})
68+
}
69+
// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }
70+
))

0 commit comments

Comments
 (0)