diff --git a/default.nix b/default.nix index 1af82296a3..f672e1c104 100644 --- a/default.nix +++ b/default.nix @@ -2,6 +2,9 @@ let name = "postgrest"; + compiler = + "ghc883"; + # PostgREST source files, filtered based on the rules in the .gitignore files # and file extensions. We want to include as litte as possible, as the files # added here will increase the space used in the Nix store and trigger the @@ -11,10 +14,13 @@ let (pkgs.gitignoreSource ./.) [ ".cabal" ".hs" ".lhs" "LICENSE" ]; + # Commit of the Nixpkgs repository that we want to use. nixpkgsVersion = import nix/nixpkgs-version.nix; - pinnedPkgs = + # Nix files that describe the Nixpkgs repository. We evaluate the expression + # using `import` below. + nixpkgs = builtins.fetchTarball { url = "https://github.com/nixos/nixpkgs/archive/${nixpkgsVersion.rev}.tar.gz"; sha256 = nixpkgsVersion.tarballHash; @@ -27,8 +33,9 @@ let (import nix/overlays/haskell-packages) ]; + # Evaluated expression of the Nixpkgs repository. pkgs = - import pinnedPkgs { inherit overlays; }; + import nixpkgs { inherit overlays; }; postgresqlVersions = [ @@ -40,22 +47,39 @@ let pkgs.postgresql_9_4 ]; + patches = + pkgs.callPackage nix/patches {}; + + # Base dynamic derivation for the PostgREST package. drv = pkgs.haskellPackages.callCabal2nix name src {}; + + # Static derivation for the PostgREST executable. + drvStatic = + import nix/static { inherit nixpkgs name src compiler patches; }; + + lib = + pkgs.haskell.lib; in rec { - inherit pkgs pinnedPkgs; + inherit nixpkgs pkgs; # Derivation for the PostgREST Haskell package, including the executable, # libraries and documentation. We disable running the test suite on Nix # builds, as they require a database to be set up. postgrestWithLib = - pkgs.haskell.lib.dontCheck drv; + lib.dontCheck drv; # Derivation for just the PostgREST binary, where we strip all dynamic - # libraries and documentation, leaving only the executable. + # libraries and documentation, leaving only the executable. Note that the + # executable is static with regards to Haskell libraries, but not system + # libraries like glibc and libpq. postgrest = - pkgs.haskell.lib.justStaticExecutables postgrestWithLib; + lib.justStaticExecutables postgrestWithLib; + + # Static executable. + postgrestStatic = + lib.justStaticExecutables (lib.dontCheck drvStatic); # Environment in which PostgREST can be built with cabal, useful e.g. for # defining a shell for nix-shell. diff --git a/nix/patches/default.nix b/nix/patches/default.nix new file mode 100644 index 0000000000..8cad309cef --- /dev/null +++ b/nix/patches/default.nix @@ -0,0 +1,25 @@ +{ runCommand }: + +{ + # Apply patches to a directory. + applyPatches = + name: path: patches: + runCommand name { inherit patches; } + '' + set -eou pipefail + + cp -r ${path} $out + chmod -R u+w $out + + for patch in $patches; do + echo "Applying patch $patch" + patch -d "$out" -p1 < "$patch" + done + ''; + + static-haskell-nix-postgrest-libpq = + ./static-haskell-nix-postgrest-libpq.patch; + + nixpkgs-revert-ghc-bootstrap = + ./nixpkgs-revert-ghc-bootstrap.patch; +} diff --git a/nix/patches/nixpkgs-revert-ghc-bootstrap.patch b/nix/patches/nixpkgs-revert-ghc-bootstrap.patch new file mode 100644 index 0000000000..0d562cda18 --- /dev/null +++ b/nix/patches/nixpkgs-revert-ghc-bootstrap.patch @@ -0,0 +1,125 @@ +From 93cc144b215654ca9cb0d2bcb58bb8922895ccab Mon Sep 17 00:00:00 2001 +From: Remo +Date: Sat, 25 Apr 2020 17:31:55 +0200 +Subject: [PATCH] Revert "ghc: 8.6.3-binary -> 8.6.5-binary" + +This reverts commit 3c7ef6bcd85e3e133ac6f2ab5e238934d56d902e. +--- + .../{8.6.5-binary.nix => 8.6.3-binary.nix} | 13 ++++++------ + pkgs/top-level/haskell-packages.nix | 20 +++++++++---------- + 2 files changed, 16 insertions(+), 17 deletions(-) + rename pkgs/development/compilers/ghc/{8.6.5-binary.nix => 8.6.3-binary.nix} (95%) + +diff --git a/pkgs/development/compilers/ghc/8.6.5-binary.nix b/pkgs/development/compilers/ghc/8.6.3-binary.nix +similarity index 95% +rename from pkgs/development/compilers/ghc/8.6.5-binary.nix +rename to pkgs/development/compilers/ghc/8.6.3-binary.nix +index 97793d912895..9e0fd12b96cf 100644 +--- a/pkgs/development/compilers/ghc/8.6.5-binary.nix ++++ b/pkgs/development/compilers/ghc/8.6.3-binary.nix +@@ -27,19 +27,18 @@ let + in + + stdenv.mkDerivation rec { +- version = "8.6.5"; ++ version = "8.6.3"; + + name = "ghc-${version}-binary"; + +- # https://downloads.haskell.org/~ghc/8.6.5/ + src = fetchurl ({ + i686-linux = { +- url = "http://haskell.org/ghc/dist/${version}/ghc-${version}-i386-deb9-linux.tar.xz"; +- sha256 = "1p2h29qghql19ajk755xa0yxkn85slbds8m9n5196ris743vkp8w"; ++ url = "http://haskell.org/ghc/dist/${version}/ghc-${version}-i386-deb8-linux.tar.xz"; ++ sha256 = "0bw8a7fxcbskf93rb4m542ff66vrmx5i5kj77qx37cbhijx70w5m"; + }; + x86_64-linux = { +- url = "http://haskell.org/ghc/dist/${version}/ghc-${version}-x86_64-deb9-linux.tar.xz"; +- sha256 = "1pqlx6rdjs2110g0y1i9f8x18lmdizibjqd15f5xahcz39hgaxdw"; ++ url = "http://haskell.org/ghc/dist/${version}/ghc-${version}-x86_64-deb8-linux.tar.xz"; ++ sha256 = "1m9gaga2pzi2cx5gvasg0rx1dlvr68gmi20l67652kag6xjsa719"; + }; + aarch64-linux = { + url = "http://haskell.org/ghc/dist/${version}/ghc-${version}-aarch64-ubuntu18.04-linux.tar.xz"; +@@ -47,7 +46,7 @@ stdenv.mkDerivation rec { + }; + x86_64-darwin = { + url = "http://haskell.org/ghc/dist/${version}/ghc-${version}-x86_64-apple-darwin.tar.xz"; +- sha256 = "0s9188vhhgf23q3rjarwhbr524z6h2qga5xaaa2pma03sfqvvhfz"; ++ sha256 = "1hbzk57v45176kxcx848p5jn5p1xbp2129ramkbzsk6plyhnkl3r"; + }; + }.${stdenv.hostPlatform.system} + or (throw "cannot bootstrap GHC on this platform")); +diff --git a/pkgs/top-level/haskell-packages.nix b/pkgs/top-level/haskell-packages.nix +index aa7ef02a3886..712a98e147e0 100644 +--- a/pkgs/top-level/haskell-packages.nix ++++ b/pkgs/top-level/haskell-packages.nix +@@ -4,7 +4,7 @@ let + # These are attributes in compiler and packages that don't support integer-simple. + integerSimpleExcludes = [ + "ghc822Binary" +- "ghc865Binary" ++ "ghc863Binary" + "ghc844" + "ghcjs" + "ghcjs86" +@@ -42,7 +42,7 @@ in { + + ghc822Binary = callPackage ../development/compilers/ghc/8.2.2-binary.nix { }; + +- ghc865Binary = callPackage ../development/compilers/ghc/8.6.5-binary.nix { }; ++ ghc863Binary = callPackage ../development/compilers/ghc/8.6.3-binary.nix { }; + + ghc844 = callPackage ../development/compilers/ghc/8.4.4.nix { + bootPkgs = packages.ghc822Binary; +@@ -57,31 +57,31 @@ in { + llvmPackages = pkgs.llvmPackages_6; + }; + ghc881 = callPackage ../development/compilers/ghc/8.8.1.nix { +- bootPkgs = packages.ghc865Binary; ++ bootPkgs = packages.ghc863Binary; + inherit (buildPackages.python3Packages) sphinx; + buildLlvmPackages = buildPackages.llvmPackages_7; + llvmPackages = pkgs.llvmPackages_7; + }; + ghc882 = callPackage ../development/compilers/ghc/8.8.2.nix { +- bootPkgs = packages.ghc865Binary; ++ bootPkgs = packages.ghc863Binary; + inherit (buildPackages.python3Packages) sphinx; + buildLlvmPackages = buildPackages.llvmPackages_7; + llvmPackages = pkgs.llvmPackages_7; + }; + ghc883 = callPackage ../development/compilers/ghc/8.8.3.nix { +- bootPkgs = packages.ghc865Binary; ++ bootPkgs = packages.ghc863Binary; + inherit (buildPackages.python3Packages) sphinx; + buildLlvmPackages = buildPackages.llvmPackages_7; + llvmPackages = pkgs.llvmPackages_7; + }; + ghc8101 = callPackage ../development/compilers/ghc/8.10.1.nix { +- bootPkgs = packages.ghc865Binary; ++ bootPkgs = packages.ghc863Binary; + inherit (buildPackages.python3Packages) sphinx; + buildLlvmPackages = buildPackages.llvmPackages_9; + llvmPackages = pkgs.llvmPackages_9; + }; + ghcHEAD = callPackage ../development/compilers/ghc/head.nix { +- bootPkgs = packages.ghc883; # no binary yet ++ bootPkgs = packages.ghc863Binary; + inherit (buildPackages.python3Packages) sphinx; + buildLlvmPackages = buildPackages.llvmPackages_9; + llvmPackages = pkgs.llvmPackages_9; +@@ -118,9 +118,9 @@ in { + compilerConfig = callPackage ../development/haskell-modules/configuration-ghc-8.2.x.nix { }; + packageSetConfig = bootstrapPackageSet; + }; +- ghc865Binary = callPackage ../development/haskell-modules { +- buildHaskellPackages = bh.packages.ghc865Binary; +- ghc = bh.compiler.ghc865Binary; ++ ghc863Binary = callPackage ../development/haskell-modules { ++ buildHaskellPackages = bh.packages.ghc863Binary; ++ ghc = bh.compiler.ghc863Binary; + compilerConfig = callPackage ../development/haskell-modules/configuration-ghc-8.6.x.nix { }; + packageSetConfig = bootstrapPackageSet; + }; diff --git a/nix/patches/static-haskell-nix-postgrest-libpq.patch b/nix/patches/static-haskell-nix-postgrest-libpq.patch new file mode 100644 index 0000000000..56919a73ff --- /dev/null +++ b/nix/patches/static-haskell-nix-postgrest-libpq.patch @@ -0,0 +1,25 @@ +From bb4c1e27e391eff01591fe60830ff68a9ada41ef Mon Sep 17 00:00:00 2001 +From: Remo +Date: Wed, 22 Apr 2020 11:58:07 +0200 +Subject: [PATCH] Add postgrest libpq linking fix + +--- + survey/default.nix | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/survey/default.nix b/survey/default.nix +index b28606c..fd7cde7 100644 +--- a/survey/default.nix ++++ b/survey/default.nix +@@ -1052,6 +1052,11 @@ let + super.squeal-postgresql + [ final.openssl ] + "--libs openssl"; ++ postgrest = ++ addStaticLinkerFlagsWithPkgconfig ++ super.postgrest ++ [ final.openssl ] ++ "--libs openssl"; + + xml-to-json = + addStaticLinkerFlagsWithPkgconfig diff --git a/nix/static/Cabal.nix b/nix/static/Cabal.nix new file mode 100644 index 0000000000..879af33810 --- /dev/null +++ b/nix/static/Cabal.nix @@ -0,0 +1,90 @@ +{ mkDerivation +, array +, base +, base-compat +, base-orphans +, binary +, bytestring +, containers +, deepseq +, Diff +, directory +, filepath +, integer-logarithms +, mtl +, optparse-applicative +, parsec +, pretty +, process +, QuickCheck +, stdenv +, stm +, tagged +, tar +, tasty +, tasty-golden +, tasty-hunit +, tasty-quickcheck +, temporary +, text +, time +, transformers +, tree-diff +, unix +}: +mkDerivation { + pname = "Cabal"; + version = "3.0.0.0"; + sha256 = "5143ec26d740c1a508c93a8860e64407e7546c29b9817db20ff1595c1968d287"; + setupHaskellDepends = [ mtl parsec ]; + libraryHaskellDepends = [ + array + base + binary + bytestring + containers + deepseq + directory + filepath + mtl + parsec + pretty + process + text + time + transformers + unix + ]; + testHaskellDepends = [ + array + base + base-compat + base-orphans + binary + bytestring + containers + deepseq + Diff + directory + filepath + integer-logarithms + optparse-applicative + pretty + process + QuickCheck + stm + tagged + tar + tasty + tasty-golden + tasty-hunit + tasty-quickcheck + temporary + text + tree-diff + ]; + doCheck = false; + homepage = "http://www.haskell.org/cabal/"; + description = "A framework for packaging Haskell software"; + license = stdenv.lib.licenses.bsd3; +} diff --git a/nix/static/default.nix b/nix/static/default.nix new file mode 100644 index 0000000000..7b987e06af --- /dev/null +++ b/nix/static/default.nix @@ -0,0 +1,89 @@ +# Turn a Haskell source package (given its name and source) into a derivation +# for a fully static executable. +{ nixpkgs, compiler, name, src, patches }: +let + # The nh2/static-haskell-nix project does all the hard work for us for + # building static Haskell executables. We apply a patch for PostgREST below + # until the respective pull request is merged. See: + # https://github.com/nh2/static-haskell-nix/pull/91 + # statix-haskell-nix builds everything based on Musl instead of glibc, so + # there will be a _lot_ to rebuild if you don't use a binary cache. + static-haskell-nix = + let + rev = "749707fc90b781c3e653e67917a7d571fe82ae7b"; + in + builtins.fetchTarball { + url = "https://github.com/nh2/static-haskell-nix/archive/${rev}.tar.gz"; + sha256 = "155spda2lww378bhx68w6dxwqd5y6s9kin3qbgl2m23r3vmk3m3w"; + }; + + patched-static-haskell-nix = + patches.applyPatches "patched-static-haskell-nix" static-haskell-nix + [ + patches.static-haskell-nix-postgrest-libpq + ]; + + haskellPackagesOverrides = + lib: final: prev: + { + # Add our source package. + "${name}" = prev.callCabal2nix name src {}; + + # cabal2nix depends on Cabal 3.0.*, while our pinned version of Nixpkgs + # only provides 2.4 or 3.2. So we pinned 3.0.0.0 in ./Cabal.nix + cabal2nix = + prev.cabal2nix.overrideScope + (self: super: { Cabal = self.callPackage ./Cabal.nix {}; }); + + # Pinned version of protolude. + protolude = + prev.callPackage ../overlays/haskell-packages/protolude.nix {}; + + # The tests for the packages below took a long time on static + # builds, so we disable them for now - to be investigated. + happy = lib.dontCheck prev.happy; + }; + + # This overlay adds our source package and applies adjustments to the + # derivation of other packages that it depends on. The overlay applies to + # Haskell packages for the given compiler, which we will later use + # with the static-haskell-nix survey. + overlay = + self: super: + # Override the set of Haskell packages at + # pkgs.haskell.packages."${compiler}". + { + haskell = super.haskell // { + packages = super.haskell.packages // { + "${compiler}" = + super.haskell.packages."${compiler}".override + { overrides = haskellPackagesOverrides self.haskell.lib; }; + }; + }; + }; + + patchedNixpkgs = + patches.applyPatches "patched-nixpkgs" nixpkgs + [ + patches.nixpkgs-revert-ghc-bootstrap + ]; + + # Apply our overlay to the given pkgs. + normalPkgs = + (import patchedNixpkgs {}).appendOverlays [ overlay ]; + + # Each version of GHC needs a specific version of Cabal. + defaultCabalPackageVersionComingWithGhc = + { + ghc883 = "Cabal_3_2_0_0"; + }."${compiler}"; + + # Let the static-haskell-nix project do the hard work of deriving a set of + # fully static Haskell executables, including one for the our source package + # that we added through the overlay. + survey = + import "${patched-static-haskell-nix}/survey" + { inherit normalPkgs compiler defaultCabalPackageVersionComingWithGhc; }; +in + # Return the fully static derivation of our source package. +survey.haskellPackages."${name}" diff --git a/shell.nix b/shell.nix index 5d2723330e..53d37a1d68 100644 --- a/shell.nix +++ b/shell.nix @@ -17,7 +17,7 @@ pkgs.lib.overrideDerivation env ( '' # Set our pinned version of Nixpkgs in the NIX_PATH so that # `stack --nix` also uses that version. - NIX_PATH="nixpkgs=${pinnedPkgs}" + NIX_PATH="nixpkgs=${nixpkgs}" ''; } )