From 034dfdbd324402f86fc5a0fde92aaaaa3c037445 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Mon, 21 May 2018 04:03:05 -0400 Subject: [PATCH 01/20] Experimental new generic builder --- nix/cabal-licenses.nix | 5 +- nix/cabal-os-arch-comp.nix | 4 +- nix/default.nix | 46 +++++++++++ nix/lib.nix | 58 ++++++++++++++ nix/new-builder.nix | 151 +++++++++++++++++++++++++++++++++++++ 5 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 nix/default.nix create mode 100644 nix/lib.nix create mode 100644 nix/new-builder.nix diff --git a/nix/cabal-licenses.nix b/nix/cabal-licenses.nix index 01ce63c..304c4c7 100644 --- a/nix/cabal-licenses.nix +++ b/nix/cabal-licenses.nix @@ -1,2 +1,5 @@ stdenv: with stdenv.lib.licenses; -{ BSD-3-Clause = bsd3; } +{ + BSD-3-Clause = bsd3; + MIT = mit; +} diff --git a/nix/cabal-os-arch-comp.nix b/nix/cabal-os-arch-comp.nix index 047cbf0..78dc1a7 100644 --- a/nix/cabal-os-arch-comp.nix +++ b/nix/cabal-os-arch-comp.nix @@ -25,10 +25,10 @@ isNetBSD = false; isDragonFly = false; isSolaris = false; - isAIX = false; + isAix = false; isHPUX = false; isIRIX = false; - isHaLVM = false; + isHalvm = false; isHurd = false; isIOS = false; isAndroid = false; diff --git a/nix/default.nix b/nix/default.nix new file mode 100644 index 0000000..8059777 --- /dev/null +++ b/nix/default.nix @@ -0,0 +1,46 @@ +{ pkgs ? import {} }: + +(pkgs.lib.fix (self: with self; { + inherit (pkgs) lib stdenv; + ghc = pkgs.haskell.compiler.${stackage.compiler.nix-name}; + haskellLib = import ./lib.nix { inherit lib haskellLib; }; + hackage = import ../hackage.nix-master; + stackage = import ../stackage.nix-master/lts-11.7.nix hackage.exprs; + new-builder = pkgs.callPackage ./new-builder.nix { + inherit haskellLib ghc; + inherit (hackage) hashes; + }; + cabal = import ./cabal-os-arch-comp.nix; + + compiler = cabal.compiler // { + isGhc = true; + version = lib.mapAttrs (_: f: v: f (builtins.compareVersions stackage.compiler.version v)) { + eq = c: c == 0; + gt = c: c > 0; + ge = c: c >= 0; + lt = c: c < 0; + le = c: c <= 0; + }; + }; + system = let + os = { + "linux" = "Linux"; + "darwin" = "OSX"; + }.${pkgs.hostPlatform.parsed.kernel.name}; + arch = { + "x86_64" = "X86_64"; + }.${pkgs.hostPlatform.parsed.cpu.name}; + in cabal.os // { "is${os}" = true; } + // cabal.arch // { "is${arch}" = true; }; + + configs = lib.mapAttrs (_: f: import f { + inherit hsPkgs pkgconfPkgs compiler system; + pkgs = pkgs // { + z = pkgs.zlib; + }; + }) stackage.packages; + + pkgconfPkgs = pkgs; + hsPkgs = lib.mapAttrs (_: _: null) stackage.compiler.packages + // lib.mapAttrs (_: new-builder) configs; +})) diff --git a/nix/lib.nix b/nix/lib.nix new file mode 100644 index 0000000..093f253 --- /dev/null +++ b/nix/lib.nix @@ -0,0 +1,58 @@ +{ lib, haskellLib }: + +with haskellLib; + +{ + subComponentTypes = [ + "sublibs" + "foreignlibs" + "exes" + "tests" + "benchmarks" + ]; + + mergeComponents = lib.zipAttrsWith (_: comps: lib.genAttrs [ + "depends" + "libs" + "frameworks" + "pkgconfig" + "build-tools" + ] (n: { + ${n} = lib.concatMap (comp: comp.${n} or []) comps; + })); + + unionrAttrs = lib.foldr (a: b: a // b) {}; + + mergeConfigs = configs: + let + mergeComponentType = type: mergeComponents (map (conf: (conf.components or {}).${type} or {}) configs); + in unionrAttrs configs // { + flags = unionrAttrs (map (conf: conf.flags or {}) configs); + package = lib.foldr (conf: lib.recursiveUpdate (conf.package or {})) {} configs; + components = + mergeComponents (map (conf: removeAttrs (conf.components or {}) subComponentTypes) configs) + // lib.genAttrs subComponentTypes mergeComponentType; + configureFlags = concatMap (conf: conf.configureFlags or []) configs; + }; + + foldrAttrVals = f: z: attrs: + lib.foldr (g: acc: g acc) z (lib.mapAttrsToList f attrs); + + attrLength = attrs: builtins.length (builtins.attrValues attrs); + + foldComponents = tys: f: z: conf: + let + comps = conf.components or {}; + foldSection = foldrAttrVals f; + libComp = acc: + foldSection acc + (removeAttrs comps subComponentTypes); + subComps = acc: + lib.foldr + (ty: acc': foldSection acc' (comps.${ty} or {})) + acc + tys; + in libComp (subComps z); + + hasLibrary = foldComponents [] (_: _: _: true) false; +} diff --git a/nix/new-builder.nix b/nix/new-builder.nix new file mode 100644 index 0000000..3dd894d --- /dev/null +++ b/nix/new-builder.nix @@ -0,0 +1,151 @@ +{ stdenv, lib, haskellLib, ghc, hashes, fetchurl, writeText, runCommand, pkgconfig }: + +{ flags ? {} +, package ? {} +, components ? {} + +, name ? "${package.identifier.name}-${package.identifier.version}" +, sha256 ? hashes.${package.identifier.name}.${package.identifier.version} +, src ? fetchurl { url = "mirror://hackage/${name}.tar.gz"; inherit sha256; } + +, doSublibs ? true +, doForeignLibs ? true +, doExecutables ? true +, doCheck ? false +, doBenchmarks ? false + +, allowNewer ? true +, allowOlder ? false + +, configureFlags ? [] +}@config: + +let + foldEnabledComps = haskellLib.foldComponents ( + lib.optional doSublibs "sublibs" + ++ lib.optional doForeignLibs "foreignlibs" + ++ lib.optional doExecutables "exes" + ++ lib.optional doCheck "tests" + ++ lib.optional doBenchmarks "benchmarks" + ); + + concatFromEnabledComps = name: + builtins.filter (p: p != null) + (foldEnabledComps (_: comp: acc: acc ++ comp.${name} or []) [] config); + + deps = { + depends = + builtins.filter + (p: p.identifier != package.identifier) + (concatFromEnabledComps "depends"); + libs = concatFromEnabledComps "libs"; + frameworks = concatFromEnabledComps "frameworks"; + pkgconfig = concatFromEnabledComps "pkgconfig"; + buildTools = concatFromEnabledComps "build-tools"; + }; + + defaultSetupSrc = builtins.toFile "Setup.hs" '' + import Distribution.Simple + main = defaultMain + ''; + defaultSetup = runCommand "Setup" { nativeBuildInputs = [ghc]; } '' + ghc ${defaultSetupSrc} --make -o $out + ''; + + flagsAndConfig = field: xs: { + flags = map (x: "--${field}=${x}") xs; + config = lib.optional (xs != []) "${field}: ${lib.concatStringsSep " " xs}"; + }; + + allFlagsAndConfigs = { + packageDbs = + let + makePairs = map (p: { key="${p}"; val=p; }); + closure = builtins.genericClosure { + startSet = makePairs deps.depends; + operator = {val,...}: makePairs val.deps.depends; + }; + flatDepends = map ({val,...}: val) closure; + in flagsAndConfig "package-db" (map (p: "${p}/package.conf.d") flatDepends); + + extraLibDirs = flagsAndConfig "extra-lib-dirs" (map (p: "${p}/lib") deps.libs); + extraIncludeDirs = flagsAndConfig "extra-include-dirs" (map (p: "${lib.getDev p}/include") deps.libs); + extraFameworks = flagsAndConfig "extra-framework-dirs" (map (p: "${p}/Library/Frameworks") deps.frameworks); + allowNewer = lib.mapAttrs (_: lib.optional allowNewer) { flags = "--allow-newer"; config = "allow-newer: True"; }; + allowOlder = lib.mapAttrs (_: lib.optional allowOlder) { flags = "--allow-older"; config = "allow-older: True"; }; + userFlags = { + flags = [("--flags=\"" + lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: lib.optionalString (!val) "-" + fname) flags) + "\"")]; + config = []; + }; + }; + + finalConfigureFlags = lib.concatStringsSep " " ( + [ "--prefix=$out" ] + ++ builtins.concatLists (lib.mapAttrsToList (_: x: x.flags) allFlagsAndConfigs) + ++ configureFlags + ); + +in stdenv.mkDerivation { + inherit name src; + passthru = { + inherit deps; + inherit (package) identifier; + }; + + enableParallelBuilding = true; + + meta = { + homepage = package.homepage; + description = package.synopsis; + license = (import ./cabal-licenses.nix stdenv).${package.license}; + }; + + # Environment + CABAL_CONFIG = writeText + "package-db-cabal.config" + (lib.concatStringsSep "\n" (builtins.concatLists (lib.mapAttrsToList (_: x: x.config) allFlagsAndConfigs))); + + # Deps + nativeBuildInputs = + [ghc] + ++ deps.pkgconfig + ++ lib.optional (deps.pkgconfig != []) pkgconfig + ++ deps.buildTools; + + # Phases + configurePhase = '' + setuphs=${defaultSetup} + for f in Setup.hs Setup.lhs; do + if [ -f $f ]; then + if (diff $f ${defaultSetupSrc} > /dev/null); then + setuphs=${defaultSetup} + else + ghc $f --make -o ./Setup + setuphs=$(pwd)/Setup + fi + break + fi + done + echo Configure flags: + printf "%q " ${finalConfigureFlags} + echo + $setuphs configure ${finalConfigureFlags} + ''; + + buildPhase = '' + $setuphs build -j$NIX_BUILD_CORES + ''; + + checkPhase = lib.optionalString doCheck '' + $setuphs test -j$NIX_BUILD_CORES + ''; + + installPhase = '' + $setuphs copy + ${lib.optionalString (haskellLib.hasLibrary config) '' + $setuphs register --gen-pkg-config=${name}.conf + ghc-pkg init $out/package.conf.d + ghc-pkg ${lib.concatStringsSep " " allFlagsAndConfigs.packageDbs.flags} -f $out/package.conf.d register ${name}.conf + ''} + ''; +} From 910ea334550d4342e4cfdb50c0f09d63c659208a Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Sun, 27 May 2018 15:18:20 -0400 Subject: [PATCH 02/20] Per-component building --- nix/cabal-os-arch-comp.nix | 6 +- nix/comp-builder.nix | 104 ++++++++++++++++++++++ nix/default.nix | 49 +++++++--- nix/lib.nix | 19 +++- nix/new-builder.nix | 178 +++++++++++-------------------------- 5 files changed, 212 insertions(+), 144 deletions(-) create mode 100644 nix/comp-builder.nix diff --git a/nix/cabal-os-arch-comp.nix b/nix/cabal-os-arch-comp.nix index 78dc1a7..cdcb45c 100644 --- a/nix/cabal-os-arch-comp.nix +++ b/nix/cabal-os-arch-comp.nix @@ -19,8 +19,8 @@ # OSs isLinux = false; isWindows = false; - isOSX = false; - isFreeBSD = false; + isOsx = false; + isFreebsd = false; isOpenBSD = false; isNetBSD = false; isDragonFly = false; @@ -30,7 +30,7 @@ isIRIX = false; isHalvm = false; isHurd = false; - isIOS = false; + isIos = false; isAndroid = false; isGhcjs = false; }; diff --git a/nix/comp-builder.nix b/nix/comp-builder.nix new file mode 100644 index 0000000..c351364 --- /dev/null +++ b/nix/comp-builder.nix @@ -0,0 +1,104 @@ +{ stdenv, ghc, lib, pkgconfig, writeText, haskellLib }: + +{ componentId +, component +, package +, name +, setup +, src +, flags +}: + +let + flagsAndConfig = field: xs: { + flags = map (x: "--${field}=${x}") xs; + config = lib.optional (xs != []) "${field}: ${lib.concatStringsSep " " xs}"; + }; + + allFlagsAndConfigs = { + packageDbs = + let + makePairs = map (p: rec { key="${val}"; val=p.components.${p.identifier.name}; }); + closure = builtins.genericClosure { + startSet = makePairs component.depends; + operator = {val,...}: makePairs val.config.depends; + }; + flatDepends = map ({val,...}: val) closure; + in flagsAndConfig "package-db" (map (p: "${p}/package.conf.d") flatDepends); + + extraLibDirs = flagsAndConfig "extra-lib-dirs" (map (p: "${p}/lib") component.libs); + extraIncludeDirs = flagsAndConfig "extra-include-dirs" (map (p: "${lib.getDev p}/include") component.libs); + extraFameworks = flagsAndConfig "extra-framework-dirs" (map (p: "${p}/Library/Frameworks") component.frameworks); + allowNewer = lib.mapAttrs (_: lib.optional component.allowNewer) { flags = "--allow-newer"; config = "allow-newer: True"; }; + allowOlder = lib.mapAttrs (_: lib.optional component.allowOlder) { flags = "--allow-older"; config = "allow-older: True"; }; + userFlags = { + flags = [("--flags=\"" + lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: lib.optionalString (!val) "-" + fname) flags) + "\"")]; + config = []; + }; + }; + + finalConfigureFlags = lib.concatStringsSep " " ( + [ "--prefix=$out" "${componentId.ctype}:${componentId.cname}" ] + ++ builtins.concatLists (lib.mapAttrsToList (_: x: x.flags) allFlagsAndConfigs) + ++ component.configureFlags + ); +in stdenv.mkDerivation { + name = "${name}-${componentId.ctype}-${componentId.cname}"; + + inherit src; + + doCheck = componentId.ctype == "test"; + + passthru = { + inherit (package) identifier; + config = component; + }; + + meta = { + homepage = package.homepage; + description = package.synopsis; + license = (import ./cabal-licenses.nix stdenv).${package.license}; + }; + + CABAL_CONFIG = writeText + "package-db-cabal.config" + (lib.concatStringsSep "\n" (builtins.concatLists (lib.mapAttrsToList (_: x: x.config) allFlagsAndConfigs))); + + enableParallelBuilding = true; + + buildInputs = component.libs + ++ component.pkgconfig; + + nativeBuildInputs = + [ghc] + ++ lib.optional (component.pkgconfig != []) pkgconfig + ++ lib.concatMap (c: builtins.attrValues (c.components.exes or {})) component.build-tools; + + SETUP_HS = setup + /bin/Setup; + + # Phases + configurePhase = '' + echo Configure flags: + printf "%q " ${finalConfigureFlags} + echo + $SETUP_HS configure ${finalConfigureFlags} + ''; + + buildPhase = '' + $SETUP_HS build -j$NIX_BUILD_CORES + $SETUP_HS haddock + ''; + + checkPhase = '' + $SETUP_HS test + ''; + + installPhase = '' + $SETUP_HS copy + ${lib.optionalString (haskellLib.isLibrary componentId) '' + $SETUP_HS register --gen-pkg-config=${name}.conf + ghc-pkg init $out/package.conf.d + ghc-pkg ${lib.concatStringsSep " " allFlagsAndConfigs.packageDbs.flags} -f $out/package.conf.d register ${name}.conf + ''} + ''; +} diff --git a/nix/default.nix b/nix/default.nix index 8059777..c7d69e0 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -23,24 +23,47 @@ }; }; system = let - os = { - "linux" = "Linux"; - "darwin" = "OSX"; - }.${pkgs.hostPlatform.parsed.kernel.name}; - arch = { - "x86_64" = "X86_64"; - }.${pkgs.hostPlatform.parsed.cpu.name}; - in cabal.os // { "is${os}" = true; } - // cabal.arch // { "is${arch}" = true; }; + hostMap = import ./host-map.nix pkgs.stdenv; + in cabal.os // { "is${hostMap.os}" = true; } + // cabal.arch // { "is${hostMap.arch}" = true; }; configs = lib.mapAttrs (_: f: import f { - inherit hsPkgs pkgconfPkgs compiler system; + inherit hsPkgs compiler system; pkgs = pkgs // { + pthread = null; + "stdc++" = null; + ssl = pkgs.openssl.dev; + crypto = pkgs.openssl.dev; z = pkgs.zlib; + GL = pkgs.libGL; + GLU = pkgs.libGLU; + alut = pkgs.freealut; + X11 = pkgs.xorg.libX11; + Xrandr = pkgs.xorg.libXrandr; + Xext = pkgs.xorg.libXext; + Xi = pkgs.xorg.libXi; + Xxf86vm = pkgs.xorg.libXxf86vm; + Xcursor = pkgs.xorg.libXcursor; + Xinerama = pkgs.xorg.libXinerama; + mysqlclient = pkgs.mysql; + Imlib2 = pkgs.imlib2; + asound = pkgs.alsaLib; + ffi = null; }; - }) stackage.packages; + pkgconfPkgs = pkgs // { + cairo-pdf = pkgs.cairo; + cairo-ps = pkgs.cairo; + cairo-svg = pkgs.cairo; + xft = pkgs.xorg.libXft; + xau = pkgs.xorg.libXau; + libR = pkgs.R; + fftw3f = pkgs.fftwFloat; + fftw3 = pkgs.fftw; + }; + }) (stackage.packages // { + hello = hackage.exprs.hello."1.0.0.2"; + }); - pkgconfPkgs = pkgs; - hsPkgs = lib.mapAttrs (_: _: null) stackage.compiler.packages + hsPkgs = lib.mapAttrs (_: _: null) (stackage.compiler.packages // { hsc2hs = "0.68.2"; }) // lib.mapAttrs (_: new-builder) configs; })) diff --git a/nix/lib.nix b/nix/lib.nix index 093f253..a0791c0 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -54,5 +54,22 @@ with haskellLib; tys; in libComp (subComps z); - hasLibrary = foldComponents [] (_: _: _: true) false; + componentPrefix = { + # Are all of these right? + sublibs = "sublib"; + foreignlibs = "foreignlib"; + exes = "exe"; + tests = "test"; + benchmarks = "bench"; + }; + + applyComponents = f: comps: + let + libComp = lib.mapAttrs (cname: f {ctype="lib"; inherit cname;}) (removeAttrs comps subComponentTypes); + subComps = lib.mapAttrs + (ctype: lib.mapAttrs (cname: f {inherit cname; ctype=componentPrefix.${ctype};})) + (builtins.intersectAttrs (lib.genAttrs subComponentTypes (_: null)) comps); + in subComps // libComp; + + isLibrary = componentId: componentId.ctype == "lib"; } diff --git a/nix/new-builder.nix b/nix/new-builder.nix index 3dd894d..aafc1e2 100644 --- a/nix/new-builder.nix +++ b/nix/new-builder.nix @@ -1,151 +1,75 @@ -{ stdenv, lib, haskellLib, ghc, hashes, fetchurl, writeText, runCommand, pkgconfig }: +{ stdenv, lib, haskellLib, ghc, hashes, fetchurl, writeText, runCommand, pkgconfig, callPackage }: { flags ? {} , package ? {} , components ? {} , name ? "${package.identifier.name}-${package.identifier.version}" -, sha256 ? hashes.${package.identifier.name}.${package.identifier.version} +, sha256 ? (hashes.${package.identifier.name}.${package.identifier.version} or (throw name)) , src ? fetchurl { url = "mirror://hackage/${name}.tar.gz"; inherit sha256; } - -, doSublibs ? true -, doForeignLibs ? true -, doExecutables ? true -, doCheck ? false -, doBenchmarks ? false - -, allowNewer ? true -, allowOlder ? false - -, configureFlags ? [] }@config: let - foldEnabledComps = haskellLib.foldComponents ( - lib.optional doSublibs "sublibs" - ++ lib.optional doForeignLibs "foreignlibs" - ++ lib.optional doExecutables "exes" - ++ lib.optional doCheck "tests" - ++ lib.optional doBenchmarks "benchmarks" - ); - - concatFromEnabledComps = name: - builtins.filter (p: p != null) - (foldEnabledComps (_: comp: acc: acc ++ comp.${name} or []) [] config); - - deps = { - depends = - builtins.filter - (p: p.identifier != package.identifier) - (concatFromEnabledComps "depends"); - libs = concatFromEnabledComps "libs"; - frameworks = concatFromEnabledComps "frameworks"; - pkgconfig = concatFromEnabledComps "pkgconfig"; - buildTools = concatFromEnabledComps "build-tools"; - }; - defaultSetupSrc = builtins.toFile "Setup.hs" '' import Distribution.Simple main = defaultMain ''; - defaultSetup = runCommand "Setup" { nativeBuildInputs = [ghc]; } '' + defaultSetup = runCommand "default-Setup" { nativeBuildInputs = [ghc]; } '' ghc ${defaultSetupSrc} --make -o $out ''; - flagsAndConfig = field: xs: { - flags = map (x: "--${field}=${x}") xs; - config = lib.optional (xs != []) "${field}: ${lib.concatStringsSep " " xs}"; - }; - - allFlagsAndConfigs = { - packageDbs = - let - makePairs = map (p: { key="${p}"; val=p; }); - closure = builtins.genericClosure { - startSet = makePairs deps.depends; - operator = {val,...}: makePairs val.deps.depends; - }; - flatDepends = map ({val,...}: val) closure; - in flagsAndConfig "package-db" (map (p: "${p}/package.conf.d") flatDepends); - - extraLibDirs = flagsAndConfig "extra-lib-dirs" (map (p: "${p}/lib") deps.libs); - extraIncludeDirs = flagsAndConfig "extra-include-dirs" (map (p: "${lib.getDev p}/include") deps.libs); - extraFameworks = flagsAndConfig "extra-framework-dirs" (map (p: "${p}/Library/Frameworks") deps.frameworks); - allowNewer = lib.mapAttrs (_: lib.optional allowNewer) { flags = "--allow-newer"; config = "allow-newer: True"; }; - allowOlder = lib.mapAttrs (_: lib.optional allowOlder) { flags = "--allow-older"; config = "allow-older: True"; }; - userFlags = { - flags = [("--flags=\"" + lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: lib.optionalString (!val) "-" + fname) flags) + "\"")]; - config = []; - }; - }; - - finalConfigureFlags = lib.concatStringsSep " " ( - [ "--prefix=$out" ] - ++ builtins.concatLists (lib.mapAttrsToList (_: x: x.flags) allFlagsAndConfigs) - ++ configureFlags - ); + setup = stdenv.mkDerivation { + name = "${name}-setup"; + nativeBuildInputs = [ghc]; + inherit src; + phases = ["unpackPhase" "buildPhase" "installPhase"]; + buildPhase = '' + setup=${defaultSetup} + for f in Setup.hs Setup.lhs; do + if [ -f $f ]; then + if ! (diff $f ${defaultSetupSrc} > /dev/null); then + echo Compiling package $f + ghc $f --make -o ./Setup + setup=$(pwd)/Setup + else + echo Using default Setup + fi + break + fi + done + ''; -in stdenv.mkDerivation { - inherit name src; - passthru = { - inherit deps; - inherit (package) identifier; + installPhase = '' + mkdir -p $out/bin + install $setup $out/bin/Setup + ''; }; - enableParallelBuilding = true; + comp-builder = callPackage ./comp-builder.nix { inherit ghc haskellLib; }; - meta = { - homepage = package.homepage; - description = package.synopsis; - license = (import ./cabal-licenses.nix stdenv).${package.license}; + buildComp = componentId: component: comp-builder { + inherit componentId package name src flags setup; + component = + let + nonNullLists = fs: component // lib.genAttrs fs (field: + if component ? ${field} + then builtins.filter (x: x != null) component.${field} + else []); + in { + allowNewer = true; + allowOlder = false; + } // nonNullLists [ + "depends" + "libs" + "frameworks" + "pkgconfig" + "build-tools" + "configureFlags" + ]; }; - # Environment - CABAL_CONFIG = writeText - "package-db-cabal.config" - (lib.concatStringsSep "\n" (builtins.concatLists (lib.mapAttrsToList (_: x: x.config) allFlagsAndConfigs))); - - # Deps - nativeBuildInputs = - [ghc] - ++ deps.pkgconfig - ++ lib.optional (deps.pkgconfig != []) pkgconfig - ++ deps.buildTools; - - # Phases - configurePhase = '' - setuphs=${defaultSetup} - for f in Setup.hs Setup.lhs; do - if [ -f $f ]; then - if (diff $f ${defaultSetupSrc} > /dev/null); then - setuphs=${defaultSetup} - else - ghc $f --make -o ./Setup - setuphs=$(pwd)/Setup - fi - break - fi - done - echo Configure flags: - printf "%q " ${finalConfigureFlags} - echo - $setuphs configure ${finalConfigureFlags} - ''; - - buildPhase = '' - $setuphs build -j$NIX_BUILD_CORES - ''; - - checkPhase = lib.optionalString doCheck '' - $setuphs test -j$NIX_BUILD_CORES - ''; - - installPhase = '' - $setuphs copy - ${lib.optionalString (haskellLib.hasLibrary config) '' - $setuphs register --gen-pkg-config=${name}.conf - ghc-pkg init $out/package.conf.d - ghc-pkg ${lib.concatStringsSep " " allFlagsAndConfigs.packageDbs.flags} -f $out/package.conf.d register ${name}.conf - ''} - ''; +in { + components = haskellLib.applyComponents buildComp components; + inherit (package) identifier; + inherit setup; } From bfcafe5546121a48b522a1780510137b8e387c55 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Mon, 28 May 2018 03:19:37 -0400 Subject: [PATCH 03/20] Adds hackage-to-nix --- .gitmodules | 3 ++ cabal.project | 4 ++- hackage-db | 1 + hackage2nix/Main.hs | 87 +++++++++++++++++++++++++++++++++++++++++++++ lib/Cabal2Nix.hs | 13 +++---- nix-tools.cabal | 18 ++++++++++ 6 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 .gitmodules create mode 160000 hackage-db create mode 100644 hackage2nix/Main.hs diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..687730f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "hackage-db"] + path = hackage-db + url = https://github.com/ElvishJerricco/hackage-db.git diff --git a/cabal.project b/cabal.project index e6fdbad..cf9ee9d 100644 --- a/cabal.project +++ b/cabal.project @@ -1 +1,3 @@ -packages: . +packages: + ./. + ./hackage-db/ diff --git a/hackage-db b/hackage-db new file mode 160000 index 0000000..84ca9fc --- /dev/null +++ b/hackage-db @@ -0,0 +1 @@ +Subproject commit 84ca9fc75ad45a71880e938e0d93ea4bde05f5bd diff --git a/hackage2nix/Main.hs b/hackage2nix/Main.hs new file mode 100644 index 0000000..1d3d664 --- /dev/null +++ b/hackage2nix/Main.hs @@ -0,0 +1,87 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NamedFieldPuns #-} + +module Main +where + +import Cabal2Nix +import Cabal2Nix.Util ( quoted ) +import Crypto.Hash.SHA256 ( hash + , hashlazy + ) +import qualified Data.ByteString.Base16 as Base16 +import qualified Data.ByteString.Char8 as BS +import qualified Data.ByteString.Lazy as BL +import Data.Foldable ( toList ) +import qualified Data.Map as Map +import qualified Data.Sequence as Seq +import Data.String ( IsString(fromString) ) +import Data.Text.Encoding ( decodeUtf8 ) +import Distribution.Hackage.DB ( hackageTarball ) +import qualified Distribution.Hackage.DB.Parsed + as P +import Distribution.Hackage.DB.Parsed ( parseMetaData + , parseVersionData + ) +import Distribution.Hackage.DB.Unparsed +import Distribution.Pretty ( prettyShow + , Pretty + ) +import Nix.Expr +import Nix.Pretty ( prettyNix ) +import System.Directory ( createDirectoryIfMissing ) +import System.Environment ( getArgs ) +import System.FilePath ( () + , (<.>) + ) + +main :: IO () +main = do + [out] <- getArgs + db <- readTarball Nothing =<< hackageTarball + + let defaultNix = seqToSet $ Map.foldMapWithKey package2nix db + createDirectoryIfMissing False out + writeFile (out "default.nix") $ show $ prettyNix defaultNix + + _ <- forWithKey db $ \pname (PackageData { versions }) -> + forWithKey versions $ \vnum vdata@(VersionData { cabalFileRevisions }) -> + let parsedVData = parseVersionData pname vnum vdata + writeFiles gpd cabalFile revNum = do + let dir = out packagePath pname fromPretty vnum + revPath = dir revName revNum + createDirectoryIfMissing True dir + BL.writeFile (revPath <.> "cabal") cabalFile + writeFile (revPath <.> "nix") $ show $ prettyNix $ gpd2nix Nothing Nothing gpd + in sequence $ zipWith3 writeFiles + (toList (P.cabalFileRevisions parsedVData)) + cabalFileRevisions + [(0 :: Int) ..] + return () + where + forWithKey :: Applicative f => Map.Map k v -> (k -> v -> f x) -> f (Map.Map k x) + forWithKey = flip Map.traverseWithKey + seqToSet = mkNonRecSet . toList + fromPretty :: (Pretty a, IsString b) => a -> b + fromPretty = fromString . prettyShow + package2nix pname (PackageData { versions }) = + Seq.singleton $ quoted (fromPretty pname) $= seqToSet + (Map.foldMapWithKey (version2nix pname) versions) + version2nix pname vnum (VersionData { cabalFileRevisions, metaFile }) = + Seq.singleton $ quoted (fromPretty vnum) $= mkRecSet + ( ("revision" $= mkSym (revName $ length cabalFileRevisions - 1)) + : ("sha256" $= mkStr (fromString $ parseMetaData pname vnum metaFile Map.! "sha256")) + : zipWith (revBinding (packagePath pname) vnum) cabalFileRevisions [(0 :: Int) ..] + ) + revName revNum = "r" <> fromString (show revNum) + revBinding ppath vnum cabalFile revNum = + let name :: (IsString a, Semigroup a) => a + name = revName revNum + revPath = "." ppath fromPretty vnum name + in name $= mkNonRecSet + [ "outPath" $= mkRelPath (revPath <.> "nix") + , "cabalFile" $= mkRelPath (revPath <.> "cabal") + , "cabalSha256" $= mkStr (decodeUtf8 $ Base16.encode $ hashlazy cabalFile) + ] + packagePath pname = + BS.unpack (BS.take 30 $ Base16.encode $ hash $ fromPretty pname) ++ "-" ++ fromPretty pname diff --git a/lib/Cabal2Nix.hs b/lib/Cabal2Nix.hs index 2cc018b..1c63d10 100644 --- a/lib/Cabal2Nix.hs +++ b/lib/Cabal2Nix.hs @@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} -module Cabal2Nix (cabal2nix, Src(..), CabalFile(..), CabalFileGenerator(..), cabalFilePath, cabalFilePkgName) where +module Cabal2Nix (cabal2nix, gpd2nix, Src(..), CabalFile(..), CabalFileGenerator(..), cabalFilePath, cabalFilePkgName) where import Distribution.PackageDescription.Parsec (readGenericPackageDescription, parseGenericPackageDescriptionMaybe) import Distribution.Verbosity (normal) @@ -76,13 +76,14 @@ genExtra Hpack = mkNonRecSet [ "cabal-generator" $= mkStr "hpack" ] cabal2nix :: Maybe Src -> CabalFile -> IO NExpr cabal2nix src = \case - (OnDisk path) -> fmap (go Nothing) + (OnDisk path) -> fmap (gpd2nix src Nothing) $ readGenericPackageDescription normal path - (InMemory gen path body) -> fmap (go (Just $ genExtra gen)) + (InMemory gen path body) -> fmap (gpd2nix src (Just $ genExtra gen)) $ maybe (error "Failed to parse in-memory cabal file") pure (parseGenericPackageDescriptionMaybe body) - where go :: Maybe NExpr -> GenericPackageDescription -> NExpr - go extra gpd = mkFunction args . lets gpd $ toNix gpd $//? (toNix <$> src) $//? extra - args :: Params NExpr + +gpd2nix :: Maybe Src -> Maybe NExpr -> GenericPackageDescription -> NExpr +gpd2nix src extra gpd = mkFunction args . lets gpd $ toNix gpd $//? (toNix <$> src) $//? extra + where args :: Params NExpr args = mkParamset [ ("system", Nothing) , ("compiler", Nothing) , ("flags", Just $ mkNonRecSet []) diff --git a/nix-tools.cabal b/nix-tools.cabal index 889b612..ce1eb66 100644 --- a/nix-tools.cabal +++ b/nix-tools.cabal @@ -80,6 +80,24 @@ executable plan-to-nix hs-source-dirs: plan2nix default-language: Haskell2010 +executable hackage-to-nix + ghc-options: -Wall + main-is: Main.hs + build-depends: base >=4.11 && <4.12 + , nix-tools + , hackage-db + , hnix + , Cabal + , containers + , bytestring + , text + , cryptohash-sha256 + , base16-bytestring + , filepath + , directory + hs-source-dirs: hackage2nix + default-language: Haskell2010 + executable lts-to-nix ghc-options: -Wall main-is: Main.hs From 6c9470d4ee233a90953237208c63f77bd4e93a7d Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Mon, 28 May 2018 04:40:56 -0400 Subject: [PATCH 04/20] Use Stackage pinned revisions --- nix/comp-builder.nix | 5 +++++ nix/default.nix | 18 +++++++++++------- nix/new-builder.nix | 9 +++++---- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/nix/comp-builder.nix b/nix/comp-builder.nix index c351364..8f508d6 100644 --- a/nix/comp-builder.nix +++ b/nix/comp-builder.nix @@ -7,6 +7,7 @@ , setup , src , flags +, cabalFile }: let @@ -77,6 +78,10 @@ in stdenv.mkDerivation { SETUP_HS = setup + /bin/Setup; # Phases + prePatch = lib.optionalString (cabalFile != null) '' + cat ${cabalFile} > ${package.identifier.name}.cabal + ''; + configurePhase = '' echo Configure flags: printf "%q " ${finalConfigureFlags} diff --git a/nix/default.nix b/nix/default.nix index c7d69e0..d5cafce 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -4,11 +4,14 @@ inherit (pkgs) lib stdenv; ghc = pkgs.haskell.compiler.${stackage.compiler.nix-name}; haskellLib = import ./lib.nix { inherit lib haskellLib; }; - hackage = import ../hackage.nix-master; - stackage = import ../stackage.nix-master/lts-11.7.nix hackage.exprs; + hackage = import ../hackage; + stackage = import ../stackage/lts-11.11.nix (lib.mapAttrs (_: p: + lib.mapAttrs (ver: revs: lib.mapAttrs' (_: rev: + {name = rev.cabalSha256; value = revs // {revision = rev;};} + ) (builtins.removeAttrs revs ["revision" "sha256"])) p + ) hackage); new-builder = pkgs.callPackage ./new-builder.nix { inherit haskellLib ghc; - inherit (hackage) hashes; }; cabal = import ./cabal-os-arch-comp.nix; @@ -27,7 +30,7 @@ in cabal.os // { "is${hostMap.os}" = true; } // cabal.arch // { "is${hostMap.arch}" = true; }; - configs = lib.mapAttrs (_: f: import f { + configs = lib.mapAttrs (_: f: import f.revision { inherit hsPkgs compiler system; pkgs = pkgs // { pthread = null; @@ -60,9 +63,10 @@ fftw3f = pkgs.fftwFloat; fftw3 = pkgs.fftw; }; - }) (stackage.packages // { - hello = hackage.exprs.hello."1.0.0.2"; - }); + } // { + inherit (f) sha256; + cabalFile = if f.revision == f.r0 then null else f.revision.cabalFile; + }) stackage.packages; hsPkgs = lib.mapAttrs (_: _: null) (stackage.compiler.packages // { hsc2hs = "0.68.2"; }) // lib.mapAttrs (_: new-builder) configs; diff --git a/nix/new-builder.nix b/nix/new-builder.nix index aafc1e2..fda6e68 100644 --- a/nix/new-builder.nix +++ b/nix/new-builder.nix @@ -1,12 +1,13 @@ -{ stdenv, lib, haskellLib, ghc, hashes, fetchurl, writeText, runCommand, pkgconfig, callPackage }: +{ stdenv, lib, haskellLib, ghc, fetchurl, writeText, runCommand, pkgconfig, callPackage }: { flags ? {} , package ? {} , components ? {} , name ? "${package.identifier.name}-${package.identifier.version}" -, sha256 ? (hashes.${package.identifier.name}.${package.identifier.version} or (throw name)) +, sha256 ? null , src ? fetchurl { url = "mirror://hackage/${name}.tar.gz"; inherit sha256; } +, cabalFile ? null }@config: let @@ -48,7 +49,7 @@ let comp-builder = callPackage ./comp-builder.nix { inherit ghc haskellLib; }; buildComp = componentId: component: comp-builder { - inherit componentId package name src flags setup; + inherit componentId package name src flags setup cabalFile; component = let nonNullLists = fs: component // lib.genAttrs fs (field: @@ -56,7 +57,7 @@ let then builtins.filter (x: x != null) component.${field} else []); in { - allowNewer = true; + allowNewer = false; allowOlder = false; } // nonNullLists [ "depends" From e15aa0e4c11f5fe063893599768cc6215ddd7a23 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 29 May 2018 00:51:58 -0400 Subject: [PATCH 05/20] Remove allowNewer/Older flags --- nix/comp-builder.nix | 2 -- nix/new-builder.nix | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/nix/comp-builder.nix b/nix/comp-builder.nix index 8f508d6..7560ac2 100644 --- a/nix/comp-builder.nix +++ b/nix/comp-builder.nix @@ -30,8 +30,6 @@ let extraLibDirs = flagsAndConfig "extra-lib-dirs" (map (p: "${p}/lib") component.libs); extraIncludeDirs = flagsAndConfig "extra-include-dirs" (map (p: "${lib.getDev p}/include") component.libs); extraFameworks = flagsAndConfig "extra-framework-dirs" (map (p: "${p}/Library/Frameworks") component.frameworks); - allowNewer = lib.mapAttrs (_: lib.optional component.allowNewer) { flags = "--allow-newer"; config = "allow-newer: True"; }; - allowOlder = lib.mapAttrs (_: lib.optional component.allowOlder) { flags = "--allow-older"; config = "allow-older: True"; }; userFlags = { flags = [("--flags=\"" + lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: lib.optionalString (!val) "-" + fname) flags) + "\"")]; config = []; diff --git a/nix/new-builder.nix b/nix/new-builder.nix index fda6e68..b12787e 100644 --- a/nix/new-builder.nix +++ b/nix/new-builder.nix @@ -56,10 +56,7 @@ let if component ? ${field} then builtins.filter (x: x != null) component.${field} else []); - in { - allowNewer = false; - allowOlder = false; - } // nonNullLists [ + in nonNullLists [ "depends" "libs" "frameworks" From b4e93c5254cdcc04bde802e2fa4574e2fff4b7ff Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Wed, 30 May 2018 21:14:24 -0400 Subject: [PATCH 06/20] Fix haskell packages for plan2nix --- nix/default.nix | 23 +++++++++++++++-------- nix/new-builder.nix | 3 ++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index d5cafce..a7c4966 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,14 +1,21 @@ -{ pkgs ? import {} }: +{ pkgs ? import {} +, planFile ? ../stackage/lts-11.11.nix +}: (pkgs.lib.fix (self: with self; { inherit (pkgs) lib stdenv; ghc = pkgs.haskell.compiler.${stackage.compiler.nix-name}; haskellLib = import ./lib.nix { inherit lib haskellLib; }; hackage = import ../hackage; - stackage = import ../stackage/lts-11.11.nix (lib.mapAttrs (_: p: - lib.mapAttrs (ver: revs: lib.mapAttrs' (_: rev: - {name = rev.cabalSha256; value = revs // {revision = rev;};} - ) (builtins.removeAttrs revs ["revision" "sha256"])) p + plan = import planFile (lib.mapAttrs (_: p: + lib.mapAttrs (ver: vdata: + let revs = builtins.removeAttrs vdata ["revision" "sha256"]; + in vdata + // lib.mapAttrs (_: rev: vdata // {revision = rev;}) revs + // lib.mapAttrs' (_: rev: + {name = rev.cabalSha256; value = vdata // {revision = rev;};} + ) revs + ) p ) hackage); new-builder = pkgs.callPackage ./new-builder.nix { inherit haskellLib ghc; @@ -17,7 +24,7 @@ compiler = cabal.compiler // { isGhc = true; - version = lib.mapAttrs (_: f: v: f (builtins.compareVersions stackage.compiler.version v)) { + version = lib.mapAttrs (_: f: v: f (builtins.compareVersions plan.compiler.version v)) { eq = c: c == 0; gt = c: c > 0; ge = c: c >= 0; @@ -66,8 +73,8 @@ } // { inherit (f) sha256; cabalFile = if f.revision == f.r0 then null else f.revision.cabalFile; - }) stackage.packages; + }) plan.packages; - hsPkgs = lib.mapAttrs (_: _: null) (stackage.compiler.packages // { hsc2hs = "0.68.2"; }) + hsPkgs = lib.mapAttrs (_: _: null) (plan.compiler.packages // { hsc2hs = "0.68.2"; }) // lib.mapAttrs (_: new-builder) configs; })) diff --git a/nix/new-builder.nix b/nix/new-builder.nix index b12787e..2f8ab3d 100644 --- a/nix/new-builder.nix +++ b/nix/new-builder.nix @@ -16,7 +16,8 @@ let main = defaultMain ''; defaultSetup = runCommand "default-Setup" { nativeBuildInputs = [ghc]; } '' - ghc ${defaultSetupSrc} --make -o $out + cat ${defaultSetupSrc} > Setup.hs + ghc Setup.hs --make -o $out ''; setup = stdenv.mkDerivation { From 216d0d9ca91e10e3145c76faba8d616da57d834a Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Wed, 30 May 2018 21:15:35 -0400 Subject: [PATCH 07/20] weakCallPackage --- nix/default.nix | 81 +++++++++++++++++++++++++-------------------- nix/new-builder.nix | 4 +-- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index a7c4966..49dc956 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -4,8 +4,17 @@ (pkgs.lib.fix (self: with self; { inherit (pkgs) lib stdenv; - ghc = pkgs.haskell.compiler.${stackage.compiler.nix-name}; + ghc = pkgs.haskell.compiler.${plan.compiler.nix-name}; + + # Avoid pkgs.callPackage for now. It does a lot of nonsense with OOP + # style programming that we should avoid until we know we want it. + weakCallPackage = scope: f: args: + let f' = if lib.isFunction f then f else import f; + args' = scope // args; + in f' (builtins.intersectAttrs (builtins.functionArgs f') args'); + haskellLib = import ./lib.nix { inherit lib haskellLib; }; + hackage = import ../hackage; plan = import planFile (lib.mapAttrs (_: p: lib.mapAttrs (ver: vdata: @@ -17,8 +26,8 @@ ) revs ) p ) hackage); - new-builder = pkgs.callPackage ./new-builder.nix { - inherit haskellLib ghc; + new-builder = weakCallPackage pkgs ./new-builder.nix { + inherit haskellLib ghc weakCallPackage; }; cabal = import ./cabal-os-arch-comp.nix; @@ -37,39 +46,41 @@ in cabal.os // { "is${hostMap.os}" = true; } // cabal.arch // { "is${hostMap.arch}" = true; }; + adjustedPkgs = pkgs // { + pthread = null; + "stdc++" = null; + ssl = pkgs.openssl.dev; + crypto = pkgs.openssl.dev; + z = pkgs.zlib; + GL = pkgs.libGL; + GLU = pkgs.libGLU; + alut = pkgs.freealut; + X11 = pkgs.xorg.libX11; + Xrandr = pkgs.xorg.libXrandr; + Xext = pkgs.xorg.libXext; + Xi = pkgs.xorg.libXi; + Xxf86vm = pkgs.xorg.libXxf86vm; + Xcursor = pkgs.xorg.libXcursor; + Xinerama = pkgs.xorg.libXinerama; + mysqlclient = pkgs.mysql; + Imlib2 = pkgs.imlib2; + asound = pkgs.alsaLib; + ffi = null; + }; + pkgconfPkgs = pkgs // { + cairo-pdf = pkgs.cairo; + cairo-ps = pkgs.cairo; + cairo-svg = pkgs.cairo; + xft = pkgs.xorg.libXft; + xau = pkgs.xorg.libXau; + libR = pkgs.R; + fftw3f = pkgs.fftwFloat; + fftw3 = pkgs.fftw; + }; + configs = lib.mapAttrs (_: f: import f.revision { - inherit hsPkgs compiler system; - pkgs = pkgs // { - pthread = null; - "stdc++" = null; - ssl = pkgs.openssl.dev; - crypto = pkgs.openssl.dev; - z = pkgs.zlib; - GL = pkgs.libGL; - GLU = pkgs.libGLU; - alut = pkgs.freealut; - X11 = pkgs.xorg.libX11; - Xrandr = pkgs.xorg.libXrandr; - Xext = pkgs.xorg.libXext; - Xi = pkgs.xorg.libXi; - Xxf86vm = pkgs.xorg.libXxf86vm; - Xcursor = pkgs.xorg.libXcursor; - Xinerama = pkgs.xorg.libXinerama; - mysqlclient = pkgs.mysql; - Imlib2 = pkgs.imlib2; - asound = pkgs.alsaLib; - ffi = null; - }; - pkgconfPkgs = pkgs // { - cairo-pdf = pkgs.cairo; - cairo-ps = pkgs.cairo; - cairo-svg = pkgs.cairo; - xft = pkgs.xorg.libXft; - xau = pkgs.xorg.libXau; - libR = pkgs.R; - fftw3f = pkgs.fftwFloat; - fftw3 = pkgs.fftw; - }; + inherit hsPkgs compiler system pkgconfPkgs; + pkgs = adjustedPkgs; } // { inherit (f) sha256; cabalFile = if f.revision == f.r0 then null else f.revision.cabalFile; diff --git a/nix/new-builder.nix b/nix/new-builder.nix index 2f8ab3d..ee3831b 100644 --- a/nix/new-builder.nix +++ b/nix/new-builder.nix @@ -1,4 +1,4 @@ -{ stdenv, lib, haskellLib, ghc, fetchurl, writeText, runCommand, pkgconfig, callPackage }: +{ pkgs, stdenv, lib, haskellLib, ghc, fetchurl, writeText, runCommand, pkgconfig, weakCallPackage }: { flags ? {} , package ? {} @@ -47,7 +47,7 @@ let ''; }; - comp-builder = callPackage ./comp-builder.nix { inherit ghc haskellLib; }; + comp-builder = weakCallPackage pkgs ./comp-builder.nix { inherit ghc haskellLib; }; buildComp = componentId: component: comp-builder { inherit componentId package name src flags setup cabalFile; From f9c103b588395ee98911301cd10f78b8e395036f Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Sun, 17 Jun 2018 18:08:25 -0400 Subject: [PATCH 08/20] Stackage / plan.json flags --- lib/Cabal2Nix.hs | 10 +++--- lib/Cabal2Nix/Plan.hs | 22 ++++++++---- lib/Cabal2Nix/Util.hs | 7 ++++ lts2nix/Main.hs | 11 +++--- nix/comp-builder.nix | 5 +-- nix/default.nix | 53 ++++++++++++++++++----------- nix/lib.nix | 78 +++++++++++++++++++++++++++++++++++++++++++ nix/new-builder.nix | 3 +- plan2nix/Main.hs | 7 ++-- 9 files changed, 153 insertions(+), 43 deletions(-) diff --git a/lib/Cabal2Nix.hs b/lib/Cabal2Nix.hs index 1c63d10..cea7461 100644 --- a/lib/Cabal2Nix.hs +++ b/lib/Cabal2Nix.hs @@ -48,7 +48,7 @@ pkgs, hsPkgs, flags :: Text pkgs = "pkgs" hsPkgs = "hsPkgs" pkgconfPkgs = "pkgconfPkgs" -flags = "_flags" +flags = "flags" ($//?) :: NExpr -> Maybe NExpr -> NExpr lhs $//? (Just e) = lhs $// e @@ -82,17 +82,15 @@ cabal2nix src = \case $ maybe (error "Failed to parse in-memory cabal file") pure (parseGenericPackageDescriptionMaybe body) gpd2nix :: Maybe Src -> Maybe NExpr -> GenericPackageDescription -> NExpr -gpd2nix src extra gpd = mkFunction args . lets gpd $ toNix gpd $//? (toNix <$> src) $//? extra +gpd2nix src extra gpd = mkFunction args $ toNix gpd $//? (toNix <$> src) $//? extra where args :: Params NExpr args = mkParamset [ ("system", Nothing) , ("compiler", Nothing) - , ("flags", Just $ mkNonRecSet []) + , ("flags", Nothing) , (pkgs, Nothing) , (hsPkgs, Nothing) , (pkgconfPkgs, Nothing)] False - lets :: GenericPackageDescription -> NExpr -> NExpr - lets gpd = mkLets [ flags $= (mkNonRecSet . fmap toNixBinding $ genPackageFlags gpd) $// mkSym "flags" ] class HasBuildInfo a where getBuildInfo :: a -> BuildInfo @@ -185,7 +183,7 @@ mkSysDep :: String -> SysDependency mkSysDep = SysDependency instance ToNixExpr GenericPackageDescription where - toNix gpd = mkNonRecSet $ [ "flags" $= mkSym flags -- keep track of the final flags; and allow them to be inspected + toNix gpd = mkNonRecSet $ [ "flags" $= (mkNonRecSet . fmap toNixBinding $ genPackageFlags gpd) , "package" $= (toNix (packageDescription gpd)) , "components" $= components ] where packageName = fromString . show . disp . pkgName . package . packageDescription $ gpd diff --git a/lib/Cabal2Nix/Plan.hs b/lib/Cabal2Nix/Plan.hs index 7ef9e08..08182f2 100644 --- a/lib/Cabal2Nix/Plan.hs +++ b/lib/Cabal2Nix/Plan.hs @@ -4,9 +4,12 @@ module Cabal2Nix.Plan where -import Cabal2Nix.Util ( quoted ) +import Cabal2Nix.Util ( quoted + , bindPath + ) import Data.HashMap.Strict ( HashMap ) import qualified Data.HashMap.Strict as Map +import Data.List.NonEmpty ( NonEmpty (..) ) import Data.Text ( Text ) import qualified Data.Text as Text import Nix.Expr @@ -23,13 +26,14 @@ data Plan = Plan data Package = Package { packageVersion :: Version , packageRevision :: Maybe Revision + , packageFlags :: HashMap Text Bool } plan2nix :: Plan -> NExpr plan2nix (Plan { packages, compilerVersion, compilerPackages }) = mkFunction "hackage" . mkNonRecSet - $ [ "packages" $= (mkNonRecSet $ uncurry bind <$> Map.toList packages) + $ [ "packages" $= (mkNonRecSet $ uncurry bind =<< Map.toList packages) , "compiler" $= mkNonRecSet [ "version" $= mkStr compilerVersion , "nix-name" $= mkStr ("ghc" <> Text.filter (/= '.') compilerVersion) @@ -54,9 +58,13 @@ plan2nix (Plan { packages, compilerVersion, compilerPackages }) = $ fmap (uncurry bindTo) . Map.toList $ (\k _v -> mkSym "dontCheck'" @@ (mkSym "super" @. k)) `Map.mapWithKey` packages) ] where - bind pkg (Package { packageVersion, packageRevision }) = - let verExpr = mkSym "hackage" @. pkg @. quoted packageVersion - revExpr = maybe verExpr (verExpr @.) (quoted <$> packageRevision) - -- disable revision logic, until we have that fixed in the hackage expression. - in quoted pkg $= verExpr -- revExpr + bind pkg (Package { packageVersion, packageRevision, packageFlags }) = + let verExpr = mkSym "hackage" @. pkg @. packageVersion + revExpr = maybe verExpr (verExpr @.) packageRevision + revBinding = bindPath (quoted pkg :| ["revision"]) revExpr + flagBindings = Map.foldrWithKey + (\fname val acc -> bindPath (quoted pkg :| ["flags", fname]) (mkBool val) : acc) + [] + packageFlags + in revBinding : flagBindings bind' pkg ver = quoted pkg $= mkStr ver diff --git a/lib/Cabal2Nix/Util.hs b/lib/Cabal2Nix/Util.hs index d4cc58d..34c5b30 100644 --- a/lib/Cabal2Nix/Util.hs +++ b/lib/Cabal2Nix/Util.hs @@ -8,9 +8,13 @@ import Control.Monad import Data.String (IsString) import Data.ByteString.Char8 (pack, unpack) +import Data.Text (Text) import Crypto.Hash.SHA256 (hash) import qualified Data.ByteString.Base16 as Base16 +import Data.List.NonEmpty (NonEmpty) +import Nix.Expr + listDirectories :: FilePath -> IO [FilePath] listDirectories p = filter (/= ".git") <$> listDirectory p @@ -21,3 +25,6 @@ quoted str = "\"" <> str <> "\"" sha256 :: String -> String sha256 = unpack . Base16.encode . hash . pack + +bindPath :: NonEmpty Text -> NExpr -> Binding NExpr +bindPath ks e = NamedVar (fmap StaticKey ks) e nullPos diff --git a/lts2nix/Main.hs b/lts2nix/Main.hs index 5b2231c..9d9c9fd 100644 --- a/lts2nix/Main.hs +++ b/lts2nix/Main.hs @@ -10,10 +10,10 @@ import Data.Yaml (decodeFileEither) import Nix.Pretty (prettyNix) import Nix.Expr -import Data.Aeson -import Lens.Micro -import Lens.Micro.Aeson - +import Data.Aeson +import qualified Data.HashMap.Strict as Map +import Lens.Micro +import Lens.Micro.Aeson import Cabal2Nix.Plan @@ -36,6 +36,7 @@ lts2plan lts = Plan { packages , compilerVersion , compilerPackages } packages = lts ^. key "packages" . _Object <&> \v -> Package { packageVersion = v ^. key "version" . _String , packageRevision = v ^? key "cabal-file-info" . key "hashes" . key "SHA256" . _String + , packageFlags = Map.mapMaybe (^? _Bool) $ v ^. key "constraints" . key "flags" . _Object } - compilerVersion = lts ^. key "system-info" . key "ghc-version" . _String + compilerVersion = lts ^. key "system-info" . key "ghc-version" . _String compilerPackages = lts ^. key "system-info" . key "core-packages" . _Object <&> (^. _String) diff --git a/nix/comp-builder.nix b/nix/comp-builder.nix index 7560ac2..8622c3f 100644 --- a/nix/comp-builder.nix +++ b/nix/comp-builder.nix @@ -71,7 +71,9 @@ in stdenv.mkDerivation { nativeBuildInputs = [ghc] ++ lib.optional (component.pkgconfig != []) pkgconfig - ++ lib.concatMap (c: builtins.attrValues (c.components.exes or {})) component.build-tools; + ++ lib.concatMap (c: if c.isHaskell or false + then builtins.attrValues (c.components.exes or {}) + else [c]) component.build-tools; SETUP_HS = setup + /bin/Setup; @@ -89,7 +91,6 @@ in stdenv.mkDerivation { buildPhase = '' $SETUP_HS build -j$NIX_BUILD_CORES - $SETUP_HS haddock ''; checkPhase = '' diff --git a/nix/default.nix b/nix/default.nix index 49dc956..142197c 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,5 +1,6 @@ { pkgs ? import {} -, planFile ? ../stackage/lts-11.11.nix +, planFunc ? import ../stackage/lts-11.4.nix +, hackage ? import ../hackage }: (pkgs.lib.fix (self: with self; { @@ -15,17 +16,32 @@ haskellLib = import ./lib.nix { inherit lib haskellLib; }; - hackage = import ../hackage; - plan = import planFile (lib.mapAttrs (_: p: - lib.mapAttrs (ver: vdata: - let revs = builtins.removeAttrs vdata ["revision" "sha256"]; - in vdata - // lib.mapAttrs (_: rev: vdata // {revision = rev;}) revs - // lib.mapAttrs' (_: rev: - {name = rev.cabalSha256; value = vdata // {revision = rev;};} - ) revs - ) p - ) hackage); + plan = + let p = planFunc hackageConfigs; + in p // { + packages = lib.mapAttrs + (_: pkg: self: + lib.recursiveUpdate (pkg.revision self) { flags = pkg.flags or {}; } + ) p.packages; + }; + hackageConfigs = + let + args = { + inherit hsPkgs compiler system pkgconfPkgs; + pkgs = adjustedPkgs; + }; + handleVer = vdata: + let + revs = builtins.removeAttrs vdata ["sha256"]; + rev2HashedConfig = name: rev: { name = rev.cabalSha256; value = revConfigs.${name}; }; + revConfigs = lib.mapAttrs (_: rev2config vdata.sha256) revs; + in revConfigs // lib.mapAttrs' rev2HashedConfig revs; + rev2config = sha256: rev: self: import rev (args // { inherit (self) flags; }) // { + inherit sha256; + inherit (rev) cabalFile; + }; + in lib.mapAttrs (_: lib.mapAttrs (_: handleVer)) hackage; + new-builder = weakCallPackage pkgs ./new-builder.nix { inherit haskellLib ghc weakCallPackage; }; @@ -78,14 +94,11 @@ fftw3 = pkgs.fftw; }; - configs = lib.mapAttrs (_: f: import f.revision { - inherit hsPkgs compiler system pkgconfPkgs; - pkgs = adjustedPkgs; - } // { - inherit (f) sha256; - cabalFile = if f.revision == f.r0 then null else f.revision.cabalFile; - }) plan.packages; + configs = lib.mapAttrs (_: lib.fix) (plan.packages // { + stack = self: let super = plan.packages.stack self; in super // { flags = super.flags // { hide-dependency-versions = true; }; }; + }); - hsPkgs = lib.mapAttrs (_: _: null) (plan.compiler.packages // { hsc2hs = "0.68.2"; }) + hsPkgs = adjustedPkgs + // lib.mapAttrs (_: _: null) (plan.compiler.packages // { hsc2hs = "0.68.2"; }) // lib.mapAttrs (_: new-builder) configs; })) diff --git a/nix/lib.nix b/nix/lib.nix index a0791c0..934f8fc 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -72,4 +72,82 @@ with haskellLib; in subComps // libComp; isLibrary = componentId: componentId.ctype == "lib"; + + adjustHackage = hackage: args: + let + handleVer = vdata: + let + revs = builtins.removeAttrs vdata ["sha256"]; + rev2HashedConfig = name: rev: { name = rev.cabalSha256; value = revConfigs.${name}; }; + revConfigs = lib.mapAttrs (_: rev2config vdata.sha256) revs; + in revConfigs // lib.mapAttrs' rev2HashedConfig revs; + rev2config = sha256: rev: self: import rev (args // { inherit (self) flags; }) // { + inherit sha256; + inherit (rev) cabalFile; + }; + in lib.mapAttrs (_: lib.mapAttrs (_: handleVer)) hackage; + + buildPlan = { pkgs, plan }: + let + ghc = pkgs.haskell.compiler.${plan.compiler.nix-name}; + weakCallPackage = scope: f: args: + let f' = if lib.isFunction f then f else import f; + args' = scope // args; + in f' (builtins.intersectAttrs (builtins.functionArgs f') args'); + + new-builder = weakCallPackage pkgs ./new-builder.nix { + inherit haskellLib ghc weakCallPackage; + }; + cabal = import ./cabal-os-arch-comp.nix; + configs = lib.mapAttrs (_: lib.fix) plan.packages; + in { + system = + let hostMap = import ./host-map.nix pkgs.stdenv; + in cabal.os // { "is${hostMap.os}" = true; } + // cabal.arch // { "is${hostMap.arch}" = true; }; + compiler = cabal.compiler // { + isGhc = true; + version = lib.mapAttrs (_: f: v: f (builtins.compareVersions plan.compiler.version v)) { + eq = c: c == 0; + gt = c: c > 0; + ge = c: c >= 0; + lt = c: c < 0; + le = c: c <= 0; + }; + }; + pkgconfPkgs = pkgs // { + cairo-pdf = pkgs.cairo; + cairo-ps = pkgs.cairo; + cairo-svg = pkgs.cairo; + xft = pkgs.xorg.libXft; + xau = pkgs.xorg.libXau; + libR = pkgs.R; + fftw3f = pkgs.fftwFloat; + fftw3 = pkgs.fftw; + }; + pkgs = pkgs // { + pthread = null; + "stdc++" = null; + ssl = pkgs.openssl.dev; + crypto = pkgs.openssl.dev; + z = pkgs.zlib; + GL = pkgs.libGL; + GLU = pkgs.libGLU; + alut = pkgs.freealut; + X11 = pkgs.xorg.libX11; + Xrandr = pkgs.xorg.libXrandr; + Xext = pkgs.xorg.libXext; + Xi = pkgs.xorg.libXi; + Xxf86vm = pkgs.xorg.libXxf86vm; + Xcursor = pkgs.xorg.libXcursor; + Xinerama = pkgs.xorg.libXinerama; + mysqlclient = pkgs.mysql; + Imlib2 = pkgs.imlib2; + asound = pkgs.alsaLib; + ffi = null; + }; + hsPkgs = lib.mapAttrs (_: _: null) (plan.compiler.packages // { hsc2hs = "0.68.2"; }) + // lib.mapAttrs (_: new-builder) configs; + }; + } diff --git a/nix/new-builder.nix b/nix/new-builder.nix index ee3831b..5bb2b6f 100644 --- a/nix/new-builder.nix +++ b/nix/new-builder.nix @@ -70,5 +70,6 @@ let in { components = haskellLib.applyComponents buildComp components; inherit (package) identifier; - inherit setup; + inherit setup cabalFile; + isHaskell = true; } diff --git a/plan2nix/Main.hs b/plan2nix/Main.hs index bd75921..8b84a0f 100644 --- a/plan2nix/Main.hs +++ b/plan2nix/Main.hs @@ -40,8 +40,11 @@ value2plan plan = Plan {packages , compilerVersion , compilerPackages } where packages = filterInstallPlan $ \pkg -> if (pkg ^. key "style" . _String) /= "global" then Nothing - else Just - $ Package {packageVersion = pkg ^. key "pkg-version" . _String, packageRevision = Nothing} + else Just $ Package + { packageVersion = pkg ^. key "pkg-version" . _String + , packageRevision = Nothing + , packageFlags = Map.mapMaybe (^? _Bool) $ pkg ^. key "flags" . _Object + } compilerVersion = Text.dropWhile (not . isDigit) $ plan ^. key "compiler-id" . _String compilerPackages = filterInstallPlan $ \pkg -> if isJust (pkg ^? key "style" . _String) then Nothing From 98a12ffb11a146bc7440dc8ec96ce9a451cd4a05 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Wed, 27 Jun 2018 22:58:29 -0400 Subject: [PATCH 09/20] Fix buildPackages with a hack --- nix/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/default.nix b/nix/default.nix index 142197c..e90ee05 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -99,6 +99,7 @@ }); hsPkgs = adjustedPkgs + // { buildPackages = hsPkgs; } // lib.mapAttrs (_: _: null) (plan.compiler.packages // { hsc2hs = "0.68.2"; }) // lib.mapAttrs (_: new-builder) configs; })) From 4530b7704e38a282f2961542a57b5440c58065c4 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Wed, 10 Oct 2018 10:15:00 -0400 Subject: [PATCH 10/20] Added bsd2 --- nix/cabal-licenses.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/cabal-licenses.nix b/nix/cabal-licenses.nix index 304c4c7..8ecc695 100644 --- a/nix/cabal-licenses.nix +++ b/nix/cabal-licenses.nix @@ -1,5 +1,6 @@ stdenv: with stdenv.lib.licenses; { + BSD-2-Clause = bsd2; BSD-3-Clause = bsd3; MIT = mit; } From 03b0bb50eeeebc6bbc62e81a7f39dc79bed935ea Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Sun, 14 Oct 2018 19:56:38 -0400 Subject: [PATCH 11/20] Fix quoting --- lib/Cabal2Nix/Plan.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cabal2Nix/Plan.hs b/lib/Cabal2Nix/Plan.hs index 08182f2..6a036e3 100644 --- a/lib/Cabal2Nix/Plan.hs +++ b/lib/Cabal2Nix/Plan.hs @@ -59,8 +59,8 @@ plan2nix (Plan { packages, compilerVersion, compilerPackages }) = ] where bind pkg (Package { packageVersion, packageRevision, packageFlags }) = - let verExpr = mkSym "hackage" @. pkg @. packageVersion - revExpr = maybe verExpr (verExpr @.) packageRevision + let verExpr = mkSym "hackage" @. quoted pkg @. quoted packageVersion + revExpr = maybe verExpr ((verExpr @.) . quoted) packageRevision revBinding = bindPath (quoted pkg :| ["revision"]) revExpr flagBindings = Map.foldrWithKey (\fname val acc -> bindPath (quoted pkg :| ["flags", fname]) (mkBool val) : acc) From de0a474a553bb3d808deb05581486a89fd303ec7 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Mon, 15 Oct 2018 21:23:31 -0400 Subject: [PATCH 12/20] Rewrite hackage-to-nix --- hackage2nix/Main.hs | 145 +++++++++++++++++++++++++++----------------- lib/Cabal2Nix.hs | 4 +- nix-tools.cabal | 1 + stack2nix/Main.hs | 2 +- 4 files changed, 94 insertions(+), 58 deletions(-) diff --git a/hackage2nix/Main.hs b/hackage2nix/Main.hs index 1d3d664..20245fe 100644 --- a/hackage2nix/Main.hs +++ b/hackage2nix/Main.hs @@ -1,35 +1,43 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NamedFieldPuns #-} -module Main -where +module Main where import Cabal2Nix import Cabal2Nix.Util ( quoted ) -import Crypto.Hash.SHA256 ( hash - , hashlazy - ) +import Control.Applicative ( liftA2 ) +import Control.Monad.Trans.State.Strict +import Crypto.Hash.SHA256 ( hashlazy ) import qualified Data.ByteString.Base16 as Base16 import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy as BL -import Data.Foldable ( toList ) +import Data.Foldable ( toList + , for_ + ) +import Data.List ( intersperse ) +import Data.Map ( Map ) import qualified Data.Map as Map +import Data.Semigroup as Sem +import Data.Sequence ( Seq ) import qualified Data.Sequence as Seq -import Data.String ( IsString(fromString) ) +import Data.String ( IsString(fromString) + ) +import Data.Text ( Text ) import Data.Text.Encoding ( decodeUtf8 ) import Distribution.Hackage.DB ( hackageTarball ) import qualified Distribution.Hackage.DB.Parsed as P -import Distribution.Hackage.DB.Parsed ( parseMetaData - , parseVersionData - ) -import Distribution.Hackage.DB.Unparsed +import qualified Distribution.Hackage.DB.Unparsed + as U import Distribution.Pretty ( prettyShow , Pretty ) +import Distribution.Types.PackageName ( PackageName ) +import Distribution.Types.Version ( Version ) import Nix.Expr import Nix.Pretty ( prettyNix ) -import System.Directory ( createDirectoryIfMissing ) +import System.Directory ( createDirectoryIfMissing + ) import System.Environment ( getArgs ) import System.FilePath ( () , (<.>) @@ -38,50 +46,77 @@ import System.FilePath ( () main :: IO () main = do [out] <- getArgs - db <- readTarball Nothing =<< hackageTarball + db <- U.readTarball Nothing =<< hackageTarball - let defaultNix = seqToSet $ Map.foldMapWithKey package2nix db + let (defaultNix, cabalFiles) = + runState (fmap seqToSet $ foldMapWithKeyA package2nix db) mempty createDirectoryIfMissing False out writeFile (out "default.nix") $ show $ prettyNix defaultNix - _ <- forWithKey db $ \pname (PackageData { versions }) -> - forWithKey versions $ \vnum vdata@(VersionData { cabalFileRevisions }) -> - let parsedVData = parseVersionData pname vnum vdata - writeFiles gpd cabalFile revNum = do - let dir = out packagePath pname fromPretty vnum - revPath = dir revName revNum - createDirectoryIfMissing True dir - BL.writeFile (revPath <.> "cabal") cabalFile - writeFile (revPath <.> "nix") $ show $ prettyNix $ gpd2nix Nothing Nothing gpd - in sequence $ zipWith3 writeFiles - (toList (P.cabalFileRevisions parsedVData)) - cabalFileRevisions - [(0 :: Int) ..] - return () - where - forWithKey :: Applicative f => Map.Map k v -> (k -> v -> f x) -> f (Map.Map k x) - forWithKey = flip Map.traverseWithKey - seqToSet = mkNonRecSet . toList - fromPretty :: (Pretty a, IsString b) => a -> b - fromPretty = fromString . prettyShow - package2nix pname (PackageData { versions }) = - Seq.singleton $ quoted (fromPretty pname) $= seqToSet - (Map.foldMapWithKey (version2nix pname) versions) - version2nix pname vnum (VersionData { cabalFileRevisions, metaFile }) = - Seq.singleton $ quoted (fromPretty vnum) $= mkRecSet - ( ("revision" $= mkSym (revName $ length cabalFileRevisions - 1)) - : ("sha256" $= mkStr (fromString $ parseMetaData pname vnum metaFile Map.! "sha256")) - : zipWith (revBinding (packagePath pname) vnum) cabalFileRevisions [(0 :: Int) ..] - ) - revName revNum = "r" <> fromString (show revNum) - revBinding ppath vnum cabalFile revNum = - let name :: (IsString a, Semigroup a) => a - name = revName revNum - revPath = "." ppath fromPretty vnum name - in name $= mkNonRecSet - [ "outPath" $= mkRelPath (revPath <.> "nix") - , "cabalFile" $= mkRelPath (revPath <.> "cabal") - , "cabalSha256" $= mkStr (decodeUtf8 $ Base16.encode $ hashlazy cabalFile) - ] - packagePath pname = - BS.unpack (BS.take 30 $ Base16.encode $ hash $ fromPretty pname) ++ "-" ++ fromPretty pname + for_ cabalFiles $ \(cabalFile, pname, path) -> do + gpd <- cabal2nix Nothing $ InMemory Nothing pname $ BL.toStrict cabalFile + writeFile (out path) $ show $ prettyNix gpd + +type GPDWriter = State (Seq (BL.ByteString, String, FilePath)) + +newtype ApplicativeMonoid f a = ApplicativeMonoid { unApplicativeMonoid :: f a } +instance (Applicative f, Semigroup a) => Sem.Semigroup (ApplicativeMonoid f a) where + ApplicativeMonoid a <> ApplicativeMonoid b = ApplicativeMonoid $ liftA2 (Sem.<>) a b +instance (Applicative f, Monoid a) => Monoid (ApplicativeMonoid f a) where + mempty = ApplicativeMonoid $ pure mempty + mappend = (Sem.<>) + +foldMapWithKeyA + :: (Applicative f, Monoid b) => (k -> a -> f b) -> Map k a -> f b +foldMapWithKeyA f = + unApplicativeMonoid . Map.foldMapWithKey (\k -> ApplicativeMonoid . f k) + +seqToSet :: Seq (Binding NExpr) -> NExpr +seqToSet = mkNonRecSet . toList + +fromPretty :: (Pretty a, IsString b) => a -> b +fromPretty = fromString . prettyShow + +package2nix :: PackageName -> U.PackageData -> GPDWriter (Seq (Binding NExpr)) +package2nix pname (U.PackageData { U.versions }) = do + versionBindings <- foldMapWithKeyA (version2nix pname) versions + return $ Seq.singleton $ quoted (fromPretty pname) $= seqToSet versionBindings + +version2nix + :: PackageName -> Version -> U.VersionData -> GPDWriter (Seq (Binding NExpr)) +version2nix pname vnum (U.VersionData { U.cabalFileRevisions, U.metaFile }) = + do + revisionBindings <- sequenceA + $ zipWith (revBinding pname vnum) cabalFileRevisions [0 ..] + return $ Seq.singleton $ quoted (fromPretty vnum) $= mkRecSet + [ "sha256" $= mkStr + (fromString $ P.parseMetaData pname vnum metaFile Map.! "sha256") + , "revisions" $= mkNonRecSet + ( fmap snd revisionBindings + ++ ["default" $= (mkSym "revisions" @. fst (last revisionBindings))] + ) + ] + +revName :: Integer -> String +revName revNum = "r" <> fromString (show revNum) + +revBinding + :: PackageName + -> Version + -> BL.ByteString + -> Integer + -> GPDWriter (Text, Binding NExpr) +revBinding pname vnum cabalFile revNum = do + let qualifiedName = mconcat + (intersperse + "-" + [prettyPname, fromPretty vnum, revName revNum, BS.unpack cabalHash] + ) + revPath = "." qualifiedName <.> "nix" + prettyPname = fromPretty pname + cabalHash = Base16.encode $ hashlazy cabalFile + key = quoted (decodeUtf8 cabalHash) + modify' $ mappend $ Seq.singleton + (cabalFile, prettyPname ++ ".cabal", revPath) + return $ (,) key $ key $= mkNonRecSet + ["outPath" $= mkRelPath revPath, "revNum" $= mkInt revNum] diff --git a/lib/Cabal2Nix.hs b/lib/Cabal2Nix.hs index cea7461..72b7e63 100644 --- a/lib/Cabal2Nix.hs +++ b/lib/Cabal2Nix.hs @@ -60,7 +60,7 @@ data CabalFileGenerator data CabalFile = OnDisk FilePath - | InMemory CabalFileGenerator FilePath ByteString + | InMemory (Maybe CabalFileGenerator) FilePath ByteString deriving Show @@ -78,7 +78,7 @@ cabal2nix :: Maybe Src -> CabalFile -> IO NExpr cabal2nix src = \case (OnDisk path) -> fmap (gpd2nix src Nothing) $ readGenericPackageDescription normal path - (InMemory gen path body) -> fmap (gpd2nix src (Just $ genExtra gen)) + (InMemory gen _ body) -> fmap (gpd2nix src (genExtra <$> gen)) $ maybe (error "Failed to parse in-memory cabal file") pure (parseGenericPackageDescriptionMaybe body) gpd2nix :: Maybe Src -> Maybe NExpr -> GenericPackageDescription -> NExpr diff --git a/nix-tools.cabal b/nix-tools.cabal index ce1eb66..bb87216 100644 --- a/nix-tools.cabal +++ b/nix-tools.cabal @@ -95,6 +95,7 @@ executable hackage-to-nix , base16-bytestring , filepath , directory + , transformers hs-source-dirs: hackage2nix default-language: Haskell2010 diff --git a/stack2nix/Main.hs b/stack2nix/Main.hs index 19be1da..1ae4f06 100644 --- a/stack2nix/Main.hs +++ b/stack2nix/Main.hs @@ -161,7 +161,7 @@ findCabalFiles path = doesFileExist (path Hpack.packageConfig) >>= \case case mbPkg of Left e -> error e Right r -> - return $ [InMemory Hpack + return $ [InMemory (Just Hpack) (Hpack.decodeResultCabalFile r) (encodeUtf8 $ Hpack.renderPackage [] (Hpack.decodeResultPackage r))] From 95ee61fa188520ae566333a40c7da34bc8657cc9 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 16 Oct 2018 00:00:54 -0400 Subject: [PATCH 13/20] Move nix files to subdir --- hackage2nix/Main.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hackage2nix/Main.hs b/hackage2nix/Main.hs index 20245fe..3adf2f4 100644 --- a/hackage2nix/Main.hs +++ b/hackage2nix/Main.hs @@ -50,12 +50,15 @@ main = do let (defaultNix, cabalFiles) = runState (fmap seqToSet $ foldMapWithKeyA package2nix db) mempty + hackageOut = out "hackage" + createDirectoryIfMissing False out writeFile (out "default.nix") $ show $ prettyNix defaultNix + createDirectoryIfMissing False hackageOut for_ cabalFiles $ \(cabalFile, pname, path) -> do gpd <- cabal2nix Nothing $ InMemory Nothing pname $ BL.toStrict cabalFile - writeFile (out path) $ show $ prettyNix gpd + writeFile (hackageOut path) $ show $ prettyNix gpd type GPDWriter = State (Seq (BL.ByteString, String, FilePath)) @@ -112,7 +115,7 @@ revBinding pname vnum cabalFile revNum = do "-" [prettyPname, fromPretty vnum, revName revNum, BS.unpack cabalHash] ) - revPath = "." qualifiedName <.> "nix" + revPath = "." "hackage" qualifiedName <.> "nix" prettyPname = fromPretty pname cabalHash = Base16.encode $ hashlazy cabalFile key = quoted (decodeUtf8 cabalHash) From 9a4dea150848e302736bbe83196cc54151ceb9a8 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 16 Oct 2018 00:41:51 -0400 Subject: [PATCH 14/20] Fixed identical revisions --- hackage2nix/Main.hs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/hackage2nix/Main.hs b/hackage2nix/Main.hs index 3adf2f4..0db086d 100644 --- a/hackage2nix/Main.hs +++ b/hackage2nix/Main.hs @@ -50,15 +50,14 @@ main = do let (defaultNix, cabalFiles) = runState (fmap seqToSet $ foldMapWithKeyA package2nix db) mempty - hackageOut = out "hackage" createDirectoryIfMissing False out writeFile (out "default.nix") $ show $ prettyNix defaultNix - createDirectoryIfMissing False hackageOut + createDirectoryIfMissing False (out "hackage") for_ cabalFiles $ \(cabalFile, pname, path) -> do gpd <- cabal2nix Nothing $ InMemory Nothing pname $ BL.toStrict cabalFile - writeFile (hackageOut path) $ show $ prettyNix gpd + writeFile (out path) $ show $ prettyNix gpd type GPDWriter = State (Seq (BL.ByteString, String, FilePath)) @@ -95,31 +94,30 @@ version2nix pname vnum (U.VersionData { U.cabalFileRevisions, U.metaFile }) = [ "sha256" $= mkStr (fromString $ P.parseMetaData pname vnum metaFile Map.! "sha256") , "revisions" $= mkNonRecSet - ( fmap snd revisionBindings + ( fmap (uncurry ($=)) revisionBindings ++ ["default" $= (mkSym "revisions" @. fst (last revisionBindings))] ) ] -revName :: Integer -> String -revName revNum = "r" <> fromString (show revNum) - revBinding :: PackageName -> Version -> BL.ByteString -> Integer - -> GPDWriter (Text, Binding NExpr) + -> GPDWriter (Text, NExpr) revBinding pname vnum cabalFile revNum = do - let qualifiedName = mconcat - (intersperse - "-" - [prettyPname, fromPretty vnum, revName revNum, BS.unpack cabalHash] - ) + let qualifiedName = mconcat $ intersperse + "-" + [prettyPname, fromPretty vnum, revName, BS.unpack cabalHash] + revName :: (Semigroup a, IsString a) => a + revName = "r" <> fromString (show revNum) revPath = "." "hackage" qualifiedName <.> "nix" prettyPname = fromPretty pname cabalHash = Base16.encode $ hashlazy cabalFile - key = quoted (decodeUtf8 cabalHash) modify' $ mappend $ Seq.singleton (cabalFile, prettyPname ++ ".cabal", revPath) - return $ (,) key $ key $= mkNonRecSet - ["outPath" $= mkRelPath revPath, "revNum" $= mkInt revNum] + return $ (,) revName $ mkNonRecSet + [ "outPath" $= mkRelPath revPath + , "revNum" $= mkInt revNum + , "sha256" $= mkStr (decodeUtf8 cabalHash) + ] From 2496961b17920ac2a6c19afcff8df6f154b8f305 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 16 Oct 2018 00:44:58 -0400 Subject: [PATCH 15/20] Slight modifications to Plan.hs --- lib/Cabal2Nix/Plan.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Cabal2Nix/Plan.hs b/lib/Cabal2Nix/Plan.hs index 6a036e3..63a8915 100644 --- a/lib/Cabal2Nix/Plan.hs +++ b/lib/Cabal2Nix/Plan.hs @@ -15,7 +15,7 @@ import qualified Data.Text as Text import Nix.Expr type Version = Text -type Revision = Text -- Can be: rNUM, cabal file sha256, or "revision" +type Revision = Text -- Can be: rNUM, cabal file sha256, or "default" data Plan = Plan { packages :: HashMap Text Package @@ -59,11 +59,11 @@ plan2nix (Plan { packages, compilerVersion, compilerPackages }) = ] where bind pkg (Package { packageVersion, packageRevision, packageFlags }) = - let verExpr = mkSym "hackage" @. quoted pkg @. quoted packageVersion - revExpr = maybe verExpr ((verExpr @.) . quoted) packageRevision - revBinding = bindPath (quoted pkg :| ["revision"]) revExpr + let verExpr = mkSym "hackage" @. pkg @. quoted packageVersion + revExpr = verExpr @. "revisions" @. maybe "default" quoted packageRevision + revBinding = bindPath (pkg :| ["revision"]) revExpr flagBindings = Map.foldrWithKey - (\fname val acc -> bindPath (quoted pkg :| ["flags", fname]) (mkBool val) : acc) + (\fname val acc -> bindPath (pkg :| ["flags", fname]) (mkBool val) : acc) [] packageFlags in revBinding : flagBindings From 4ebd79700302cdb54310386f4e316ae4206fbb79 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 16 Oct 2018 01:50:02 -0400 Subject: [PATCH 16/20] Update the component builder --- nix/default.nix | 56 ++++--- nix/new-builder.nix | 4 +- plan.nix | 398 +++++++++++++++++++++++++++++--------------- 3 files changed, 304 insertions(+), 154 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index e90ee05..8984ced 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -16,31 +16,49 @@ haskellLib = import ./lib.nix { inherit lib haskellLib; }; - plan = - let p = planFunc hackageConfigs; - in p // { - packages = lib.mapAttrs - (_: pkg: self: - lib.recursiveUpdate (pkg.revision self) { flags = pkg.flags or {}; } - ) p.packages; - }; hackageConfigs = + lib.flip lib.mapAttrs hackage + (pname: lib.mapAttrs + (vnum: version: version // { + revisions = + let + rev2Config = rev: { + inherit (version) sha256; + inherit (rev) outPath; + revision = rev.revNum; + revisionSha256 = rev.sha256; + }; + f = rev: acc: acc // { + # If there's a collision (e.g. a revision was + # reverted), pick the one with the smaller + # revNum. They're identical, but if the smaller one is + # r0 then we don't have to download a cabal file. + ${rev.sha256} = if lib.hasAttr rev.sha256 acc && acc.${rev.sha256}.revNum < rev.revNum + then acc.${rev.sha256} + else rev; + }; + contentAddressedRevs = lib.foldr f {} (builtins.attrValues version.revisions); + in lib.mapAttrs (_: rev2Config) (version.revisions // contentAddressedRevs); + })); + plan = let args = { inherit hsPkgs compiler system pkgconfPkgs; pkgs = adjustedPkgs; }; - handleVer = vdata: - let - revs = builtins.removeAttrs vdata ["sha256"]; - rev2HashedConfig = name: rev: { name = rev.cabalSha256; value = revConfigs.${name}; }; - revConfigs = lib.mapAttrs (_: rev2config vdata.sha256) revs; - in revConfigs // lib.mapAttrs' rev2HashedConfig revs; - rev2config = sha256: rev: self: import rev (args // { inherit (self) flags; }) // { - inherit sha256; - inherit (rev) cabalFile; - }; - in lib.mapAttrs (_: lib.mapAttrs (_: handleVer)) hackage; + p = planFunc hackageConfigs; + in p // { + packages = lib.mapAttrs + (pname: { revision, flags ? {} }: self: + # Set the flags with the rhs of the recursiveUpdate, but + # pass the final choice in flags using open recursion. + lib.recursiveUpdate (import revision (args // { inherit (self) flags; })) { + inherit flags; + inherit (revision) sha256 revision revisionSha256; + } + ) + p.packages; + }; new-builder = weakCallPackage pkgs ./new-builder.nix { inherit haskellLib ghc weakCallPackage; diff --git a/nix/new-builder.nix b/nix/new-builder.nix index 5bb2b6f..1473fa7 100644 --- a/nix/new-builder.nix +++ b/nix/new-builder.nix @@ -7,10 +7,12 @@ , name ? "${package.identifier.name}-${package.identifier.version}" , sha256 ? null , src ? fetchurl { url = "mirror://hackage/${name}.tar.gz"; inherit sha256; } -, cabalFile ? null +, revision ? null +, revisionSha256 ? null }@config: let + cabalFile = null; defaultSetupSrc = builtins.toFile "Setup.hs" '' import Distribution.Simple main = defaultMain diff --git a/plan.nix b/plan.nix index 413cd7c..def4070 100644 --- a/plan.nix +++ b/plan.nix @@ -1,139 +1,268 @@ hackage: { packages = { - "http-client" = hackage.http-client."0.5.13.1"; - "semigroupoids" = hackage.semigroupoids."5.3.1"; - "cookie" = hackage.cookie."0.4.4"; - "tf-random" = hackage.tf-random."0.5"; - "exceptions" = hackage.exceptions."0.10.0"; - "free" = hackage.free."5.1"; - "void" = hackage.void."0.7.2"; - "cereal" = hackage.cereal."0.5.7.0"; - "streaming-commons" = hackage.streaming-commons."0.2.1.0"; - "regex-tdfa-text" = hackage.regex-tdfa-text."1.0.0.3"; - "serialise" = hackage.serialise."0.2.0.0"; - "cryptohash-sha1" = hackage.cryptohash-sha1."0.11.100.1"; - "haskell-lexer" = hackage.haskell-lexer."1.0.1"; - "socks" = hackage.socks."0.5.6"; - "integer-logarithms" = hackage.integer-logarithms."1.0.2.2"; - "these" = hackage.these."0.7.5"; - "lens-family" = hackage.lens-family."1.2.2"; - "basement" = hackage.basement."0.0.8"; - "ansi-wl-pprint" = hackage.ansi-wl-pprint."0.6.8.2"; - "logict" = hackage.logict."0.6.0.2"; - "data-fix" = hackage.data-fix."0.2.0"; - "case-insensitive" = hackage.case-insensitive."1.2.0.11"; - "x509-validation" = hackage.x509-validation."1.6.10"; - "extra" = hackage.extra."1.6.11"; - "hourglass" = hackage.hourglass."0.2.12"; - "haskeline" = hackage.haskeline."0.7.4.3"; - "hashing" = hackage.hashing."0.1.0.1"; - "split" = hackage.split."0.2.3.3"; - "stm" = hackage.stm."2.4.5.1"; - "data-default-class" = hackage.data-default-class."0.1.2.0"; - "comonad" = hackage.comonad."5.0.4"; - "parser-combinators" = hackage.parser-combinators."1.0.0"; - "deriving-compat" = hackage.deriving-compat."0.5.2"; - "pointed" = hackage.pointed."5.0.1"; - "unordered-containers" = hackage.unordered-containers."0.2.9.0"; - "pem" = hackage.pem."0.2.4"; - "adjunctions" = hackage.adjunctions."4.4"; - "cryptohash-md5" = hackage.cryptohash-md5."0.11.100.1"; - "invariant" = hackage.invariant."0.5.1"; - "clock" = hackage.clock."0.7.2"; - "megaparsec" = hackage.megaparsec."6.5.0"; - "th-orphans" = hackage.th-orphans."0.13.6"; - "syb" = hackage.syb."0.7"; - "distributive" = hackage.distributive."0.6"; - "kan-extensions" = hackage.kan-extensions."5.2"; - "cborg" = hackage.cborg."0.2.0.0"; - "foundation" = hackage.foundation."0.0.21"; - "tls" = hackage.tls."1.4.1"; - "asn1-types" = hackage.asn1-types."0.3.2"; - "network" = hackage.network."2.8.0.0"; - "async" = hackage.async."2.2.1"; - "x509-store" = hackage.x509-store."1.6.6"; - "connection" = hackage.connection."0.2.8"; - "dlist" = hackage.dlist."0.8.0.5"; - "conduit" = hackage.conduit."1.3.0.3"; - "lens-family-th" = hackage.lens-family-th."0.5.0.2"; - "vector-instances" = hackage.vector-instances."3.4"; - "semigroups" = hackage.semigroups."0.18.5"; - "th-reify-many" = hackage.th-reify-many."0.1.8"; - "lens-family-core" = hackage.lens-family-core."1.2.2"; - "base-orphans" = hackage.base-orphans."0.8"; - "memory" = hackage.memory."0.14.16"; - "repline" = hackage.repline."0.1.7.0"; - "th-abstraction" = hackage.th-abstraction."0.2.8.0"; - "xml" = hackage.xml."1.3.14"; - "erf" = hackage.erf."2.0.0.0"; - "th-lift-instances" = hackage.th-lift-instances."0.1.11"; - "tagged" = hackage.tagged."0.8.6"; - "haskell-src-exts" = hackage.haskell-src-exts."1.20.2"; - "x509" = hackage.x509."1.7.4"; - "keys" = hackage.keys."3.12.1"; - "blaze-builder" = hackage.blaze-builder."0.4.1.0"; - "ansi-terminal" = hackage.ansi-terminal."0.8.1"; - "unliftio-core" = hackage.unliftio-core."0.1.2.0"; - "base-compat" = hackage.base-compat."0.10.4"; - "x509-system" = hackage.x509-system."1.6.6"; - "polyparse" = hackage.polyparse."1.12"; - "hnix" = hackage.hnix."0.5.2"; - "bifunctors" = hackage.bifunctors."5.5.3"; - "cryptohash-sha256" = hackage.cryptohash-sha256."0.11.101.0"; - "interpolate" = hackage.interpolate."0.2.0"; - "old-time" = hackage.old-time."1.1.0.3"; - "regex-tdfa" = hackage.regex-tdfa."1.2.3.1"; - "text-metrics" = hackage.text-metrics."0.3.0"; - "old-locale" = hackage.old-locale."1.0.0.7"; - "http-client-tls" = hackage.http-client-tls."0.3.5.3"; - "contravariant" = hackage.contravariant."1.5"; - "mime-types" = hackage.mime-types."0.1.0.8"; - "StateVar" = hackage.StateVar."1.1.1.1"; - "regex-base" = hackage.regex-base."0.93.2"; - "th-expand-syns" = hackage.th-expand-syns."0.4.4.0"; - "cryptonite" = hackage.cryptonite."0.25"; - "zlib" = hackage.zlib."0.6.2"; - "network-uri" = hackage.network-uri."2.6.1.0"; - "asn1-parse" = hackage.asn1-parse."0.9.4"; - "microlens-aeson" = hackage.microlens-aeson."2.3.0"; - "happy" = hackage.happy."1.19.9"; - "hashable" = hackage.hashable."1.2.7.0"; - "cpphs" = hackage.cpphs."1.20.8"; - "transformers-base" = hackage.transformers-base."0.4.5.2"; - "cryptohash-sha512" = hackage.cryptohash-sha512."0.11.100.1"; - "vector-algorithms" = hackage.vector-algorithms."0.8.0.0"; - "byteable" = hackage.byteable."0.1.1"; - "pretty-show" = hackage.pretty-show."1.8.2"; - "base16-bytestring" = hackage.base16-bytestring."0.1.1.6"; - "attoparsec" = hackage.attoparsec."0.13.2.2"; - "colour" = hackage.colour."2.3.4"; - "infer-license" = hackage.infer-license."0.2.0"; - "optparse-applicative" = hackage.optparse-applicative."0.14.2.0"; - "random" = hackage.random."1.1"; - "uuid-types" = hackage.uuid-types."1.0.3"; - "scientific" = hackage.scientific."0.3.6.2"; - "monadlist" = hackage.monadlist."0.0.2"; - "asn1-encoding" = hackage.asn1-encoding."0.9.5"; - "QuickCheck" = hackage.QuickCheck."2.12.4"; - "half" = hackage.half."0.3"; - "haskell-src-meta" = hackage.haskell-src-meta."0.8.0.3"; - "cabal-doctest" = hackage.cabal-doctest."1.0.6"; - "th-lift" = hackage.th-lift."0.7.11"; - "resourcet" = hackage.resourcet."1.2.1"; - "http-types" = hackage.http-types."0.12.1"; - "microlens" = hackage.microlens."0.4.9.1"; - "Glob" = hackage.Glob."0.9.2"; - "aeson" = hackage.aeson."1.4.0.0"; - "mono-traversable" = hackage.mono-traversable."1.0.9.0"; - "primitive" = hackage.primitive."0.6.4.0"; - "safe" = hackage.safe."0.3.17"; - "yaml" = hackage.yaml."0.10.2.0"; - "transformers-compat" = hackage.transformers-compat."0.6.2"; - "profunctors" = hackage.profunctors."5.3"; - "vector" = hackage.vector."0.12.0.1"; - "time-locale-compat" = hackage.time-locale-compat."0.1.1.5"; - "hpack" = hackage.hpack."0.31.0"; + http-client.revision = hackage.http-client."0.5.13.1".revisions.default; + http-client.flags.network-uri = true; + semigroupoids.revision = hackage.semigroupoids."5.3.1".revisions.default; + semigroupoids.flags.comonad = true; + semigroupoids.flags.doctests = true; + semigroupoids.flags.unordered-containers = true; + semigroupoids.flags.distributive = true; + semigroupoids.flags.tagged = true; + semigroupoids.flags.containers = true; + semigroupoids.flags.contravariant = true; + cookie.revision = hackage.cookie."0.4.4".revisions.default; + tf-random.revision = hackage.tf-random."0.5".revisions.default; + exceptions.revision = hackage.exceptions."0.10.0".revisions.default; + free.revision = hackage.free."5.1".revisions.default; + void.revision = hackage.void."0.7.2".revisions.default; + void.flags.safe = false; + cereal.revision = hackage.cereal."0.5.7.0".revisions.default; + cereal.flags.bytestring-builder = false; + streaming-commons.revision = hackage.streaming-commons."0.2.1.0".revisions.default; + streaming-commons.flags.use-bytestring-builder = false; + regex-tdfa-text.revision = hackage.regex-tdfa-text."1.0.0.3".revisions.default; + serialise.revision = hackage.serialise."0.2.0.0".revisions.default; + serialise.flags.newtime15 = true; + cryptohash-sha1.revision = hackage.cryptohash-sha1."0.11.100.1".revisions.default; + haskell-lexer.revision = hackage.haskell-lexer."1.0.1".revisions.default; + socks.revision = hackage.socks."0.5.6".revisions.default; + integer-logarithms.revision = hackage.integer-logarithms."1.0.2.2".revisions.default; + integer-logarithms.flags.check-bounds = false; + integer-logarithms.flags.integer-gmp = true; + these.revision = hackage.these."0.7.4".revisions.default; + lens-family.revision = hackage.lens-family."1.2.2".revisions.default; + basement.revision = hackage.basement."0.0.8".revisions.default; + ansi-wl-pprint.revision = hackage.ansi-wl-pprint."0.6.8.2".revisions.default; + ansi-wl-pprint.flags.example = false; + logict.revision = hackage.logict."0.6.0.2".revisions.default; + data-fix.revision = hackage.data-fix."0.2.0".revisions.default; + case-insensitive.revision = hackage.case-insensitive."1.2.0.11".revisions.default; + x509-validation.revision = hackage.x509-validation."1.6.10".revisions.default; + extra.revision = hackage.extra."1.6.9".revisions.default; + hourglass.revision = hackage.hourglass."0.2.12".revisions.default; + haskeline.revision = hackage.haskeline."0.7.4.3".revisions.default; + haskeline.flags.terminfo = true; + hashing.revision = hackage.hashing."0.1.0.1".revisions.default; + split.revision = hackage.split."0.2.3.3".revisions.default; + stm.revision = hackage.stm."2.4.5.1".revisions.default; + data-default-class.revision = hackage.data-default-class."0.1.2.0".revisions.default; + comonad.revision = hackage.comonad."5.0.4".revisions.default; + comonad.flags.distributive = true; + comonad.flags.test-doctests = true; + comonad.flags.containers = true; + comonad.flags.contravariant = true; + parser-combinators.revision = hackage.parser-combinators."1.0.0".revisions.default; + parser-combinators.flags.dev = false; + deriving-compat.revision = hackage.deriving-compat."0.5.1".revisions.default; + deriving-compat.flags.base-4-9 = true; + deriving-compat.flags.template-haskell-2-11 = true; + deriving-compat.flags.new-functor-classes = true; + pointed.revision = hackage.pointed."5.0.1".revisions.default; + pointed.flags.semigroupoids = true; + pointed.flags.stm = true; + pointed.flags.comonad = true; + pointed.flags.unordered-containers = true; + pointed.flags.kan-extensions = true; + pointed.flags.semigroups = true; + pointed.flags.tagged = true; + pointed.flags.containers = true; + pointed.flags.transformers = true; + unordered-containers.revision = hackage.unordered-containers."0.2.9.0".revisions.default; + unordered-containers.flags.debug = false; + pem.revision = hackage.pem."0.2.4".revisions.default; + adjunctions.revision = hackage.adjunctions."4.4".revisions.default; + cryptohash-md5.revision = hackage.cryptohash-md5."0.11.100.1".revisions.default; + invariant.revision = hackage.invariant."0.5.1".revisions.default; + clock.revision = hackage.clock."0.7.2".revisions.default; + clock.flags.llvm = false; + megaparsec.revision = hackage.megaparsec."6.5.0".revisions.default; + megaparsec.flags.dev = false; + th-orphans.revision = hackage.th-orphans."0.13.6".revisions.default; + syb.revision = hackage.syb."0.7".revisions.default; + distributive.revision = hackage.distributive."0.6".revisions.default; + distributive.flags.semigroups = true; + distributive.flags.tagged = true; + kan-extensions.revision = hackage.kan-extensions."5.2".revisions.default; + cborg.revision = hackage.cborg."0.2.0.0".revisions.default; + cborg.flags.optimize-gmp = true; + foundation.revision = hackage.foundation."0.0.21".revisions.default; + foundation.flags.minimal-deps = false; + foundation.flags.doctest = false; + foundation.flags.linktest = false; + foundation.flags.experimental = false; + foundation.flags.bounds-check = false; + foundation.flags.bench-all = false; + tls.revision = hackage.tls."1.4.1".revisions.default; + tls.flags.compat = true; + tls.flags.network = true; + tls.flags.hans = false; + asn1-types.revision = hackage.asn1-types."0.3.2".revisions.default; + network.revision = hackage.network."2.8.0.0".revisions.default; + async.revision = hackage.async."2.2.1".revisions.default; + async.flags.bench = false; + x509-store.revision = hackage.x509-store."1.6.6".revisions.default; + connection.revision = hackage.connection."0.2.8".revisions.default; + dlist.revision = hackage.dlist."0.8.0.5".revisions.default; + conduit.revision = hackage.conduit."1.3.0.3".revisions.default; + lens-family-th.revision = hackage.lens-family-th."0.5.0.2".revisions.default; + vector-instances.revision = hackage.vector-instances."3.4".revisions.default; + vector-instances.flags.hashable = true; + semigroups.revision = hackage.semigroups."0.18.5".revisions.default; + semigroups.flags.bytestring = true; + semigroups.flags.unordered-containers = true; + semigroups.flags.text = true; + semigroups.flags.tagged = true; + semigroups.flags.containers = true; + semigroups.flags.binary = true; + semigroups.flags.hashable = true; + semigroups.flags.transformers = true; + semigroups.flags.deepseq = true; + semigroups.flags.bytestring-builder = false; + th-reify-many.revision = hackage.th-reify-many."0.1.8".revisions.default; + lens-family-core.revision = hackage.lens-family-core."1.2.2".revisions.default; + base-orphans.revision = hackage.base-orphans."0.8".revisions.default; + memory.revision = hackage.memory."0.14.16".revisions.default; + memory.flags.support_bytestring = true; + memory.flags.support_foundation = true; + memory.flags.support_deepseq = true; + repline.revision = hackage.repline."0.1.7.0".revisions.default; + th-abstraction.revision = hackage.th-abstraction."0.2.8.0".revisions.default; + xml.revision = hackage.xml."1.3.14".revisions.default; + th-lift-instances.revision = hackage.th-lift-instances."0.1.11".revisions.default; + tagged.revision = hackage.tagged."0.8.6".revisions.default; + tagged.flags.transformers = true; + tagged.flags.deepseq = true; + haskell-src-exts.revision = hackage.haskell-src-exts."1.20.2".revisions.default; + x509.revision = hackage.x509."1.7.4".revisions.default; + keys.revision = hackage.keys."3.12.1".revisions.default; + blaze-builder.revision = hackage.blaze-builder."0.4.1.0".revisions.default; + ansi-terminal.revision = hackage.ansi-terminal."0.8.1".revisions.default; + ansi-terminal.flags.example = false; + unliftio-core.revision = hackage.unliftio-core."0.1.2.0".revisions.default; + base-compat.revision = hackage.base-compat."0.10.4".revisions.default; + x509-system.revision = hackage.x509-system."1.6.6".revisions.default; + polyparse.revision = hackage.polyparse."1.12".revisions.default; + hnix.revision = hackage.hnix."0.5.2".revisions.default; + hnix.flags.tracing = false; + hnix.flags.profiling = false; + hnix.flags.optimize = false; + tar.revision = hackage.tar."0.5.1.0".revisions.default; + tar.flags.old-time = false; + tar.flags.old-bytestring = false; + bifunctors.revision = hackage.bifunctors."5.5.3".revisions.default; + bifunctors.flags.semigroups = true; + bifunctors.flags.tagged = true; + utf8-string.revision = hackage.utf8-string."1.0.1.1".revisions.default; + cryptohash-sha256.revision = hackage.cryptohash-sha256."0.11.101.0".revisions.default; + cryptohash-sha256.flags.exe = false; + interpolate.revision = hackage.interpolate."0.2.0".revisions.default; + old-time.revision = hackage.old-time."1.1.0.3".revisions.default; + regex-tdfa.revision = hackage.regex-tdfa."1.2.3.1".revisions.default; + regex-tdfa.flags.devel = false; + text-metrics.revision = hackage.text-metrics."0.3.0".revisions.default; + text-metrics.flags.dev = false; + old-locale.revision = hackage.old-locale."1.0.0.7".revisions.default; + http-client-tls.revision = hackage.http-client-tls."0.3.5.3".revisions.default; + contravariant.revision = hackage.contravariant."1.5".revisions.default; + contravariant.flags.semigroups = true; + contravariant.flags.tagged = true; + contravariant.flags.statevar = true; + contravariant.flags.safe = false; + mime-types.revision = hackage.mime-types."0.1.0.8".revisions.default; + StateVar.revision = hackage.StateVar."1.1.1.1".revisions.default; + regex-base.revision = hackage.regex-base."0.93.2".revisions.default; + regex-base.flags.splitbase = true; + regex-base.flags.newbase = true; + th-expand-syns.revision = hackage.th-expand-syns."0.4.4.0".revisions.default; + cryptonite.revision = hackage.cryptonite."0.25".revisions.default; + cryptonite.flags.support_sse = false; + cryptonite.flags.integer-gmp = true; + cryptonite.flags.support_rdrand = true; + cryptonite.flags.support_aesni = true; + cryptonite.flags.support_deepseq = true; + cryptonite.flags.support_pclmuldq = false; + cryptonite.flags.check_alignment = false; + cryptonite.flags.old_toolchain_inliner = false; + zlib.revision = hackage.zlib."0.6.2".revisions.default; + zlib.flags.non-blocking-ffi = false; + zlib.flags.pkg-config = false; + network-uri.revision = hackage.network-uri."2.6.1.0".revisions.default; + asn1-parse.revision = hackage.asn1-parse."0.9.4".revisions.default; + microlens-aeson.revision = hackage.microlens-aeson."2.3.0".revisions.default; + happy.revision = hackage.happy."1.19.9".revisions.default; + happy.flags.small_base = true; + hashable.revision = hackage.hashable."1.2.7.0".revisions.default; + hashable.flags.sse2 = true; + hashable.flags.integer-gmp = true; + hashable.flags.sse41 = false; + hashable.flags.examples = false; + cpphs.revision = hackage.cpphs."1.20.8".revisions.default; + transformers-base.revision = hackage.transformers-base."0.4.5.2".revisions.default; + transformers-base.flags.orphaninstances = true; + cryptohash-sha512.revision = hackage.cryptohash-sha512."0.11.100.1".revisions.default; + vector-algorithms.revision = hackage.vector-algorithms."0.7.0.4".revisions.default; + vector-algorithms.flags.unsafechecks = false; + vector-algorithms.flags.internalchecks = false; + vector-algorithms.flags.llvm = false; + vector-algorithms.flags.boundschecks = true; + vector-algorithms.flags.bench = false; + vector-algorithms.flags.properties = true; + byteable.revision = hackage.byteable."0.1.1".revisions.default; + pretty-show.revision = hackage.pretty-show."1.8.2".revisions.default; + base16-bytestring.revision = hackage.base16-bytestring."0.1.1.6".revisions.default; + attoparsec.revision = hackage.attoparsec."0.13.2.2".revisions.default; + attoparsec.flags.developer = false; + colour.revision = hackage.colour."2.3.4".revisions.default; + infer-license.revision = hackage.infer-license."0.2.0".revisions.default; + optparse-applicative.revision = hackage.optparse-applicative."0.14.2.0".revisions.default; + random.revision = hackage.random."1.1".revisions.default; + uuid-types.revision = hackage.uuid-types."1.0.3".revisions.default; + scientific.revision = hackage.scientific."0.3.6.2".revisions.default; + scientific.flags.integer-simple = false; + scientific.flags.bytestring-builder = false; + monadlist.revision = hackage.monadlist."0.0.2".revisions.default; + asn1-encoding.revision = hackage.asn1-encoding."0.9.5".revisions.default; + QuickCheck.revision = hackage.QuickCheck."2.11.3".revisions.default; + QuickCheck.flags.templatehaskell = true; + half.revision = hackage.half."0.3".revisions.default; + haskell-src-meta.revision = hackage.haskell-src-meta."0.8.0.3".revisions.default; + cabal-doctest.revision = hackage.cabal-doctest."1.0.6".revisions.default; + th-lift.revision = hackage.th-lift."0.7.11".revisions.default; + resourcet.revision = hackage.resourcet."1.2.1".revisions.default; + http-types.revision = hackage.http-types."0.12.1".revisions.default; + microlens.revision = hackage.microlens."0.4.9.1".revisions.default; + Glob.revision = hackage.Glob."0.9.2".revisions.default; + aeson.revision = hackage.aeson."1.4.0.0".revisions.default; + aeson.flags.cffi = false; + aeson.flags.fast = false; + aeson.flags.bytestring-builder = false; + aeson.flags.developer = false; + mono-traversable.revision = hackage.mono-traversable."1.0.9.0".revisions.default; + primitive.revision = hackage.primitive."0.6.4.0".revisions.default; + safe.revision = hackage.safe."0.3.17".revisions.default; + yaml.revision = hackage.yaml."0.10.1.1".revisions.default; + yaml.flags.no-exe = true; + yaml.flags.no-examples = true; + yaml.flags.system-libyaml = false; + yaml.flags.no-unicode = false; + transformers-compat.revision = hackage.transformers-compat."0.6.2".revisions.default; + transformers-compat.flags.five = false; + transformers-compat.flags.generic-deriving = true; + transformers-compat.flags.two = false; + transformers-compat.flags.five-three = true; + transformers-compat.flags.mtl = true; + transformers-compat.flags.four = false; + transformers-compat.flags.three = false; + profunctors.revision = hackage.profunctors."5.3".revisions.default; + vector.revision = hackage.vector."0.12.0.1".revisions.default; + vector.flags.unsafechecks = false; + vector.flags.internalchecks = false; + vector.flags.wall = false; + vector.flags.boundschecks = true; + time-locale-compat.revision = hackage.time-locale-compat."0.1.1.5".revisions.default; + time-locale-compat.flags.old-locale = false; + hpack.revision = hackage.hpack."0.31.0".revisions.default; }; compiler = { version = "8.4.3"; @@ -239,7 +368,6 @@ hackage: repline = dontCheck' (super.repline); th-abstraction = dontCheck' (super.th-abstraction); xml = dontCheck' (super.xml); - erf = dontCheck' (super.erf); th-lift-instances = dontCheck' (super.th-lift-instances); tagged = dontCheck' (super.tagged); haskell-src-exts = dontCheck' (super.haskell-src-exts); @@ -252,7 +380,9 @@ hackage: x509-system = dontCheck' (super.x509-system); polyparse = dontCheck' (super.polyparse); hnix = dontCheck' (super.hnix); + tar = dontCheck' (super.tar); bifunctors = dontCheck' (super.bifunctors); + utf8-string = dontCheck' (super.utf8-string); cryptohash-sha256 = dontCheck' (super.cryptohash-sha256); interpolate = dontCheck' (super.interpolate); old-time = dontCheck' (super.old-time); From 4d6d7414d2ffce23413f510e6e17b523001e79d9 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 16 Oct 2018 02:04:39 -0400 Subject: [PATCH 17/20] Fix forgotten cabal file --- nix/new-builder.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nix/new-builder.nix b/nix/new-builder.nix index 1473fa7..f84bf5f 100644 --- a/nix/new-builder.nix +++ b/nix/new-builder.nix @@ -12,7 +12,11 @@ }@config: let - cabalFile = null; + cabalFile = if revision == null || revision == 0 then null else + fetchurl { + url = "https://hackage.haskell.org/package/${name}/revision/${toString revision}.cabal"; + sha256 = revisionSha256; + }; defaultSetupSrc = builtins.toFile "Setup.hs" '' import Distribution.Simple main = defaultMain From 5b219b6b3508cc1635c473840841c00fdc4e873c Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 16 Oct 2018 20:12:41 -0400 Subject: [PATCH 18/20] Abstract drivers --- nix/cabal-licenses.nix | 3 +- nix/comp-builder.nix | 2 +- nix/compat-driver.nix | 13 ++++++++ nix/component-driver.nix | 11 +++++++ nix/default.nix | 34 ++++++++++---------- nix/driver.nix | 42 ++++++------------------ plan.nix | 69 +++++++++++++++++----------------------- 7 files changed, 81 insertions(+), 93 deletions(-) create mode 100644 nix/compat-driver.nix create mode 100644 nix/component-driver.nix diff --git a/nix/cabal-licenses.nix b/nix/cabal-licenses.nix index 8ecc695..f5e1ef9 100644 --- a/nix/cabal-licenses.nix +++ b/nix/cabal-licenses.nix @@ -1,6 +1,7 @@ -stdenv: with stdenv.lib.licenses; +lib: with lib.licenses; { BSD-2-Clause = bsd2; BSD-3-Clause = bsd3; MIT = mit; + ISC = isc; } diff --git a/nix/comp-builder.nix b/nix/comp-builder.nix index 8622c3f..c417e0b 100644 --- a/nix/comp-builder.nix +++ b/nix/comp-builder.nix @@ -56,7 +56,7 @@ in stdenv.mkDerivation { meta = { homepage = package.homepage; description = package.synopsis; - license = (import ./cabal-licenses.nix stdenv).${package.license}; + license = (import ./cabal-licenses.nix lib).${package.license}; }; CABAL_CONFIG = writeText diff --git a/nix/compat-driver.nix b/nix/compat-driver.nix new file mode 100644 index 0000000..0315f36 --- /dev/null +++ b/nix/compat-driver.nix @@ -0,0 +1,13 @@ +{ pkgs, lib, haskellLib, ghc, weakCallPackage, plan }: + +lib.fix (hsPkgs: pkgs.callPackage "${pkgs.path}/pkgs/development/haskell-modules" { + haskellLib = pkgs.haskell.lib; + inherit ghc; + buildHaskellPackages = hsPkgs; + compilerConfig = _: _: lib.mapAttrs (_: _: null) plan.compiler.packages; + initialPackages = self: _: + lib.mapAttrs + (_: pkg: self.callPackage ./driver.nix { expr = lib.fix pkg; inherit lib; }) + (plan.packages self); + packageSetConfig = plan.overlay pkgs; +}) diff --git a/nix/component-driver.nix b/nix/component-driver.nix new file mode 100644 index 0000000..b33cce4 --- /dev/null +++ b/nix/component-driver.nix @@ -0,0 +1,11 @@ +{ pkgs, lib, haskellLib, ghc, weakCallPackage, plan }: +let + new-builder = weakCallPackage pkgs ./new-builder.nix { + inherit haskellLib ghc weakCallPackage; + }; +in +lib.fix (self: + { buildPackages = self; } + // lib.mapAttrs (_: _: null) plan.compiler.packages + // lib.mapAttrs (_: pkg: new-builder (lib.fix pkg)) (plan.packages self) +) diff --git a/nix/default.nix b/nix/default.nix index 8984ced..3205e70 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,6 +1,7 @@ { pkgs ? import {} , planFunc ? import ../stackage/lts-11.4.nix , hackage ? import ../hackage +, driver ? ./component-driver.nix }: (pkgs.lib.fix (self: with self; { @@ -41,15 +42,15 @@ in lib.mapAttrs (_: rev2Config) (version.revisions // contentAddressedRevs); })); plan = - let - args = { - inherit hsPkgs compiler system pkgconfPkgs; - pkgs = adjustedPkgs; - }; - p = planFunc hackageConfigs; + let p = planFunc hackageConfigs; in p // { - packages = lib.mapAttrs - (pname: { revision, flags ? {} }: self: + packages = hsPkgs: + let + args = { + inherit hsPkgs compiler system pkgconfPkgs; + pkgs = adjustedPkgs; + }; + in lib.mapAttrs (pname: { revision, flags ? {} }: self: # Set the flags with the rhs of the recursiveUpdate, but # pass the final choice in flags using open recursion. lib.recursiveUpdate (import revision (args // { inherit (self) flags; })) { @@ -60,9 +61,6 @@ p.packages; }; - new-builder = weakCallPackage pkgs ./new-builder.nix { - inherit haskellLib ghc weakCallPackage; - }; cabal = import ./cabal-os-arch-comp.nix; compiler = cabal.compiler // { @@ -112,12 +110,12 @@ fftw3 = pkgs.fftw; }; - configs = lib.mapAttrs (_: lib.fix) (plan.packages // { - stack = self: let super = plan.packages.stack self; in super // { flags = super.flags // { hide-dependency-versions = true; }; }; - }); + # hsPkgs = adjustedPkgs + # // { buildPackages = hsPkgs; } + # // lib.mapAttrs (_: _: null) (plan.compiler.packages // { hsc2hs = "0.68.2"; }) + # // lib.mapAttrs (_: driver) configs; - hsPkgs = adjustedPkgs - // { buildPackages = hsPkgs; } - // lib.mapAttrs (_: _: null) (plan.compiler.packages // { hsc2hs = "0.68.2"; }) - // lib.mapAttrs (_: new-builder) configs; + hsPkgs = weakCallPackage pkgs driver { + inherit haskellLib ghc weakCallPackage plan; + }; })) diff --git a/nix/driver.nix b/nix/driver.nix index 4c373bf..866a26f 100644 --- a/nix/driver.nix +++ b/nix/driver.nix @@ -1,34 +1,10 @@ -{ cabalexpr, pkgs, compiler ? "Ghc", os ? "OSX", arch ? "X86_64" }: -assert (builtins.elem compiler ["Ghc" "Ghcjs" "Nhc" "Yhc" "Hugs" "Hbc" "Helium" "Jhc" "Lhc" "Uhc" "Eta"]); -assert (builtins.elem os ["Linux" "Windows" "OSX" "FreeBSD" "OpenBSD" "NetBSD" "DragonFly" "Solaris" "AIX" "HPUX" "IRIX" "HaLVM" "Hurd" "IOS" "Android" "Ghcjs"]); -assert (builtins.elem arch ["I386" "X86_64" "PPC" "PPC64" "Sparc" "Arm" "Aarch64" "Mips" "SH" "IA64" "S390" "Alpha" "Hppa" "Rs6000" "M68k" "Vax" "JavaScript"]); +{ lib, expr, mkDerivation }: -with rec { +let # utilities - collectAttr = a: s: pkgs.lib.lists.fold (e: acc: (if e ? ${a} then e.${a} else []) ++ acc) [] (builtins.attrValues s); - - # resolver for cabal license to nix license - resolve = { license = stdenv: license: (import ./cabal-licenses.nix stdenv).${license}; }; - - # cabal os, arch and compilers. - cabal = import ./cabal-os-arch-comp.nix; - - expr = cabalexpr { - # null out self references. Tests, Benchmarks, ... - # naturally depend on the package (as a library), but - # we don't want those dependencies. - hsPkgs = pkgs.haskellPackages // { ${pname} = null; }; - pkgs = pkgs; - compiler = cabal.compiler // { "is${compiler}" = true; }; - system = cabal.os // { "is${os}" = true; } - // cabal.arch // { "is${arch}" = true; }; - }; - + collectAttr = a: s: lib.lists.fold (e: acc: (if e ? ${a} then e.${a} else []) ++ acc) [] (builtins.attrValues s); pname = expr.package.identifier.name; -}; -{ mkDerivation, stdenv }: -mkDerivation { - +in mkDerivation { inherit pname; version = expr.package.identifier.version; sha256 = null; @@ -38,13 +14,13 @@ mkDerivation { homepage = expr.package.homepage; description = expr.package.synopsis; - license = resolve.license stdenv expr.package.license; -} // pkgs.lib.optionalAttrs (builtins.hasAttr pname expr.components) { + license = (import ./cabal-licenses.nix lib).${expr.package.license}; +} // lib.optionalAttrs (builtins.hasAttr pname expr.components) { libraryHaskeallDepends = expr.components.${pname}.depends; -} // pkgs.lib.optionalAttrs (builtins.hasAttr "exes" expr.components) { +} // lib.optionalAttrs (builtins.hasAttr "exes" expr.components) { executableHaskellDepends = collectAttr "depends" expr.components.exes; -} // pkgs.lib.optionalAttrs (builtins.hasAttr "tests" expr.components) { +} // lib.optionalAttrs (builtins.hasAttr "tests" expr.components) { testHaskellDepends = collectAttr "depends" expr.components.tests; -} // pkgs.lib.optionalAttrs (builtins.hasAttr "benchmarks" expr.components) { +} // lib.optionalAttrs (builtins.hasAttr "benchmarks" expr.components) { benchmarkHaskellDepends = collectAttr "depends" expr.components.benchmarks; } diff --git a/plan.nix b/plan.nix index def4070..28cb160 100644 --- a/plan.nix +++ b/plan.nix @@ -22,16 +22,16 @@ hackage: streaming-commons.revision = hackage.streaming-commons."0.2.1.0".revisions.default; streaming-commons.flags.use-bytestring-builder = false; regex-tdfa-text.revision = hackage.regex-tdfa-text."1.0.0.3".revisions.default; - serialise.revision = hackage.serialise."0.2.0.0".revisions.default; + serialise.revision = hackage.serialise."0.2.1.0".revisions.default; serialise.flags.newtime15 = true; cryptohash-sha1.revision = hackage.cryptohash-sha1."0.11.100.1".revisions.default; - haskell-lexer.revision = hackage.haskell-lexer."1.0.1".revisions.default; + haskell-lexer.revision = hackage.haskell-lexer."1.0.2".revisions.default; socks.revision = hackage.socks."0.5.6".revisions.default; integer-logarithms.revision = hackage.integer-logarithms."1.0.2.2".revisions.default; integer-logarithms.flags.check-bounds = false; integer-logarithms.flags.integer-gmp = true; - these.revision = hackage.these."0.7.4".revisions.default; - lens-family.revision = hackage.lens-family."1.2.2".revisions.default; + these.revision = hackage.these."0.7.5".revisions.default; + lens-family.revision = hackage.lens-family."1.2.3".revisions.default; basement.revision = hackage.basement."0.0.8".revisions.default; ansi-wl-pprint.revision = hackage.ansi-wl-pprint."0.6.8.2".revisions.default; ansi-wl-pprint.flags.example = false; @@ -39,13 +39,13 @@ hackage: data-fix.revision = hackage.data-fix."0.2.0".revisions.default; case-insensitive.revision = hackage.case-insensitive."1.2.0.11".revisions.default; x509-validation.revision = hackage.x509-validation."1.6.10".revisions.default; - extra.revision = hackage.extra."1.6.9".revisions.default; + extra.revision = hackage.extra."1.6.13".revisions.default; hourglass.revision = hackage.hourglass."0.2.12".revisions.default; haskeline.revision = hackage.haskeline."0.7.4.3".revisions.default; haskeline.flags.terminfo = true; hashing.revision = hackage.hashing."0.1.0.1".revisions.default; split.revision = hackage.split."0.2.3.3".revisions.default; - stm.revision = hackage.stm."2.4.5.1".revisions.default; + stm.revision = hackage.stm."2.5.0.0".revisions.default; data-default-class.revision = hackage.data-default-class."0.1.2.0".revisions.default; comonad.revision = hackage.comonad."5.0.4".revisions.default; comonad.flags.distributive = true; @@ -54,7 +54,7 @@ hackage: comonad.flags.contravariant = true; parser-combinators.revision = hackage.parser-combinators."1.0.0".revisions.default; parser-combinators.flags.dev = false; - deriving-compat.revision = hackage.deriving-compat."0.5.1".revisions.default; + deriving-compat.revision = hackage.deriving-compat."0.5.2".revisions.default; deriving-compat.flags.base-4-9 = true; deriving-compat.flags.template-haskell-2-11 = true; deriving-compat.flags.new-functor-classes = true; @@ -84,15 +84,8 @@ hackage: distributive.flags.semigroups = true; distributive.flags.tagged = true; kan-extensions.revision = hackage.kan-extensions."5.2".revisions.default; - cborg.revision = hackage.cborg."0.2.0.0".revisions.default; + cborg.revision = hackage.cborg."0.2.1.0".revisions.default; cborg.flags.optimize-gmp = true; - foundation.revision = hackage.foundation."0.0.21".revisions.default; - foundation.flags.minimal-deps = false; - foundation.flags.doctest = false; - foundation.flags.linktest = false; - foundation.flags.experimental = false; - foundation.flags.bounds-check = false; - foundation.flags.bench-all = false; tls.revision = hackage.tls."1.4.1".revisions.default; tls.flags.compat = true; tls.flags.network = true; @@ -104,7 +97,7 @@ hackage: x509-store.revision = hackage.x509-store."1.6.6".revisions.default; connection.revision = hackage.connection."0.2.8".revisions.default; dlist.revision = hackage.dlist."0.8.0.5".revisions.default; - conduit.revision = hackage.conduit."1.3.0.3".revisions.default; + conduit.revision = hackage.conduit."1.3.1".revisions.default; lens-family-th.revision = hackage.lens-family-th."0.5.0.2".revisions.default; vector-instances.revision = hackage.vector-instances."3.4".revisions.default; vector-instances.flags.hashable = true; @@ -120,20 +113,22 @@ hackage: semigroups.flags.deepseq = true; semigroups.flags.bytestring-builder = false; th-reify-many.revision = hackage.th-reify-many."0.1.8".revisions.default; - lens-family-core.revision = hackage.lens-family-core."1.2.2".revisions.default; + lens-family-core.revision = hackage.lens-family-core."1.2.3".revisions.default; base-orphans.revision = hackage.base-orphans."0.8".revisions.default; - memory.revision = hackage.memory."0.14.16".revisions.default; + memory.revision = hackage.memory."0.14.18".revisions.default; memory.flags.support_bytestring = true; + memory.flags.support_basement = true; memory.flags.support_foundation = true; memory.flags.support_deepseq = true; - repline.revision = hackage.repline."0.1.7.0".revisions.default; + repline.revision = hackage.repline."0.2.0.0".revisions.default; th-abstraction.revision = hackage.th-abstraction."0.2.8.0".revisions.default; xml.revision = hackage.xml."1.3.14".revisions.default; + erf.revision = hackage.erf."2.0.0.0".revisions.default; th-lift-instances.revision = hackage.th-lift-instances."0.1.11".revisions.default; tagged.revision = hackage.tagged."0.8.6".revisions.default; tagged.flags.transformers = true; tagged.flags.deepseq = true; - haskell-src-exts.revision = hackage.haskell-src-exts."1.20.2".revisions.default; + haskell-src-exts.revision = hackage.haskell-src-exts."1.20.3".revisions.default; x509.revision = hackage.x509."1.7.4".revisions.default; keys.revision = hackage.keys."3.12.1".revisions.default; blaze-builder.revision = hackage.blaze-builder."0.4.1.0".revisions.default; @@ -142,7 +137,6 @@ hackage: unliftio-core.revision = hackage.unliftio-core."0.1.2.0".revisions.default; base-compat.revision = hackage.base-compat."0.10.4".revisions.default; x509-system.revision = hackage.x509-system."1.6.6".revisions.default; - polyparse.revision = hackage.polyparse."1.12".revisions.default; hnix.revision = hackage.hnix."0.5.2".revisions.default; hnix.flags.tracing = false; hnix.flags.profiling = false; @@ -157,12 +151,10 @@ hackage: cryptohash-sha256.revision = hackage.cryptohash-sha256."0.11.101.0".revisions.default; cryptohash-sha256.flags.exe = false; interpolate.revision = hackage.interpolate."0.2.0".revisions.default; - old-time.revision = hackage.old-time."1.1.0.3".revisions.default; regex-tdfa.revision = hackage.regex-tdfa."1.2.3.1".revisions.default; regex-tdfa.flags.devel = false; text-metrics.revision = hackage.text-metrics."0.3.0".revisions.default; text-metrics.flags.dev = false; - old-locale.revision = hackage.old-locale."1.0.0.7".revisions.default; http-client-tls.revision = hackage.http-client-tls."0.3.5.3".revisions.default; contravariant.revision = hackage.contravariant."1.5".revisions.default; contravariant.flags.semigroups = true; @@ -197,16 +189,15 @@ hackage: hashable.flags.integer-gmp = true; hashable.flags.sse41 = false; hashable.flags.examples = false; - cpphs.revision = hackage.cpphs."1.20.8".revisions.default; transformers-base.revision = hackage.transformers-base."0.4.5.2".revisions.default; transformers-base.flags.orphaninstances = true; cryptohash-sha512.revision = hackage.cryptohash-sha512."0.11.100.1".revisions.default; - vector-algorithms.revision = hackage.vector-algorithms."0.7.0.4".revisions.default; + vector-algorithms.revision = hackage.vector-algorithms."0.8.0.1".revisions.default; vector-algorithms.flags.unsafechecks = false; vector-algorithms.flags.internalchecks = false; vector-algorithms.flags.llvm = false; vector-algorithms.flags.boundschecks = true; - vector-algorithms.flags.bench = false; + vector-algorithms.flags.bench = true; vector-algorithms.flags.properties = true; byteable.revision = hackage.byteable."0.1.1".revisions.default; pretty-show.revision = hackage.pretty-show."1.8.2".revisions.default; @@ -215,7 +206,7 @@ hackage: attoparsec.flags.developer = false; colour.revision = hackage.colour."2.3.4".revisions.default; infer-license.revision = hackage.infer-license."0.2.0".revisions.default; - optparse-applicative.revision = hackage.optparse-applicative."0.14.2.0".revisions.default; + optparse-applicative.revision = hackage.optparse-applicative."0.14.3.0".revisions.default; random.revision = hackage.random."1.1".revisions.default; uuid-types.revision = hackage.uuid-types."1.0.3".revisions.default; scientific.revision = hackage.scientific."0.3.6.2".revisions.default; @@ -223,17 +214,20 @@ hackage: scientific.flags.bytestring-builder = false; monadlist.revision = hackage.monadlist."0.0.2".revisions.default; asn1-encoding.revision = hackage.asn1-encoding."0.9.5".revisions.default; - QuickCheck.revision = hackage.QuickCheck."2.11.3".revisions.default; + QuickCheck.revision = hackage.QuickCheck."2.12.6.1".revisions.default; QuickCheck.flags.templatehaskell = true; half.revision = hackage.half."0.3".revisions.default; haskell-src-meta.revision = hackage.haskell-src-meta."0.8.0.3".revisions.default; cabal-doctest.revision = hackage.cabal-doctest."1.0.6".revisions.default; + libyaml.revision = hackage.libyaml."0.1.0.0".revisions.default; + libyaml.flags.system-libyaml = false; + libyaml.flags.no-unicode = false; th-lift.revision = hackage.th-lift."0.7.11".revisions.default; - resourcet.revision = hackage.resourcet."1.2.1".revisions.default; - http-types.revision = hackage.http-types."0.12.1".revisions.default; + resourcet.revision = hackage.resourcet."1.2.2".revisions.default; + http-types.revision = hackage.http-types."0.12.2".revisions.default; microlens.revision = hackage.microlens."0.4.9.1".revisions.default; - Glob.revision = hackage.Glob."0.9.2".revisions.default; - aeson.revision = hackage.aeson."1.4.0.0".revisions.default; + Glob.revision = hackage.Glob."0.9.3".revisions.default; + aeson.revision = hackage.aeson."1.4.1.0".revisions.default; aeson.flags.cffi = false; aeson.flags.fast = false; aeson.flags.bytestring-builder = false; @@ -241,11 +235,9 @@ hackage: mono-traversable.revision = hackage.mono-traversable."1.0.9.0".revisions.default; primitive.revision = hackage.primitive."0.6.4.0".revisions.default; safe.revision = hackage.safe."0.3.17".revisions.default; - yaml.revision = hackage.yaml."0.10.1.1".revisions.default; + yaml.revision = hackage.yaml."0.11.0.0".revisions.default; yaml.flags.no-exe = true; yaml.flags.no-examples = true; - yaml.flags.system-libyaml = false; - yaml.flags.no-unicode = false; transformers-compat.revision = hackage.transformers-compat."0.6.2".revisions.default; transformers-compat.flags.five = false; transformers-compat.flags.generic-deriving = true; @@ -349,7 +341,6 @@ hackage: distributive = dontCheck' (super.distributive); kan-extensions = dontCheck' (super.kan-extensions); cborg = dontCheck' (super.cborg); - foundation = dontCheck' (super.foundation); tls = dontCheck' (super.tls); asn1-types = dontCheck' (super.asn1-types); network = dontCheck' (super.network); @@ -368,6 +359,7 @@ hackage: repline = dontCheck' (super.repline); th-abstraction = dontCheck' (super.th-abstraction); xml = dontCheck' (super.xml); + erf = dontCheck' (super.erf); th-lift-instances = dontCheck' (super.th-lift-instances); tagged = dontCheck' (super.tagged); haskell-src-exts = dontCheck' (super.haskell-src-exts); @@ -378,17 +370,14 @@ hackage: unliftio-core = dontCheck' (super.unliftio-core); base-compat = dontCheck' (super.base-compat); x509-system = dontCheck' (super.x509-system); - polyparse = dontCheck' (super.polyparse); hnix = dontCheck' (super.hnix); tar = dontCheck' (super.tar); bifunctors = dontCheck' (super.bifunctors); utf8-string = dontCheck' (super.utf8-string); cryptohash-sha256 = dontCheck' (super.cryptohash-sha256); interpolate = dontCheck' (super.interpolate); - old-time = dontCheck' (super.old-time); regex-tdfa = dontCheck' (super.regex-tdfa); text-metrics = dontCheck' (super.text-metrics); - old-locale = dontCheck' (super.old-locale); http-client-tls = dontCheck' (super.http-client-tls); contravariant = dontCheck' (super.contravariant); mime-types = dontCheck' (super.mime-types); @@ -402,7 +391,6 @@ hackage: microlens-aeson = dontCheck' (super.microlens-aeson); happy = dontCheck' (super.happy); hashable = dontCheck' (super.hashable); - cpphs = dontCheck' (super.cpphs); transformers-base = dontCheck' (super.transformers-base); cryptohash-sha512 = dontCheck' (super.cryptohash-sha512); vector-algorithms = dontCheck' (super.vector-algorithms); @@ -422,6 +410,7 @@ hackage: half = dontCheck' (super.half); haskell-src-meta = dontCheck' (super.haskell-src-meta); cabal-doctest = dontCheck' (super.cabal-doctest); + libyaml = dontCheck' (super.libyaml); th-lift = dontCheck' (super.th-lift); resourcet = dontCheck' (super.resourcet); http-types = dontCheck' (super.http-types); From c4d1611c4376e4e53ea8e4fe88879a6b88d14f28 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 16 Oct 2018 20:20:28 -0400 Subject: [PATCH 19/20] Don't null the ghc attr --- nix/compat-driver.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/compat-driver.nix b/nix/compat-driver.nix index 0315f36..f48c7cd 100644 --- a/nix/compat-driver.nix +++ b/nix/compat-driver.nix @@ -4,7 +4,7 @@ lib.fix (hsPkgs: pkgs.callPackage "${pkgs.path}/pkgs/development/haskell-modules haskellLib = pkgs.haskell.lib; inherit ghc; buildHaskellPackages = hsPkgs; - compilerConfig = _: _: lib.mapAttrs (_: _: null) plan.compiler.packages; + compilerConfig = _: _: lib.mapAttrs (_: _: null) (builtins.removeAttrs plan.compiler.packages ["ghc"]); initialPackages = self: _: lib.mapAttrs (_: pkg: self.callPackage ./driver.nix { expr = lib.fix pkg; inherit lib; }) From 97968aa1ddbadae75cbb0179a7bcd5807902969f Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Tue, 16 Oct 2018 21:00:40 -0400 Subject: [PATCH 20/20] Fix compat driver parenthization and sha256 --- nix/cabal-licenses.nix | 1 + nix/compat-driver.nix | 2 +- nix/driver.nix | 13 +++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/nix/cabal-licenses.nix b/nix/cabal-licenses.nix index f5e1ef9..e89d27c 100644 --- a/nix/cabal-licenses.nix +++ b/nix/cabal-licenses.nix @@ -4,4 +4,5 @@ lib: with lib.licenses; BSD-3-Clause = bsd3; MIT = mit; ISC = isc; + LicenseRef-LGPL = "LGPL"; } diff --git a/nix/compat-driver.nix b/nix/compat-driver.nix index f48c7cd..119e313 100644 --- a/nix/compat-driver.nix +++ b/nix/compat-driver.nix @@ -5,7 +5,7 @@ lib.fix (hsPkgs: pkgs.callPackage "${pkgs.path}/pkgs/development/haskell-modules inherit ghc; buildHaskellPackages = hsPkgs; compilerConfig = _: _: lib.mapAttrs (_: _: null) (builtins.removeAttrs plan.compiler.packages ["ghc"]); - initialPackages = self: _: + initialPackages = args: self: lib.mapAttrs (_: pkg: self.callPackage ./driver.nix { expr = lib.fix pkg; inherit lib; }) (plan.packages self); diff --git a/nix/driver.nix b/nix/driver.nix index 866a26f..37cddc7 100644 --- a/nix/driver.nix +++ b/nix/driver.nix @@ -4,10 +4,9 @@ let # utilities collectAttr = a: s: lib.lists.fold (e: acc: (if e ? ${a} then e.${a} else []) ++ acc) [] (builtins.attrValues s); pname = expr.package.identifier.name; -in mkDerivation { +in mkDerivation ({ inherit pname; version = expr.package.identifier.version; - sha256 = null; isLibrary = builtins.hasAttr pname expr.components; isExecutable = builtins.hasAttr "exes" expr.components; @@ -15,12 +14,18 @@ in mkDerivation { homepage = expr.package.homepage; description = expr.package.synopsis; license = (import ./cabal-licenses.nix lib).${expr.package.license}; + +} // lib.optionalAttrs (expr ? revision) { + revision = "${toString expr.revision}"; + editedCabalFile = expr.revisionSha256; +} // lib.optionalAttrs (expr ? sha256) { + inherit (expr) sha256; } // lib.optionalAttrs (builtins.hasAttr pname expr.components) { - libraryHaskeallDepends = expr.components.${pname}.depends; + libraryHaskellDepends = expr.components.${pname}.depends; } // lib.optionalAttrs (builtins.hasAttr "exes" expr.components) { executableHaskellDepends = collectAttr "depends" expr.components.exes; } // lib.optionalAttrs (builtins.hasAttr "tests" expr.components) { testHaskellDepends = collectAttr "depends" expr.components.tests; } // lib.optionalAttrs (builtins.hasAttr "benchmarks" expr.components) { benchmarkHaskellDepends = collectAttr "depends" expr.components.benchmarks; -} +})