aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix
diff options
context:
space:
mode:
authorMx Kookie <kookie@spacekookie.de>2020-10-31 19:35:09 +0100
committerMx Kookie <kookie@spacekookie.de>2020-10-31 19:35:09 +0100
commitc4625b175f8200f643fd6e11010932ea44c78433 (patch)
treebce3f89888c8ac3991fa5569a878a9eab6801ccc /infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix
parent49f735974dd103039ddc4cb576bb76555164a9e7 (diff)
parentd661aa56a8843e991261510c1bb28fdc2f6975ae (diff)
Add 'infra/libkookie/' from commit 'd661aa56a8843e991261510c1bb28fdc2f6975ae'
git-subtree-dir: infra/libkookie git-subtree-mainline: 49f735974dd103039ddc4cb576bb76555164a9e7 git-subtree-split: d661aa56a8843e991261510c1bb28fdc2f6975ae
Diffstat (limited to 'infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix')
-rw-r--r--infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix329
1 files changed, 329 insertions, 0 deletions
diff --git a/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix b/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix
new file mode 100644
index 000000000000..1418cfef0574
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix
@@ -0,0 +1,329 @@
+# This expression takes a file like `hackage-packages.nix` and constructs
+# a full package set out of that.
+
+{ # package-set used for build tools (all of nixpkgs)
+ buildPackages
+
+, # A haskell package set for Setup.hs, compiler plugins, and similar
+ # build-time uses.
+ buildHaskellPackages
+
+, # package-set used for non-haskell dependencies (all of nixpkgs)
+ pkgs
+
+, # stdenv to use for building haskell packages
+ stdenv
+
+, haskellLib
+
+, # hashes for downloading Hackage packages
+ all-cabal-hashes
+
+, # compiler to use
+ ghc
+
+, # A function that takes `{ pkgs, stdenv, callPackage }` as the first arg and
+ # `self` as second, and returns a set of haskell packages
+ package-set
+
+, # The final, fully overriden package set usable with the nixpkgs fixpoint
+ # overriding functionality
+ extensible-self
+}:
+
+# return value: a function from self to the package set
+self:
+
+let
+ inherit (stdenv) buildPlatform hostPlatform;
+
+ inherit (stdenv.lib) fix' extends makeOverridable;
+ inherit (haskellLib) overrideCabal;
+
+ mkDerivationImpl = pkgs.callPackage ./generic-builder.nix {
+ inherit stdenv;
+ nodejs = buildPackages.nodejs-slim;
+ inherit (self) buildHaskellPackages ghc ghcWithHoogle ghcWithPackages;
+ inherit (self.buildHaskellPackages) jailbreak-cabal;
+ hscolour = overrideCabal self.buildHaskellPackages.hscolour (drv: {
+ isLibrary = false;
+ doHaddock = false;
+ hyperlinkSource = false; # Avoid depending on hscolour for this build.
+ postFixup = "rm -rf $out/lib $out/share $out/nix-support";
+ });
+ cpphs = overrideCabal (self.cpphs.overrideScope (self: super: {
+ mkDerivation = drv: super.mkDerivation (drv // {
+ enableSharedExecutables = false;
+ enableSharedLibraries = false;
+ doHaddock = false;
+ useCpphs = false;
+ });
+ })) (drv: {
+ isLibrary = false;
+ postFixup = "rm -rf $out/lib $out/share $out/nix-support";
+ });
+ };
+
+ mkDerivation = makeOverridable mkDerivationImpl;
+
+ # manualArgs are the arguments that were explictly passed to `callPackage`, like:
+ #
+ # callPackage foo { bar = null; };
+ #
+ # here `bar` is a manual argument.
+ callPackageWithScope = scope: fn: manualArgs:
+ let
+ # this code is copied from callPackage in lib/customisation.nix
+ #
+ # we cannot use `callPackage` here because we want to call `makeOverridable`
+ # on `drvScope` (we cannot add `overrideScope` after calling `callPackage` because then it is
+ # lost on `.override`) but determine the auto-args based on `drv` (the problem here
+ # is that nix has no way to "passthrough" args while preserving the reflection
+ # info that callPackage uses to determine the arguments).
+ drv = if stdenv.lib.isFunction fn then fn else import fn;
+ auto = builtins.intersectAttrs (stdenv.lib.functionArgs drv) scope;
+
+ # this wraps the `drv` function to add a `overrideScope` function to the result.
+ drvScope = allArgs: drv allArgs // {
+ overrideScope = f:
+ let newScope = mkScope (fix' (extends f scope.__unfix__));
+ # note that we have to be careful here: `allArgs` includes the auto-arguments that
+ # weren't manually specified. If we would just pass `allArgs` to the recursive call here,
+ # then we wouldn't look up any packages in the scope in the next interation, because it
+ # appears as if all arguments were already manually passed, so the scope change would do
+ # nothing.
+ in callPackageWithScope newScope drv manualArgs;
+ };
+ in stdenv.lib.makeOverridable drvScope (auto // manualArgs);
+
+ mkScope = scope: let
+ ps = pkgs.__splicedPackages;
+ scopeSpliced = pkgs.splicePackages {
+ pkgsBuildBuild = scope.buildHaskellPackages.buildHaskellPackages;
+ pkgsBuildHost = scope.buildHaskellPackages;
+ pkgsBuildTarget = {};
+ pkgsHostHost = {};
+ pkgsHostTarget = scope;
+ pkgsTargetTarget = {};
+ } // {
+ # Don't splice these
+ inherit (scope) ghc buildHaskellPackages;
+ };
+ in ps // ps.xorg // ps.gnome2 // { inherit stdenv; } // scopeSpliced;
+ defaultScope = mkScope self;
+ callPackage = drv: args: callPackageWithScope defaultScope drv args;
+
+ withPackages = packages: buildPackages.callPackage ./with-packages-wrapper.nix {
+ inherit (self) ghc llvmPackages;
+ inherit packages;
+ };
+
+ # Use cabal2nix to create a default.nix for the package sources found at 'src'.
+ haskellSrc2nix = { name, src, sha256 ? null, extraCabal2nixOptions ? "" }:
+ let
+ sha256Arg = if sha256 == null then "--sha256=" else ''--sha256="${sha256}"'';
+ in buildPackages.stdenv.mkDerivation {
+ name = "cabal2nix-${name}";
+ nativeBuildInputs = [ buildPackages.cabal2nix-unwrapped ];
+ preferLocalBuild = true;
+ allowSubstitutes = false;
+ phases = ["installPhase"];
+ LANG = "en_US.UTF-8";
+ LOCALE_ARCHIVE = pkgs.lib.optionalString (buildPlatform.libc == "glibc") "${buildPackages.glibcLocales}/lib/locale/locale-archive";
+ installPhase = ''
+ export HOME="$TMP"
+ mkdir -p "$out"
+ cabal2nix --compiler=${self.ghc.haskellCompilerName} --system=${hostPlatform.config} ${sha256Arg} "${src}" ${extraCabal2nixOptions} > "$out/default.nix"
+ '';
+ };
+
+ all-cabal-hashes-component = name: version: buildPackages.runCommand "all-cabal-hashes-component-${name}-${version}" {} ''
+ tar --wildcards -xzvf ${all-cabal-hashes} \*/${name}/${version}/${name}.{json,cabal}
+ mkdir -p $out
+ mv */${name}/${version}/${name}.{json,cabal} $out
+ '';
+
+ hackage2nix = name: version: let component = all-cabal-hashes-component name version; in self.haskellSrc2nix {
+ name = "${name}-${version}";
+ sha256 = ''$(sed -e 's/.*"SHA256":"//' -e 's/".*$//' "${component}/${name}.json")'';
+ src = "${component}/${name}.cabal";
+ };
+
+ # Adds a nix file as an input to the haskell derivation it
+ # produces. This is useful for callHackage / callCabal2nix to
+ # prevent the generated default.nix from being garbage collected
+ # (requiring it to be frequently rebuilt), which can be an
+ # annoyance.
+ callPackageKeepDeriver = src: args:
+ overrideCabal (self.callPackage src args) (orig: {
+ preConfigure = ''
+ # Generated from ${src}
+ ${orig.preConfigure or ""}
+ '';
+ passthru = orig.passthru or {} // {
+ # When using callCabal2nix or callHackage, it is often useful
+ # to debug a failure by inspecting the Nix expression
+ # generated by cabal2nix. This can be accessed via this
+ # cabal2nixDeriver field.
+ cabal2nixDeriver = src;
+ };
+ });
+
+in package-set { inherit pkgs stdenv callPackage; } self // {
+
+ inherit mkDerivation callPackage haskellSrc2nix hackage2nix buildHaskellPackages;
+
+ inherit (haskellLib) packageSourceOverrides;
+
+ # callHackage :: Text -> Text -> AttrSet -> HaskellPackage
+ #
+ # e.g., while overriding a package set:
+ # '... foo = self.callHackage "foo" "1.5.3" {}; ...'
+ callHackage = name: version: callPackageKeepDeriver (self.hackage2nix name version);
+
+ # callHackageDirect
+ # :: { pkg :: Text, ver :: Text, sha256 :: Text }
+ # -> AttrSet
+ # -> HaskellPackage
+ #
+ # This function does not depend on all-cabal-hashes and therefore will work
+ # for any version that has been released on hackage as opposed to only
+ # versions released before whatever version of all-cabal-hashes you happen
+ # to be currently using.
+ callHackageDirect = {pkg, ver, sha256}:
+ let pkgver = "${pkg}-${ver}";
+ in self.callCabal2nix pkg (pkgs.fetchzip {
+ url = "mirror://hackage/${pkgver}/${pkgver}.tar.gz";
+ inherit sha256;
+ });
+
+ # Creates a Haskell package from a source package by calling cabal2nix on the source.
+ callCabal2nixWithOptions = name: src: extraCabal2nixOptions: args:
+ let
+ filter = path: type:
+ pkgs.lib.hasSuffix "${name}.cabal" path ||
+ baseNameOf path == "package.yaml";
+ expr = self.haskellSrc2nix {
+ inherit name extraCabal2nixOptions;
+ src = if pkgs.lib.canCleanSource src
+ then pkgs.lib.cleanSourceWith { inherit src filter; }
+ else src;
+ };
+ in overrideCabal (callPackageKeepDeriver expr args) (orig: {
+ inherit src;
+ });
+
+ callCabal2nix = name: src: args: self.callCabal2nixWithOptions name src "" args;
+
+ # : { root : Path
+ # , name : Defaulted String
+ # , source-overrides : Defaulted (Either Path VersionNumber)
+ # , overrides : Defaulted (HaskellPackageOverrideSet)
+ # , modifier : Defaulted
+ # , returnShellEnv : Defaulted
+ # } -> NixShellAwareDerivation
+ # Given a path to a haskell package directory, an optional package name
+ # which defaults to the base name of the path, an optional set of source
+ # overrides as appropriate for the 'packageSourceOverrides' function, an
+ # optional set of arbitrary overrides, and an optional haskell package
+ # modifier, return a derivation appropriate for nix-build or nix-shell to
+ # build that package.
+ developPackage =
+ { root
+ , name ? builtins.baseNameOf root
+ , source-overrides ? {}
+ , overrides ? self: super: {}
+ , modifier ? drv: drv
+ , returnShellEnv ? pkgs.lib.inNixShell }:
+ let drv =
+ (extensible-self.extend
+ (pkgs.lib.composeExtensions
+ (self.packageSourceOverrides source-overrides)
+ overrides))
+ .callCabal2nix name root {};
+ in if returnShellEnv then (modifier drv).env else modifier drv;
+
+ ghcWithPackages = selectFrom: withPackages (selectFrom self);
+
+ ghcWithHoogle = selectFrom:
+ let
+ packages = selectFrom self;
+ hoogle = callPackage ./hoogle.nix {
+ inherit packages;
+ };
+ in withPackages (packages ++ [ hoogle ]);
+
+ # Returns a derivation whose environment contains a GHC with only
+ # the dependencies of packages listed in `packages`, not the
+ # packages themselves. Using nix-shell on this derivation will
+ # give you an environment suitable for developing the listed
+ # packages with an incremental tool like cabal-install.
+ # In addition to the "packages" arg and "withHoogle" arg, anything that
+ # can be passed into stdenv.mkDerivation can be included in the input attrset
+ #
+ # # default.nix
+ # with import <nixpkgs> {};
+ # haskellPackages.extend (haskell.lib.packageSourceOverrides {
+ # frontend = ./frontend;
+ # backend = ./backend;
+ # common = ./common;
+ # })
+ #
+ # # shell.nix
+ # let pkgs = import <nixpkgs> {} in
+ # (import ./.).shellFor {
+ # packages = p: [p.frontend p.backend p.common];
+ # withHoogle = true;
+ # buildInputs = [ pkgs.python ];
+ # }
+ #
+ # -- cabal.project
+ # packages:
+ # frontend/
+ # backend/
+ # common/
+ #
+ # bash$ nix-shell --run "cabal new-build all"
+ # bash$ nix-shell --run "python"
+ shellFor = { packages, withHoogle ? false, ... } @ args:
+ let
+ combinedPackageFor = packages:
+ let
+ selected = packages self;
+
+ pname = if pkgs.lib.length selected == 1
+ then (pkgs.lib.head selected).name
+ else "packages";
+
+ # If `packages = [ a b ]` and `a` depends on `b`, don't build `b`,
+ # because cabal will end up ignoring that built version, assuming
+ # new-style commands.
+ combinedPackages = pkgs.lib.filter
+ (input: pkgs.lib.all (p: input.outPath or null != p.outPath) selected);
+
+ # Returns an attrset containing a combined list packages' inputs for each
+ # stage of the build process
+ packageInputs = pkgs.lib.zipAttrsWith
+ (_: pkgs.lib.concatMap combinedPackages)
+ (map (p: p.getCabalDeps) selected);
+
+ genericBuilderArgs = {
+ inherit pname;
+ version = "0";
+ license = null;
+ } // packageInputs;
+
+ in self.mkDerivation genericBuilderArgs;
+
+ mkDerivationArgs = builtins.removeAttrs args [ "packages" "withHoogle" ];
+ in ((combinedPackageFor packages).envFunc { inherit withHoogle; }).overrideAttrs (old: mkDerivationArgs // {
+ nativeBuildInputs = old.nativeBuildInputs ++ mkDerivationArgs.nativeBuildInputs or [];
+ buildInputs = old.buildInputs ++ mkDerivationArgs.buildInputs or [];
+ });
+
+ ghc = ghc // {
+ withPackages = self.ghcWithPackages;
+ withHoogle = self.ghcWithHoogle;
+ };
+
+ }