diff --git a/static-stack/README.md b/static-stack/README.md index 72b6b45..d1ea995 100644 --- a/static-stack/README.md +++ b/static-stack/README.md @@ -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) diff --git a/static-stack/default.nix b/static-stack/default.nix index 8c1f324..6b62c07 100644 --- a/static-stack/default.nix +++ b/static-stack/default.nix @@ -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 + ''; + }); + } diff --git a/static-stack/stack-libyaml-dependency-name-cabal2nix-issue-378.patch b/static-stack/stack-libyaml-dependency-name-cabal2nix-issue-378.patch deleted file mode 100644 index 8400578..0000000 --- a/static-stack/stack-libyaml-dependency-name-cabal2nix-issue-378.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- stack-v1.9.nix 2018-09-16 20:08:30.683765233 +0200 -+++ stack.nix 2018-09-17 00:27:52.851814672 +0200 -@@ -41164,7 +41164,7 @@ - ({ mkDerivation, aeson, attoparsec, base, bytestring, conduit - , containers, directory, filepath, mtl, resourcet, scientific - , stdenv, template-haskell, text, transformers -- , unordered-containers, vector, yaml -+ , unordered-containers, vector, libyaml - }: - mkDerivation { - pname = "yaml"; -@@ -41178,13 +41178,13 @@ - filepath mtl resourcet scientific template-haskell text - transformers unordered-containers vector - ]; -- librarySystemDepends = [ yaml ]; -+ librarySystemDepends = [ libyaml ]; - doHaddock = false; - doCheck = false; - homepage = "https://github.com/snoyberg/yaml#readme"; - description = "Support for parsing and rendering YAML documents"; - license = stdenv.lib.licenses.bsd3; -- }) {inherit (pkgs) yaml;}; -+ }) {inherit (pkgs) libyaml;}; - "yes-precure5-command" = callPackage - ({ mkDerivation, base, Cabal, containers, mtl, parsec, random - , stdenv diff --git a/survey/default.nix b/survey/default.nix index e608f54..2ab5891 100644 --- a/survey/default.nix +++ b/survey/default.nix @@ -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 @@ -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 @@ -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 =