From 3e305ac373d7c8b2cda14d0b0b53437a3979343c Mon Sep 17 00:00:00 2001 From: Gabriel Gonzalez Date: Fri, 20 Jul 2018 19:45:27 -0700 Subject: [PATCH] Build a completely static Dhall executable in CI This adds a new `dhall-static` target that builds a fully static `dhall` executable that can be run on any Linux machine (i.e. it is a relocatable executable that is completely dependency free). That in turns implies that even though it is built with Nix it doesn't require that the user installs Nix to run it (i.e. no dependency on the `/nix/store` or a Nix installer). Just copy the standalone executable to any Linux machine and it's good to go. This based on the following work of @nh2: * https://github.com/NixOS/nixpkgs/issues/43795 * https://github.com/dhall-lang/dhall-lang/issues/192#issuecomment-406134451 This also bumps the version of `nixpkgs` used for the normal (non-static) Dhall build to be the closest revision on `nixpkgs` `master` as the one used by @nh2 in his work. Once that work is merged into `nixpkgs` `master` then both builds can use the same revision from `nixpkgs` `master`. --- default.nix | 128 ++++++++++++++++++++++++++++++++++++------- nix/fetchNixpkgs.nix | 3 +- release.nix | 2 +- 3 files changed, 111 insertions(+), 22 deletions(-) diff --git a/default.nix b/default.nix index 9a581d750..12b6ea270 100644 --- a/default.nix +++ b/default.nix @@ -1,41 +1,127 @@ let fetchNixpkgs = import ./nix/fetchNixpkgs.nix; + readDirectory = import ./nix/readDirectory.nix; + + overlayShared = pkgsNew: pkgsOld: { + haskellPackages = pkgsOld.haskellPackages.override (old: { + overrides = + let + extension = + haskellPackagesNew: haskellPackagesOld: { + dhall = + pkgsNew.haskell.lib.failOnAllWarnings + haskellPackagesOld.dhall; + + prettyprinter = + pkgsNew.haskell.lib.dontCheck + haskellPackagesOld.prettyprinter; + }; + + in + pkgsNew.lib.fold + pkgsNew.lib.composeExtensions + (old.overrides or (_: _: {})) + [ (readDirectory ./nix) + + extension + ]; + } + ); + }; + nixpkgs = fetchNixpkgs { - rev = "804060ff9a79ceb0925fe9ef79ddbf564a225d47"; + rev = "2c07921cff84dfb0b9e0f6c2d10ee2bfee6a85ac"; - sha256 = "01pb6p07xawi60kshsxxq1bzn8a0y4s5jjqvhkwps4f5xjmmwav3"; + sha256 = "09cfdbrzy3wfpqd3nkahv0jqfynpxy4kpcxq0gab0pq9a8bia6sg"; - outputSha256 = "0ga345hgw6v2kzyhvf5kw96hf60mx5pbd9c4qj5q4nan4lr7nkxn"; + outputSha256 = "1sxh54zxqy54vrak203qci4128z9mxnzfr5bb5pl6xdrdkcdpqrn"; }; - readDirectory = import ./nix/readDirectory.nix; + pkgs = import nixpkgs { config = {}; overlays = [ overlayShared ]; }; + + overlayStaticLinux = pkgsNew: pkgsOld: { + cabal_patched_src = pkgsNew.fetchFromGitHub { + owner = "nh2"; + repo = "cabal"; + rev = "748f07b50724f2618798d200894f387020afc300"; + sha256 = "1k559m291f6spip50rly5z9rbxhfgzxvaz64cx4jqpxgfhbh2gfs"; + }; - config = { - packageOverrides = pkgs: { - haskellPackages = pkgs.haskellPackages.override { + Cabal_patched_Cabal_subdir = pkgsNew.stdenv.mkDerivation { + name = "cabal-dedupe-src"; + buildCommand = '' + cp -rv ${pkgsNew.cabal_patched_src}/Cabal/ $out + ''; + }; + + haskell = pkgsOld.haskell // { + lib = pkgsOld.haskell.lib // { + useFixedCabal = drv: pkgsNew.haskell.lib.overrideCabal drv (old: { + setupHaskellDepends = + (old.setupHaskellDepends or []) ++ [ + pkgsNew.haskellPackages.Cabal_patched + ]; + + libraryHaskellDepends = + (old.libraryHaskellDepends or []) ++ [ + pkgsNew.haskellPackages.Cabal_patched + ]; + } + ); + + statify = drv: + pkgsNew.lib.foldl pkgsNew.haskell.lib.appendConfigureFlag + (pkgsNew.haskell.lib.disableLibraryProfiling + (pkgsNew.haskell.lib.disableSharedExecutables + (pkgsNew.haskell.lib.useFixedCabal drv) + ) + ) + [ "--enable-executable-static" + "--extra-lib-dirs=${pkgsNew.gmp6.override { withStatic = true; }}/lib" + "--extra-lib-dirs=${pkgsNew.zlib.static}/lib" + "--extra-lib-dirs=${pkgsNew.ncurses.override { enableStatic = true; }}/lib" + ]; + }; + }; + + haskellPackages = pkgsOld.haskellPackages.override (old: { overrides = let - manualOverrides = + extension = haskellPackagesNew: haskellPackagesOld: { - dhall = - pkgs.haskell.lib.failOnAllWarnings - (pkgs.haskell.lib.justStaticExecutables - haskellPackagesOld.dhall - ); + Cabal_patched = + pkgsNew.haskellPackages.callCabal2nix + "Cabal" + pkgsNew.Cabal_patched_Cabal_subdir + { }; - prettyprinter = - pkgs.haskell.lib.dontCheck haskellPackagesOld.prettyprinter; + dhall = pkgsNew.haskell.lib.statify haskellPackagesOld.dhall; }; in - pkgs.lib.composeExtensions (readDirectory ./nix) manualOverrides; - }; - }; + pkgsNew.lib.composeExtensions + (old.overrides or (_: _: {})) + extension; + } + ); + }; + + nixpkgsStaticLinux = fetchNixpkgs { + owner = "nh2"; + + rev = "925aac04f4ca58aceb83beef18cb7dae0715421b"; + + sha256 = "0zkvqzzyf5c742zcl1sqc8009dr6fr1fblz53v8gfl63hzqwj0x4"; + + outputSha256 = "1zr8lscjl2a5cz61f0ibyx55a94v8yyp6sjzjl2gkqjrjbg99abx"; }; - pkgs = - import nixpkgs { inherit config; }; + pkgsStaticLinux = import nixpkgsStaticLinux { + config = {}; + overlays = [ overlayShared overlayStaticLinux ]; + system = "x86_64-linux"; + }; # Derivation that trivially depends on the current directory so that Hydra's # pull request builder always posts a GitHub status on each revision @@ -44,6 +130,8 @@ let in { inherit pwd; + dhall-static = pkgsStaticLinux.pkgsMusl.haskellPackages.dhall; + inherit (pkgs.haskellPackages) dhall; shell = (pkgs.haskell.lib.doBenchmark pkgs.haskellPackages.dhall).env; diff --git a/nix/fetchNixpkgs.nix b/nix/fetchNixpkgs.nix index 478c25d35..d1125ca8a 100644 --- a/nix/fetchNixpkgs.nix +++ b/nix/fetchNixpkgs.nix @@ -1,4 +1,5 @@ { rev # The Git revision of nixpkgs to fetch +, owner ? "NixOS" , sha256 # The SHA256 of the downloaded data , outputSha256 ? null # The SHA256 fixed-output hash , system ? builtins.currentSystem # This is overridable if necessary @@ -17,7 +18,7 @@ then ( else ( (rec { tarball = import { - url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; + url = "https://github.com/${owner}/nixpkgs/archive/${rev}.tar.gz"; inherit sha256; }; diff --git a/release.nix b/release.nix index df554f909..a45776685 100644 --- a/release.nix +++ b/release.nix @@ -2,4 +2,4 @@ let default = (import ./default.nix); in - { inherit (default) pwd dhall; } + { inherit (default) pwd dhall dhall-static; }