Skip to content

Commit

Permalink
Port static-stack to static-stack2nix-builder.
Browse files Browse the repository at this point in the history
Drastically simplifies it.

Fix fallout:

* Add sqlite override for `persistent-sqlite`.
* Override stack release flags that `stack2nix`/`cabal2nix` now add.
* Mark ghc822 as supported, as the stack build tests it.
* Remove superfluous addition of Cabal to `libraryHaskellDepends`.
  • Loading branch information
nh2 committed May 23, 2019
1 parent 7609657 commit 725ceb2
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 140 deletions.
7 changes: 3 additions & 4 deletions static-stack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

This builds a fully statically linked `stack` executable that should work on any 64-bit Linux distribution.

It uses nix's cross-compilation support to build everything, including `ghc`, against the `musl` libc.
It uses nix to build everything, including `ghc`, against the `musl` libc.

## Building

```
$(nix-build --no-out-link -A stack2nix-script) /path/to/stack/source
$(nix-build --no-out-link -A build-script)
$(nix-build --no-link -A run-stack2nix-and-static-build-script --argstr stackDir /absolute/path/to/stack/source)
```

We use the `$(nix-build ...)` script approach in order to pin the version of `nix` itself for reproducibility.
We use the `$(nix-build ...)` script approach in order to pin the version of `nix` itself for reproducibility, and because the call to `stack2nix` needs Internet access and thus has to run outside of the nix build sandbox.

## Binary caches for faster building (optional)

Expand Down
147 changes: 43 additions & 104 deletions static-stack/default.nix
Original file line number Diff line number Diff line change
@@ -1,113 +1,52 @@
{
release ? false,
}:
# Builds a static `stack` executable from a stack source dir.
#
# Usage:
#
# $(nix-build --no-out-link -A stack2nix-script) /path/to/stack/source --stack-yaml stack-nightly.yaml && nix-build --no-out-link -A static_stack
#
# We do it this way instead of writing a derivation that
# does that for you because as of writing, `stack2nix` doesn't support
# being run from within a nix build, because it calls `cabal update`.
# $(nix-build --no-link -A run-stack2nix-and-static-build-script --argstr stackDir /absolute/path/to/stack/source)
{
stackDir ? "/absolute/path/to/stack/source",
}:
let
pyopenssl-fix-test-buffer-size-overlay = final: previous: {
python36 = previous.python36.override {
packageOverrides = self: super: {
cython = super.cython.overridePythonAttrs (old: rec {
# TODO Cython tests for unknown reason hang with musl. Remove when that's fixed.
# See https://github.com/nh2/static-haskell-nix/issues/6#issuecomment-421852854
doCheck = false;
});
pyopenssl = super.pyopenssl.overridePythonAttrs (old: rec {
patches = [
# TODO Remove when https://github.com/pyca/pyopenssl/commit/b2777a465b669fb647dbac0a92919cb05458707b is available in nixpkgs
(final.fetchpatch {
name = "wantWriteError-test-buffer-size.patch";
url = "https://github.com/pyca/pyopenssl/commit/b2777a465b669fb647dbac0a92919cb05458707b.patch";
sha256 = "0igksnl0cd5cx8f38bfjdriwdrzbw6ciy0hs805s84mprfwhck8d";
})
];
});
};
};
};

normalPkgs = import (fetchTarball https://github.com/nh2/nixpkgs/archive/442912b4f19644311700b43b3b5247c6291d785a.tar.gz) {};

# In `survey` we provide a nixpkgs set with some fixes; import it here.
pkgs = (import ../survey/default.nix {
inherit normalPkgs;
overlays = [ pyopenssl-fix-test-buffer-size-overlay ];
}).pkgs;
upstreamNixpkgs = import ../nixpkgs {};

# TODO Use `pkgs.stack2nix` instead of this once `stack2nix` 0.2 is in `pkgs`
stack2nix_src = pkgs.fetchFromGitHub {
owner = "input-output-hk";
repo = "stack2nix";
rev = "v0.2.1";
sha256 = "1ihcp3mr0s89xmc81f9hxq07jw6pm3lixr5bdamqiin1skpk8q3b";
static-stack2nix-builder = import ../static-stack2nix-builder/default.nix {
cabalPackageName = "stack";
normalPkgs = upstreamNixpkgs;
compiler = "ghc822"; # matching stack.yaml
hackageSnapshot = "2019-05-08T00:00:00Z"; # pins e.g. extra-deps without hashes or revisions
stack2nix-stack-project-dir = stackDir; # where stack.yaml is
# disableOptimization = true; # for compile speed
};
stack2nix = import (stack2nix_src + "/default.nix") {};

# Script that runs `stack2nix` on a given stack source dir.
# Arguments given to the script are given to `stack2nix`.
# Running the script creates file `stack.nix`.
stack2nix-script =
# `stack2nix` requires `cabal` on $PATH.
# We put our nixpkgs's version of `nix` on $PATH for reproducibility.
pkgs.writeScript "stack2nix-build-script.sh" ''
#!/usr/bin/env bash
set -eu -o pipefail
PATH=${pkgs.cabal-install}/bin:${normalPkgs.nix}/bin:$PATH ${stack2nix}/bin/stack2nix -o stack.nix $@
'';

# Apply patch to generated stack2nix output to work around
# 'libyaml' dependency to be named 'yaml'; see
# https://github.com/NixOS/cabal2nix/issues/378
# Note this patch depends on
# https://github.com/commercialhaskell/stack/blob/a2489de02/stack.yaml#L27
# which includes
# https://github.com/snoyberg/yaml/pull/151/commits/ba216731cd5bf4264e9ad95d55616ff1a9edfac5
# This patch doesn't apply and can be removed if either
# * the `stack` version to be compiled has `yaml` older than in the line mentioned above, or
# * the `cabal2nix` version in use has https://github.com/NixOS/cabal2nix/commit/67e3189f fixed
stack2nix-output = pkgs.runCommand "stack.nix-patched" {} ''
cp ${./stack.nix} $out
patch -p1 $out ${./stack-libyaml-dependency-name-cabal2nix-issue-378.patch}
'';

enableCabalFlags = flags: drv: builtins.foldl' (d: flag: pkgs.haskell.lib.enableCabalFlag d flag) drv flags;
setStackFlags = drv:
if release
then enableCabalFlags [ "hide-dependency-versions" "supported-build" ] drv
else drv;
# Builds a static stack executable from a `stack.nix` file generated
# with `stack2nix`.
static_stack = setStackFlags (import ../survey/default.nix {
normalPkgs = pkgs;
normalHaskellPackages = import stack2nix-output {
inherit pkgs;
};
}).haskellPackages.stack;
# TODO check if `overrideCabal super.stack (old: { executableToolDepends = [ pkgs.git ]; })`
# is necessary here now that it's removed from `survey`

# Script that runs `nix-build` to build the final executable.
# We do this to fix the version of `nix` to the one in our nixpkgs
# for reproducibility, as changing nix versions can change the build env.
# Arguments given to the script are given to `nix-build`.
build-script =
pkgs.writeScript "stack-build-script.sh" ''
#!/usr/bin/env bash
set -eu -o pipefail
set -x
${normalPkgs.nix}/bin/nix-build --no-out-link -A static_stack $@
'';

in {
inherit pkgs;
inherit stack2nix-script;
inherit static_stack;
inherit build-script;
}
in
static-stack2nix-builder // {
static_package =
with upstreamNixpkgs.haskell.lib;
overrideCabal
(appendConfigureFlags
static-stack2nix-builder.static_package
[
# Official release flags:
"-fsupported-build"
"-fhide-dependency-versions"
"-f-disable-git-info" # stack2nix turns that on, we turn it off again
]
)
(old: {
# Enabling git info needs these extra deps.
# TODO Make `stack2nix` accept per-package Cabal flags,
# so that `cabal2nix` would automatically add
# the right dependencies for us.
executableHaskellDepends = (old.executableHaskellDepends or []) ++
(with static-stack2nix-builder.haskell-static-nix_output.haskellPackages; [
githash
optparse-simple
]);
# Put `git` on PATH, because `githash` calls it.
preConfigure = ''
export PATH=${upstreamNixpkgs.git}/bin:$PATH
git --version
'';
});
}

This file was deleted.

24 changes: 19 additions & 5 deletions survey/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ in

defaultCabalPackageVersionComingWithGhc ?
({
ghc822 = throw "static-haskell-nix: ghc822 wasn't tried yet with the static nix Cabal patch; please try and PR it";
ghc822 = "Cabal_2_2_0_1"; # TODO this is technically incorrect for ghc 8.2.2, should be 2.0.1.0, but nixpkgs doesn't have that
ghc844 = "Cabal_2_2_0_1";
ghc863 = throw "static-haskell-nix: ghc863 is no longer supported, please upgrade";
ghc864 = "Cabal_2_4_1_0"; # TODO this is technically incorrect for ghc 8.6.4, should be 2.4.0.1, but nixpkgs doesn't have that
Expand Down Expand Up @@ -413,10 +413,17 @@ let
# here, so we use the `haskellPackagesWithLibsReadyForStaticLinking`
# one instead which has set `Cabal = ...` appropriately.
setupHaskellDepends = patchCabalInPackageList ((old.setupHaskellDepends or []) ++ [fixedCabal]);
# We also need to add the fixed cabal to the normal dependencies,
# for the case that the package itself depends on Cabal; see note
# [Fixed Cabal for Setup.hs->somePackage->Cabal dependencies].
libraryHaskellDepends = patchCabalInPackageList ((old.libraryHaskellDepends or []) ++ [fixedCabal]);
# We don't need to add it to `libraryHaskellDepends` (see note
# [Fixed Cabal for Setup.hs->somePackage->Cabal dependencies])
# here because we already add it to the package set itself
# down in `haskellLibsReadyForStaticLinkingOverlay`.
# In fact, adding it here breaks e.g. the example in
# `static-stack`, because `stack2nix` adds stacks specified
# `Cabal` dependency as `libraryHaskellDepends`
# (which is then patched via `applyPatchesToCabalDrv` in
# `haskellLibsReadyForStaticLinkingOverlay`) and adding
# it here would add a second, different Cabal version to the
# ghc package DB.
})).overrideAttrs (old: {
# Adding the fixed Cabal version to `setupHaskellDepends` is not enough:
# There may already be one in there, in which case GHC picks an
Expand Down Expand Up @@ -813,6 +820,13 @@ let
];
}))).override { openblasCompat = final.openblasCompat; };

# TODO Find out why this is needed.
# Without this, the stack in `./static-stack` doesn't link,
# complaining `cannot find -lsqlite3`.
# `persistent-sqlite` should already be using `final.sqlite`,
# but apparently it's not.
persistent-sqlite = super.persistent-sqlite.override { sqlite = final.sqlite; };

# TODO For the below packages, it would be better if we could somehow make all users
# of postgresql-libpq link in openssl via pkgconfig.
postgresql-schema =
Expand Down

0 comments on commit 725ceb2

Please sign in to comment.