From a2e51c3802687355743a1cd4859d5f0200f3f81e Mon Sep 17 00:00:00 2001 From: Auto Update Bot <no-reply@iohk.io> Date: Thu, 24 Oct 2024 21:07:05 +0000 Subject: [PATCH 01/16] update nix-tools-static.nix --- nix-tools-static.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nix-tools-static.nix b/nix-tools-static.nix index 9ab307a25f..7274ecf8ba 100644 --- a/nix-tools-static.nix +++ b/nix-tools-static.nix @@ -1,22 +1,22 @@ -pkgs: let baseurl = "https://github.com/input-output-hk/haskell.nix/releases/download/nix-tools-0.2.6/"; in { +pkgs: let baseurl = "https://github.com/input-output-hk/haskell.nix/releases/download/nix-tools-0.2.8/"; in { aarch64-darwin = pkgs.fetchurl { name = "aarch64-darwin-nix-tools-static"; url = "${baseurl}aarch64-darwin-nix-tools-static.zip"; - sha256 = "sha256-9WpTIWlpUvG3pI+tcbAMh6sMH0QO/coZrxDYWD43iq0="; + sha256 = "sha256-XzVWGDDJUd4SAKREkdN1k3EId3Gs2ji3J2LA0hLalOk="; }; x86_64-darwin = pkgs.fetchurl { name = "x86_64-darwin-nix-tools-static"; url = "${baseurl}x86_64-darwin-nix-tools-static.zip"; - sha256 = "sha256-UUr9bo2OpLPsvHRSeO2B6DKVDVTsHepRlTqN6UZoZ2M="; + sha256 = "sha256-sz9x8U/N0OfkyTltxJbbVaZvW0jemDAfcov3X2xtFmY="; }; aarch64-linux = pkgs.fetchurl { name = "aarch64-linux-nix-tools-static"; url = "${baseurl}aarch64-linux-nix-tools-static.zip"; - sha256 = "sha256-96s6RXN8st0JK0eYSOkTJvnlTxYVdE81+ZUGJEsC46A="; + sha256 = "sha256-gBpNfqtvbQvZzOKhk68+6jw+VUl5ORi3QzPgwyXiKVA="; }; x86_64-linux = pkgs.fetchurl { name = "x86_64-linux-nix-tools-static"; url = "${baseurl}x86_64-linux-nix-tools-static.zip"; - sha256 = "sha256-LMFVUKNycjVFBb3ChZsPbRNgab50zOHl7nMBrDdeTrQ="; + sha256 = "sha256-aZn6D/Cc7anLJvXiKnJpKlizh5jHSYhEwVen/atE97o="; }; } From e579849c0b3ee8b350849c09420110857693ee8b Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Thu, 31 Oct 2024 10:25:34 +0800 Subject: [PATCH 02/16] Bump Cabal-syntax-json --- nix-tools/cabal.project | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nix-tools/cabal.project b/nix-tools/cabal.project index 902e02ba31..83a2062ba4 100644 --- a/nix-tools/cabal.project +++ b/nix-tools/cabal.project @@ -36,5 +36,5 @@ source-repository-package source-repository-package type: git location: https://github.com/andreabedini/Cabal-syntax-json.git - tag: b7192832f730d9181a013ef7c77f2ad0b30cca43 - --sha256: sha256-Yw2HQOCmjOvfKHi3xWbSniAZfyrshOvsgmUbqFmDDpU= + tag: 4778c12bc06670afb7cf36473a3f9dd3d7104c5e + --sha256: sha256-PhqMSvHgTBJ7XzVOrfCpBFV07zegtOMBnivH4Jkq6Kc= From bae536cc37cd3155ca2b2484daa72fe369ca322a Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie <Hamish.K.Mackenzie@gmail.com> Date: Fri, 8 Nov 2024 15:21:37 +1300 Subject: [PATCH 03/16] Revert "update nix-tools-static.nix" This reverts commit 0bb2cb5f8981501f84bdc16681f07a725aebc7f9. --- nix-tools-static.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nix-tools-static.nix b/nix-tools-static.nix index 7274ecf8ba..9ab307a25f 100644 --- a/nix-tools-static.nix +++ b/nix-tools-static.nix @@ -1,22 +1,22 @@ -pkgs: let baseurl = "https://github.com/input-output-hk/haskell.nix/releases/download/nix-tools-0.2.8/"; in { +pkgs: let baseurl = "https://github.com/input-output-hk/haskell.nix/releases/download/nix-tools-0.2.6/"; in { aarch64-darwin = pkgs.fetchurl { name = "aarch64-darwin-nix-tools-static"; url = "${baseurl}aarch64-darwin-nix-tools-static.zip"; - sha256 = "sha256-XzVWGDDJUd4SAKREkdN1k3EId3Gs2ji3J2LA0hLalOk="; + sha256 = "sha256-9WpTIWlpUvG3pI+tcbAMh6sMH0QO/coZrxDYWD43iq0="; }; x86_64-darwin = pkgs.fetchurl { name = "x86_64-darwin-nix-tools-static"; url = "${baseurl}x86_64-darwin-nix-tools-static.zip"; - sha256 = "sha256-sz9x8U/N0OfkyTltxJbbVaZvW0jemDAfcov3X2xtFmY="; + sha256 = "sha256-UUr9bo2OpLPsvHRSeO2B6DKVDVTsHepRlTqN6UZoZ2M="; }; aarch64-linux = pkgs.fetchurl { name = "aarch64-linux-nix-tools-static"; url = "${baseurl}aarch64-linux-nix-tools-static.zip"; - sha256 = "sha256-gBpNfqtvbQvZzOKhk68+6jw+VUl5ORi3QzPgwyXiKVA="; + sha256 = "sha256-96s6RXN8st0JK0eYSOkTJvnlTxYVdE81+ZUGJEsC46A="; }; x86_64-linux = pkgs.fetchurl { name = "x86_64-linux-nix-tools-static"; url = "${baseurl}x86_64-linux-nix-tools-static.zip"; - sha256 = "sha256-aZn6D/Cc7anLJvXiKnJpKlizh5jHSYhEwVen/atE97o="; + sha256 = "sha256-LMFVUKNycjVFBb3ChZsPbRNgab50zOHl7nMBrDdeTrQ="; }; } From c534a1d2f5b4e7978ea0d8954c1e50875b963244 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie <Hamish.K.Mackenzie@gmail.com> Date: Wed, 11 Dec 2024 21:29:26 +1300 Subject: [PATCH 04/16] Use latest haskellNix and Cabal-syntax-json in nix-tools --- nix-tools/cabal.project | 6 +++--- nix-tools/flake.lock | 30 +++++++++++++++--------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/nix-tools/cabal.project b/nix-tools/cabal.project index 83a2062ba4..b96576a97a 100644 --- a/nix-tools/cabal.project +++ b/nix-tools/cabal.project @@ -1,4 +1,4 @@ -index-state: 2024-10-15T20:31:31Z +index-state: 2024-12-11T00:00:00Z packages: nix-tools @@ -36,5 +36,5 @@ source-repository-package source-repository-package type: git location: https://github.com/andreabedini/Cabal-syntax-json.git - tag: 4778c12bc06670afb7cf36473a3f9dd3d7104c5e - --sha256: sha256-PhqMSvHgTBJ7XzVOrfCpBFV07zegtOMBnivH4Jkq6Kc= + tag: c6c01db076117c309f8ec2e0b8f58b105479f391 + --sha256: sha256-Vj66Sdeq3lizcZxSBJ8QQhPVJ7QDXRdpvDX65RF51oY= diff --git a/nix-tools/flake.lock b/nix-tools/flake.lock index 06581f1296..dee1d1ba2f 100644 --- a/nix-tools/flake.lock +++ b/nix-tools/flake.lock @@ -120,11 +120,11 @@ "hackage": { "flake": false, "locked": { - "lastModified": 1729124899, - "narHash": "sha256-cmb4iMcgk5+jUGMiZGNMzPCAnG17Kz9J6WIitYM17Fc=", + "lastModified": 1733877006, + "narHash": "sha256-rNpSFS/ziUQBPgo6iAbKgU00yRpeCngv215TW0D+kCo=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "138edf81c8bcc4209e9706966f7feece70c37a96", + "rev": "583f569545854160b6bc5606374bf5006a9f6929", "type": "github" }, "original": { @@ -173,11 +173,11 @@ "stackage": "stackage" }, "locked": { - "lastModified": 1729126246, - "narHash": "sha256-OXGwQF3AMERYaVdImhGLlvJgOE8Zr0yURef4J7zlp6k=", + "lastModified": 1733878317, + "narHash": "sha256-Bbr5dUxCH+s1BXfZ5BNxmOOnLZqZUdjeZVWN0KEak/Q=", "owner": "input-output-hk", "repo": "haskell.nix", - "rev": "c2070f089bf688571c14af77744982c86f0c2e21", + "rev": "fa511ea6fd05774bbf97f187fd560658067ff7f7", "type": "github" }, "original": { @@ -579,11 +579,11 @@ }, "nixpkgs-2405": { "locked": { - "lastModified": 1726447378, - "narHash": "sha256-2yV8nmYE1p9lfmLHhOCbYwQC/W8WYfGQABoGzJOb1JQ=", + "lastModified": 1729242558, + "narHash": "sha256-VgcLDu4igNT0eYua6OAl9pWCI0cYXhDbR+pWP44tte0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "086b448a5d54fd117f4dc2dee55c9f0ff461bdc1", + "rev": "4a3f2d3195b60d07530574988df92e049372c10e", "type": "github" }, "original": { @@ -611,11 +611,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1726583932, - "narHash": "sha256-zACxiQx8knB3F8+Ze+1BpiYrI+CbhxyWpcSID9kVhkQ=", + "lastModified": 1729980323, + "narHash": "sha256-eWPRZAlhf446bKSmzw6x7RWEE4IuZgAp8NW3eXZwRAY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "658e7223191d2598641d50ee4e898126768fe847", + "rev": "86e78d3d2084ff87688da662cf78c2af085d8e73", "type": "github" }, "original": { @@ -654,11 +654,11 @@ "stackage": { "flake": false, "locked": { - "lastModified": 1729039017, - "narHash": "sha256-fGExfgG+7UNSOV8YfOrWPpOHWrCjA02gQkeSBhaAzjQ=", + "lastModified": 1733789551, + "narHash": "sha256-0tSxhYw3RqNEHYFYIwJZ99mFDpGr8Dekf+p2ZCEygYY=", "owner": "input-output-hk", "repo": "stackage.nix", - "rev": "df1d8f0960407551fea7af7af75a9c2f9e18de97", + "rev": "db7b3e7ae59867ce0ba21df45f57ea38f57710ab", "type": "github" }, "original": { From 8bf373b692d199f18cfc0018869f1598e943196e Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie <Hamish.K.Mackenzie@gmail.com> Date: Wed, 11 Dec 2024 23:43:42 +1300 Subject: [PATCH 05/16] Use GHC 9.6.6 --- nix-tools/cabal.project | 2 +- nix-tools/static/project.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nix-tools/cabal.project b/nix-tools/cabal.project index b96576a97a..e960f8a0a1 100644 --- a/nix-tools/cabal.project +++ b/nix-tools/cabal.project @@ -1,4 +1,4 @@ -index-state: 2024-12-11T00:00:00Z +index-state: 2024-12-10T00:00:00Z packages: nix-tools diff --git a/nix-tools/static/project.nix b/nix-tools/static/project.nix index e7ed7832e7..c494d320d8 100644 --- a/nix-tools/static/project.nix +++ b/nix-tools/static/project.nix @@ -64,7 +64,7 @@ let static-nix-tools-project = pkgs.haskell-nix.project' { - compiler-nix-name = "ghc928"; + compiler-nix-name = "ghc966"; src = ../.; From 78b0e718e3a007c6d3168b5058f5396867c890ec Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Thu, 12 Dec 2024 12:28:33 +0800 Subject: [PATCH 06/16] refactor: move dummy-ghc-pkg-dump to its own file --- lib/call-cabal-project-to-nix.nix | 228 ++-------------------------- lib/dummy-ghc-pkg-dump.nix | 239 ++++++++++++++++++++++++++++++ overlays/haskell.nix | 6 +- 3 files changed, 253 insertions(+), 220 deletions(-) create mode 100644 lib/dummy-ghc-pkg-dump.nix diff --git a/lib/call-cabal-project-to-nix.nix b/lib/call-cabal-project-to-nix.nix index f51b870b9a..ec7929d374 100644 --- a/lib/call-cabal-project-to-nix.nix +++ b/lib/call-cabal-project-to-nix.nix @@ -1,4 +1,5 @@ -{ pkgs, runCommand, cacert, index-state-hashes, haskellLib }: +{ pkgs, cacert, index-state-hashes, haskellLib }: + { name ? src.name or null # optional name for better error messages , src , materialized-dir ? ../materialized @@ -102,6 +103,7 @@ in let ghc = if ghc' ? latestVersion then __trace "WARNING: ${ghc'.version} is out of date, consider using upgrading to ${ghc'.latestVersion}." ghc' else ghc'; + subDir' = src.origSubDir or ""; subDir = pkgs.lib.strings.removePrefix "/" subDir'; @@ -295,8 +297,6 @@ let fixedProject = replaceSourceRepos rawCabalProject; - ghcSrc = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; - platformString = p: with p.parsed; "${cpu.name}-${vendor.name}-${kernel.name}"; # Dummy `ghc` that uses the captured output @@ -366,222 +366,12 @@ let ''; }; - ghc-pkgs = [ - "Cabal" - "array" - "base" - "binary" - "bytestring" - "containers" - "deepseq" - "directory" - "filepath" - "ghc-boot" - "ghc-boot-th" - "ghc-compact" - "ghc-heap" - "ghc-prim" - "ghci" - "integer-gmp" - "mtl" - "parsec" - "pretty" - "process" - "rts" - "template-haskell" - "text" - "time" - "transformers" - ] ++ pkgs.lib.optionals (!pkgs.stdenv.targetPlatform.isGhcjs || builtins.compareVersions ghc.version "9.0" > 0) [ - # GHCJS 8.10 does not have these - "Cabal-syntax" - "exceptions" - "file-io" - "ghc" - "ghc-bignum" - "ghc-experimental" - "ghc-internal" - "ghc-platform" - "ghc-toolchain" - "haskeline" - "hpc" - "libiserv" - "os-string" - "semaphore-compat" - "stm" - "xhtml" - ] ++ pkgs.lib.optionals (!pkgs.stdenv.targetPlatform.isGhcjs) [ - "terminfo" - ] ++ (if pkgs.stdenv.targetPlatform.isWindows - then [ "Win32" ] - else [ "unix" ] - ); - - dummy-ghc-pkg-dump = evalPackages.runCommand "dummy-ghc-pkg-dump" { - nativeBuildInputs = [ - evalPackages.haskell-nix.nix-tools-unchecked.exes.cabal2json - evalPackages.jq - ]; - } (let varname = x: builtins.replaceStrings ["-"] ["_"] x; in '' - PACKAGE_VERSION=${ghc.version} - ProjectVersion=${ghc.version} - - # The following logic is from GHC m4/setup_project_version.m4 - - # Split PACKAGE_VERSION into (possibly empty) parts - VERSION_MAJOR=`echo $PACKAGE_VERSION | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1'/` - VERSION_TMP=`echo $PACKAGE_VERSION | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3'/` - VERSION_MINOR=`echo $VERSION_TMP | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1'/` - ProjectPatchLevel=`echo $VERSION_TMP | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3'/` - - # Calculate project version as an integer, using 2 digits for minor version - case $VERSION_MINOR in - ?) ProjectVersionInt=''${VERSION_MAJOR}0''${VERSION_MINOR} ;; - ??) ProjectVersionInt=''${VERSION_MAJOR}''${VERSION_MINOR} ;; - *) echo bad minor version in $PACKAGE_VERSION; exit 1 ;; - esac - # AC_SUBST([ProjectVersionInt]) - - # The project patchlevel is zero unless stated otherwise - test -z "$ProjectPatchLevel" && ProjectPatchLevel=0 - - # Save split version of ProjectPatchLevel - ProjectPatchLevel1=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1/'` - ProjectPatchLevel2=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3/'` - - # The project patchlevel1/2 is zero unless stated otherwise - test -z "$ProjectPatchLevel1" && ProjectPatchLevel1=0 - test -z "$ProjectPatchLevel2" && ProjectPatchLevel2=0 - - # AC_SUBST([ProjectPatchLevel1]) - # AC_SUBST([ProjectPatchLevel2]) - - # Remove dots from the patch level; this allows us to have versions like 6.4.1.20050508 - ProjectPatchLevel=`echo $ProjectPatchLevel | sed 's/\.//'` - - # AC_SUBST([ProjectPatchLevel]) - - # The version of the GHC package changes every day, since the - # patchlevel is the current date. We don't want to force - # recompilation of the entire compiler when this happens, so for - # GHC HEAD we omit the patchlevel from the package version number. - # - # The ProjectPatchLevel1 > 20000000 iff GHC HEAD. If it's for a stable - # release like 7.10.1 or for a release candidate such as 7.10.1.20141224 - # then we don't omit the patchlevel components. - - ProjectVersionMunged="$ProjectVersion" - if test "$ProjectPatchLevel1" -gt 20000000; then - ProjectVersionMunged="''${VERSION_MAJOR}.''${VERSION_MINOR}" - fi - # AC_SUBST([ProjectVersionMunged]) - - # The version used for libraries tightly coupled with GHC (e.g. - # ghc-internal) which need a major version bump for every minor/patchlevel - # GHC version. - # Example: for GHC=9.10.1, ProjectVersionForLib=9.1001 - # - # Just like with project version munged, we don't want to use the - # patchlevel version which changes every day, so if using GHC HEAD, the - # patchlevel = 00. - case $VERSION_MINOR in - ?) ProjectVersionForLibUpperHalf=''${VERSION_MAJOR}.0''${VERSION_MINOR} ;; - ??) ProjectVersionForLibUpperHalf=''${VERSION_MAJOR}.''${VERSION_MINOR} ;; - *) echo bad minor version in $PACKAGE_VERSION; exit 1 ;; - esac - # GHC HEAD uses patch level version > 20000000 - case $ProjectPatchLevel1 in - ?) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}0''${ProjectPatchLevel1} ;; - ??) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}''${ProjectPatchLevel1} ;; - *) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}00 - esac - - PKGS="" - ${pkgs.lib.concatStrings - (builtins.map (name: '' - cabal_file="" - if [ -f ${ghcSrc}/libraries/${name}/${name}.cabal ]; then - cabal_file=${ghcSrc}/libraries/${name}/${name}.cabal - elif [ -f ${ghcSrc}/libraries/Cabal/${name}/${name}.cabal ]; then - cabal_file=${ghcSrc}/libraries/Cabal/${name}/${name}.cabal - elif [ -f ${ghcSrc}/libraries/${name}/${name}/${name}.cabal ]; then - cabal_file=${ghcSrc}/libraries/${name}/${name}/${name}.cabal - elif [ -f ${ghcSrc}/compiler/${name}.cabal ]; then - cabal_file=${ghcSrc}/compiler/${name}.cabal - elif [ -f ${ghcSrc}/compiler/${name}.cabal.in ]; then - cabal_file=${ghcSrc}/compiler/${name}.cabal.in - elif [ -f ${ghcSrc}/libraries/${name}/${name}.cabal.in ]; then - cabal_file=${ghcSrc}/libraries/${name}/${name}.cabal.in - fi - if [[ "$cabal_file" != "" ]]; then - fixed_cabal_file=$(mktemp) - cat $cabal_file | sed -e "s/@ProjectVersionMunged@/$ProjectVersionMunged/g" -e "s/@ProjectVersionForLib@/$ProjectVersionForLib/g" -e 's/default: *@[A-Za-z0-9]*@/default: False/g' -e 's/@Suffix@//g' > $fixed_cabal_file - json_cabal_file=$(mktemp) - cabal2json $fixed_cabal_file > $json_cabal_file - - exposed_modules="$(jq -r '.library."exposed-modules"[]|select(type=="array")[]' $json_cabal_file)" - reexported_modules="$(jq -r '.library."reexported-modules"//[]|.[]|select(type=="array")[]' $json_cabal_file)" - - # FIXME This is a bandaid. Rather than doing this, conditionals should be interpreted. - ${pkgs.lib.optionalString pkgs.stdenv.targetPlatform.isGhcjs '' - exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.arch == "javascript")|.then[]' $json_cabal_file)" - ''} - ${pkgs.lib.optionalString pkgs.stdenv.targetPlatform.isWindows '' - exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.os == "windows")|.then[]' $json_cabal_file)" - ''} - ${pkgs.lib.optionalString (!pkgs.stdenv.targetPlatform.isWindows) '' - exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.not.os == "windows")|.then[]' $json_cabal_file)" - ''} - - EXPOSED_MODULES_${varname name}="$(tr '\n' ' ' <<< "$exposed_modules $reexported_modules")" - DEPS_${varname name}="$(jq -r '.library."build-depends"[]|select(type=="array")[],select(type=="object" and .if.not.flag != "vendor-filepath").then[]' $json_cabal_file | sed 's/^\([A-Za-z0-9-]*\).*$/\1/g' | sort -u | tr '\n' ' ')" - VER_${varname name}="$(jq -r '.version' $json_cabal_file)" - PKGS+=" ${name}" - LAST_PKG="${name}" - fi - '') ghc-pkgs) - } - ${ # There is no .cabal file for system-cxx-std-lib - pkgs.lib.optionalString (builtins.compareVersions ghc.version "9.2" >= 0) ( - let name="system-cxx-std-lib"; in '' - EXPOSED_MODULES_${varname name}="" - DEPS_${varname name}="" - VER_${varname name}="1.0" - PKGS+=" ${name}" - LAST_PKG="${name}" - '') - # ghcjs packages (before the ghc JS backend). TODO remove this when GHC 8.10 support is dropped - + pkgs.lib.optionalString (pkgs.stdenv.targetPlatform.isGhcjs && builtins.compareVersions ghc.version "9" < 0) '' - EXPOSED_MODULES_${varname "ghcjs-prim"}="GHCJS.Prim GHCJS.Prim.Internal GHCJS.Prim.Internal.Build" - DEPS_${varname "ghcjs-prim"}="base ghc-prim" - VER_${varname "ghcjs-prim"}="0.1.1.0" - EXPOSED_MODULES_${varname "ghcjs-th"}="GHCJS.Prim.TH.Eval GHCJS.Prim.TH.Types" - DEPS_${varname "ghcjs-th"}="base binary bytestring containers ghc-prim ghci template-haskell" - VER_${varname "ghcjs-th"}="0.1.0.0" - PKGS+=" ghcjs-prim ghcjs-th" - LAST_PKG="ghcjs-th" - '' - } - for pkg in $PKGS; do - varname="$(echo $pkg | tr "-" "_")" - ver="VER_$varname" - exposed_mods="EXPOSED_MODULES_$varname" - deps="DEPS_$varname" - echo "name: $pkg" >> $out - echo "version: ''${!ver}" >> $out - echo "exposed-modules: ''${!exposed_mods}" >> $out - echo "depends:" >> $out - for dep in ''${!deps}; do - ver_dep="VER_$(echo $dep | tr "-" "_")" - if [[ "''${!ver_dep}" != "" ]]; then - echo " $dep-''${!ver_dep}" >> $out - fi - done - if [[ "$pkg" != "$LAST_PKG" ]]; then - echo '---' >> $out - fi - done - ''); + dummy-ghc-pkg-dump = import ./dummy-ghc-pkg-dump.nix { + inherit pkgs evalPackages; + ghc-src = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; + ghc-version = ghc.version; + }; + # Dummy `ghc-pkg` that uses the captured output dummy-ghc-pkg = evalPackages.writeTextFile { name = "dummy-pkg-" + ghc.name; diff --git a/lib/dummy-ghc-pkg-dump.nix b/lib/dummy-ghc-pkg-dump.nix new file mode 100644 index 0000000000..407f56646f --- /dev/null +++ b/lib/dummy-ghc-pkg-dump.nix @@ -0,0 +1,239 @@ +{ pkgs, evalPackages, ghc-version, ghc-src }: + +let + inherit (pkgs) lib stdenv; + + varname = builtins.replaceStrings [ "-" ] [ "_" ]; + + ghc-pkgs = [ + "Cabal" + "array" + "base" + "binary" + "bytestring" + "containers" + "deepseq" + "directory" + "filepath" + "ghc-boot" + "ghc-boot-th" + "ghc-compact" + "ghc-heap" + "ghc-prim" + "ghci" + "integer-gmp" + "mtl" + "parsec" + "pretty" + "process" + "rts" + "template-haskell" + "text" + "time" + "transformers" + ] ++ lib.optionals (!stdenv.targetPlatform.isGhcjs + || builtins.compareVersions ghc-version "9.0" > 0) [ + # GHCJS 8.10 does not have these + "Cabal-syntax" + "exceptions" + "file-io" + "ghc" + "ghc-bignum" + "ghc-experimental" + "ghc-internal" + "ghc-platform" + "ghc-toolchain" + "haskeline" + "hpc" + "libiserv" + "os-string" + "semaphore-compat" + "stm" + "xhtml" + ] ++ lib.optionals (!stdenv.targetPlatform.isGhcjs) [ "terminfo" ] + ++ (if stdenv.targetPlatform.isWindows then + [ "Win32" ] + else + [ "unix" ]); + +in evalPackages.runCommand "dummy-ghc-pkg-dump" { + nativeBuildInputs = [ + evalPackages.haskell-nix.nix-tools-unchecked.exes.cabal2json + evalPackages.jq + ]; +} '' + PACKAGE_VERSION=${ghc-version} + ProjectVersion=${ghc-version} + + # The following logic is from GHC m4/setup_project_version.m4 + + # Split PACKAGE_VERSION into (possibly empty) parts + VERSION_MAJOR=`echo $PACKAGE_VERSION | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1'/` + VERSION_TMP=`echo $PACKAGE_VERSION | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3'/` + VERSION_MINOR=`echo $VERSION_TMP | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1'/` + ProjectPatchLevel=`echo $VERSION_TMP | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3'/` + + # Calculate project version as an integer, using 2 digits for minor version + case $VERSION_MINOR in + ?) ProjectVersionInt=''${VERSION_MAJOR}0''${VERSION_MINOR} ;; + ??) ProjectVersionInt=''${VERSION_MAJOR}''${VERSION_MINOR} ;; + *) echo bad minor version in $PACKAGE_VERSION; exit 1 ;; + esac + # AC_SUBST([ProjectVersionInt]) + + # The project patchlevel is zero unless stated otherwise + test -z "$ProjectPatchLevel" && ProjectPatchLevel=0 + + # Save split version of ProjectPatchLevel + ProjectPatchLevel1=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1/'` + ProjectPatchLevel2=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3/'` + + # The project patchlevel1/2 is zero unless stated otherwise + test -z "$ProjectPatchLevel1" && ProjectPatchLevel1=0 + test -z "$ProjectPatchLevel2" && ProjectPatchLevel2=0 + + # AC_SUBST([ProjectPatchLevel1]) + # AC_SUBST([ProjectPatchLevel2]) + + # Remove dots from the patch level; this allows us to have versions like 6.4.1.20050508 + ProjectPatchLevel=`echo $ProjectPatchLevel | sed 's/\.//'` + + # AC_SUBST([ProjectPatchLevel]) + + # The version of the GHC package changes every day, since the + # patchlevel is the current date. We don't want to force + # recompilation of the entire compiler when this happens, so for + # GHC HEAD we omit the patchlevel from the package version number. + # + # The ProjectPatchLevel1 > 20000000 iff GHC HEAD. If it's for a stable + # release like 7.10.1 or for a release candidate such as 7.10.1.20141224 + # then we don't omit the patchlevel components. + + ProjectVersionMunged="$ProjectVersion" + if test "$ProjectPatchLevel1" -gt 20000000; then + ProjectVersionMunged="''${VERSION_MAJOR}.''${VERSION_MINOR}" + fi + # AC_SUBST([ProjectVersionMunged]) + + # The version used for libraries tightly coupled with GHC (e.g. + # ghc-internal) which need a major version bump for every minor/patchlevel + # GHC version. + # Example: for GHC=9.10.1, ProjectVersionForLib=9.1001 + # + # Just like with project version munged, we don't want to use the + # patchlevel version which changes every day, so if using GHC HEAD, the + # patchlevel = 00. + case $VERSION_MINOR in + ?) ProjectVersionForLibUpperHalf=''${VERSION_MAJOR}.0''${VERSION_MINOR} ;; + ??) ProjectVersionForLibUpperHalf=''${VERSION_MAJOR}.''${VERSION_MINOR} ;; + *) echo bad minor version in $PACKAGE_VERSION; exit 1 ;; + esac + # GHC HEAD uses patch level version > 20000000 + case $ProjectPatchLevel1 in + ?) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}0''${ProjectPatchLevel1} ;; + ??) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}''${ProjectPatchLevel1} ;; + *) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}00 + esac + + PKGS="" + ${lib.concatStrings (builtins.map (name: '' + cabal_file="" + if [ -f ${ghc-src}/libraries/${name}/${name}.cabal ]; then + cabal_file=${ghc-src}/libraries/${name}/${name}.cabal + elif [ -f ${ghc-src}/libraries/Cabal/${name}/${name}.cabal ]; then + cabal_file=${ghc-src}/libraries/Cabal/${name}/${name}.cabal + elif [ -f ${ghc-src}/libraries/${name}/${name}/${name}.cabal ]; then + cabal_file=${ghc-src}/libraries/${name}/${name}/${name}.cabal + elif [ -f ${ghc-src}/compiler/${name}.cabal ]; then + cabal_file=${ghc-src}/compiler/${name}.cabal + elif [ -f ${ghc-src}/compiler/${name}.cabal.in ]; then + cabal_file=${ghc-src}/compiler/${name}.cabal.in + elif [ -f ${ghc-src}/libraries/${name}/${name}.cabal.in ]; then + cabal_file=${ghc-src}/libraries/${name}/${name}.cabal.in + fi + if [[ "$cabal_file" != "" ]]; then + fixed_cabal_file=$(mktemp) + cat $cabal_file | sed -e "s/@ProjectVersionMunged@/$ProjectVersionMunged/g" -e "s/@ProjectVersionForLib@/$ProjectVersionForLib/g" -e 's/default: *@[A-Za-z0-9]*@/default: False/g' -e 's/@Suffix@//g' > $fixed_cabal_file + json_cabal_file=$(mktemp) + cabal2json $fixed_cabal_file > $json_cabal_file + + exposed_modules="$(jq -r '.library."exposed-modules"[]|select(type=="array")[]' $json_cabal_file)" + reexported_modules="$(jq -r '.library."reexported-modules"//[]|.[]|select(type=="array")[]' $json_cabal_file)" + + # FIXME This is a bandaid. Rather than doing this, conditionals should be interpreted. + ${ + lib.optionalString stdenv.targetPlatform.isGhcjs '' + exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.arch == "javascript")|.then[]' $json_cabal_file)" + '' + } + ${ + lib.optionalString stdenv.targetPlatform.isWindows '' + exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.os == "windows")|.then[]' $json_cabal_file)" + '' + } + ${ + lib.optionalString (!stdenv.targetPlatform.isWindows) '' + exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.not.os == "windows")|.then[]' $json_cabal_file)" + '' + } + + EXPOSED_MODULES_${ + varname name + }="$(tr '\n' ' ' <<< "$exposed_modules $reexported_modules")" + DEPS_${ + varname name + }="$(jq -r '.library."build-depends"[]|select(type=="array")[],select(type=="object" and .if.not.flag != "vendor-filepath").then[]' $json_cabal_file | sed 's/^\([A-Za-z0-9-]*\).*$/\1/g' | sort -u | tr '\n' ' ')" + VER_${varname name}="$(jq -r '.version' $json_cabal_file)" + PKGS+=" ${name}" + LAST_PKG="${name}" + fi + '') ghc-pkgs)} + + ${ # There is no .cabal file for system-cxx-std-lib + lib.optionalString (builtins.compareVersions ghc-version "9.2" >= 0) + (let name = "system-cxx-std-lib"; + in '' + EXPOSED_MODULES_${varname name}="" + DEPS_${varname name}="" + VER_${varname name}="1.0" + PKGS+=" ${name}" + LAST_PKG="${name}" + '') + # ghcjs packages (before the ghc JS backend). TODO remove this when GHC 8.10 support is dropped + + lib.optionalString (stdenv.targetPlatform.isGhcjs + && builtins.compareVersions ghc-version "9" < 0) '' + EXPOSED_MODULES_${ + varname "ghcjs-prim" + }="GHCJS.Prim GHCJS.Prim.Internal GHCJS.Prim.Internal.Build" + DEPS_${varname "ghcjs-prim"}="base ghc-prim" + VER_${varname "ghcjs-prim"}="0.1.1.0" + EXPOSED_MODULES_${ + varname "ghcjs-th" + }="GHCJS.Prim.TH.Eval GHCJS.Prim.TH.Types" + DEPS_${ + varname "ghcjs-th" + }="base binary bytestring containers ghc-prim ghci template-haskell" + VER_${varname "ghcjs-th"}="0.1.0.0" + PKGS+=" ghcjs-prim ghcjs-th" + LAST_PKG="ghcjs-th" + ''} + for pkg in $PKGS; do + varname="$(echo $pkg | tr "-" "_")" + ver="VER_$varname" + exposed_mods="EXPOSED_MODULES_$varname" + deps="DEPS_$varname" + echo "name: $pkg" >> $out + echo "version: ''${!ver}" >> $out + echo "exposed-modules: ''${!exposed_mods}" >> $out + echo "depends:" >> $out + for dep in ''${!deps}; do + ver_dep="VER_$(echo $dep | tr "-" "_")" + if [[ "''${!ver_dep}" != "" ]]; then + echo " $dep-''${!ver_dep}" >> $out + fi + done + if [[ "$pkg" != "$LAST_PKG" ]]; then + echo '---' >> $out + fi + done +'' diff --git a/overlays/haskell.nix b/overlays/haskell.nix index b6b58a4a94..87ae146142 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -594,13 +594,17 @@ final: prev: { }; + dummy-ghc-pkg-dump = import ../lib/dummy-ghc-pkg-dump.nix { + pkgs = final.buildPackages.pkgs; + }; + # Takes a haskell src directory runs cabal new-configure and plan-to-nix. # Resulting nix files are added to nix-plan subdirectory. callCabalProjectToNix = import ../lib/call-cabal-project-to-nix.nix { index-state-hashes = import indexStateHashesPath; inherit (final.buildPackages.haskell-nix) haskellLib; pkgs = final.buildPackages.pkgs; - inherit (final.buildPackages.pkgs) runCommand cacert; + inherit (final.buildPackages.pkgs) cacert; }; # Loads a plan and filters the package directories using cleanSourceWith From 62e6e5c8e3201a46dd8c1110722f1e0a3d0e8f5d Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Thu, 12 Dec 2024 14:28:32 +0800 Subject: [PATCH 07/16] WIP --- lib/call-cabal-project-to-nix.nix | 2 +- lib/dummy-ghc-pkg-dump/configure.ac | 13 +++++++++++++ .../default.nix} | 17 +++++++++++++---- overlays/haskell.nix | 2 +- 4 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 lib/dummy-ghc-pkg-dump/configure.ac rename lib/{dummy-ghc-pkg-dump.nix => dummy-ghc-pkg-dump/default.nix} (96%) diff --git a/lib/call-cabal-project-to-nix.nix b/lib/call-cabal-project-to-nix.nix index ec7929d374..a21ffc12bf 100644 --- a/lib/call-cabal-project-to-nix.nix +++ b/lib/call-cabal-project-to-nix.nix @@ -366,7 +366,7 @@ let ''; }; - dummy-ghc-pkg-dump = import ./dummy-ghc-pkg-dump.nix { + dummy-ghc-pkg-dump = import ./dummy-ghc-pkg-dump { inherit pkgs evalPackages; ghc-src = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; ghc-version = ghc.version; diff --git a/lib/dummy-ghc-pkg-dump/configure.ac b/lib/dummy-ghc-pkg-dump/configure.ac new file mode 100644 index 0000000000..49d1e413a8 --- /dev/null +++ b/lib/dummy-ghc-pkg-dump/configure.ac @@ -0,0 +1,13 @@ +AC_INIT([The Glorious Glasgow Haskell Compilation System], [0.00], [glasgow-haskell-bugs@haskell.org], [ghc-AC_PACKAGE_VERSION]) + +AC_CONFIG_MACRO_DIRS([m4]) + +# Set this to YES for a released version, otherwise NO +: ${RELEASE=NO} + +dnl ** Find unixy sort and find commands, +dnl ** which are needed by FP_SETUP_PROJECT_VERSION +FP_PROG_FIND +FP_PROG_SORT + +FP_SETUP_PROJECT_VERSION diff --git a/lib/dummy-ghc-pkg-dump.nix b/lib/dummy-ghc-pkg-dump/default.nix similarity index 96% rename from lib/dummy-ghc-pkg-dump.nix rename to lib/dummy-ghc-pkg-dump/default.nix index 407f56646f..cc71359544 100644 --- a/lib/dummy-ghc-pkg-dump.nix +++ b/lib/dummy-ghc-pkg-dump/default.nix @@ -51,16 +51,25 @@ let "stm" "xhtml" ] ++ lib.optionals (!stdenv.targetPlatform.isGhcjs) [ "terminfo" ] - ++ (if stdenv.targetPlatform.isWindows then - [ "Win32" ] - else - [ "unix" ]); + ++ (if stdenv.targetPlatform.isWindows then [ "Win32" ] else [ "unix" ]); + + configure = evalPackages.runCommand "autoreconf" { + nativeBuildInputs = with evalPackages; [ autotools coreutils findutils ]; + } '' + mkdir -p $out + cd $out + cp ./configure.ac . + ln -s ${ghc-src}/m4 . + autoreconf -i + rm m4 + ''; in evalPackages.runCommand "dummy-ghc-pkg-dump" { nativeBuildInputs = [ evalPackages.haskell-nix.nix-tools-unchecked.exes.cabal2json evalPackages.jq ]; + passthru = { inherit configure; }; } '' PACKAGE_VERSION=${ghc-version} ProjectVersion=${ghc-version} diff --git a/overlays/haskell.nix b/overlays/haskell.nix index 87ae146142..fc9d9ec54e 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -594,7 +594,7 @@ final: prev: { }; - dummy-ghc-pkg-dump = import ../lib/dummy-ghc-pkg-dump.nix { + dummy-ghc-pkg-dump = import ../lib/dummy-ghc-pkg-dump { pkgs = final.buildPackages.pkgs; }; From 11718c07d0b8e52cdae7e0a8c7883307b4f4d3c7 Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Thu, 12 Dec 2024 16:16:41 +0800 Subject: [PATCH 08/16] WIP --- lib/call-cabal-project-to-nix.nix | 535 ++++++++++++++++------------ lib/dummy-ghc-pkg-dump/configure.ac | 13 +- lib/dummy-ghc-pkg-dump/default.nix | 100 ++++-- overlays/haskell.nix | 13 +- 4 files changed, 397 insertions(+), 264 deletions(-) diff --git a/lib/call-cabal-project-to-nix.nix b/lib/call-cabal-project-to-nix.nix index a21ffc12bf..1f15708c09 100644 --- a/lib/call-cabal-project-to-nix.nix +++ b/lib/call-cabal-project-to-nix.nix @@ -1,70 +1,69 @@ { pkgs, cacert, index-state-hashes, haskellLib }: -{ name ? src.name or null # optional name for better error messages -, src -, materialized-dir ? ../materialized -, compiler-nix-name # The name of the ghc compiler to use eg. "ghc884" -, index-state ? null # Hackage index-state, eg. "2019-10-10T00:00:00Z" -, index-sha256 ? null # The hash of the truncated hackage index-state -, plan-sha256 ? null # The hash of the plan-to-nix output (makes the plan-to-nix step a fixed output derivation) -, materialized ? null # Location of a materialized copy of the nix files -, checkMaterialization ? null # If true the nix files will be generated used to check plan-sha256 and material -, cabalProjectFileName ? "cabal.project" -, cabalProject ? null -, cabalProjectLocal ? null -, cabalProjectFreeze ? null -, caller ? "callCabalProjectToNix" # Name of the calling function for better warning messages -, compilerSelection ? p: p.haskell-nix.compiler -, ghc ? null # Deprecated in favour of `compiler-nix-name` -, ghcOverride ? null # Used when we need to set ghc explicitly during bootstrapping +{ name ? src.name or null # optional name for better error messages +, src, materialized-dir ? ../materialized +, compiler-nix-name # The name of the ghc compiler to use eg. "ghc884" +, index-state ? null # Hackage index-state, eg. "2019-10-10T00:00:00Z" +, index-sha256 ? null # The hash of the truncated hackage index-state +, plan-sha256 ? + null # The hash of the plan-to-nix output (makes the plan-to-nix step a fixed output derivation) +, materialized ? null # Location of a materialized copy of the nix files +, checkMaterialization ? + null # If true the nix files will be generated used to check plan-sha256 and material +, cabalProjectFileName ? "cabal.project", cabalProject ? null +, cabalProjectLocal ? null, cabalProjectFreeze ? null, caller ? + "callCabalProjectToNix" # Name of the calling function for better warning messages +, compilerSelection ? p: p.haskell-nix.compiler +, ghc ? null # Deprecated in favour of `compiler-nix-name` +, ghcOverride ? + null # Used when we need to set ghc explicitly during bootstrapping , configureArgs ? "" # Extra arguments to pass to `cabal v2-configure`. - # `--enable-tests --enable-benchmarks` are included by default. - # If the tests and benchmarks are not needed and they - # cause the wrong plan to be chosen, then we can use - # `configureArgs = "--disable-tests --disable-benchmarks";` -, sha256map ? null - # An alternative to adding `--sha256` comments into the - # cabal.project file: - # sha256map = - # { # For a `source-repository-package` use the `location` and `tag` as the key - # "https://github.com/jgm/pandoc-citeproc"."0.17" - # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; - # # For a `repository` use the `url` as the key - # "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32" - # = "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg="; - # }; -, inputMap ? {} - # An alternative to providing a `sha256` handy for flakes - # cabal.project file: - # inputs.pandoc-citeproc.url = "github:jgm/pandoc-citeproc/0.17"; - # inputs.pandoc-citeproc.flake = false; - # outputs = inputs: - # ... - # inputMap."https://github.com/jgm/pandoc-citeproc" = inputs.inputs.pandoc-citeproc; -, extra-hackage-tarballs ? {} -, source-repo-override ? {} # Cabal seems to behave incoherently when - # two source-repository-package entries - # provide the same packages, making it - # impossible to override cabal.project - # with e.g. a cabal.project.local. In CI, - # we want to be able to test against the - # latest versions of various dependencies. - # - # This argument is a map from url to - # a function taking the existing repoData - # and returning the new repoData in its - # place. E.g. - # - # { "https://github.com/input-output-hk/plutus-apps" = orig: orig // { subdirs = (orig.subdirs or [ "." ]) ++ [ "foo" ]; }; } - # - # would result in the "foo" subdirectory of - # any plutus-apps input being used for a - # package. + # `--enable-tests --enable-benchmarks` are included by default. + # If the tests and benchmarks are not needed and they + # cause the wrong plan to be chosen, then we can use + # `configureArgs = "--disable-tests --disable-benchmarks";` +, sha256map ? null + # An alternative to adding `--sha256` comments into the + # cabal.project file: + # sha256map = + # { # For a `source-repository-package` use the `location` and `tag` as the key + # "https://github.com/jgm/pandoc-citeproc"."0.17" + # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; + # # For a `repository` use the `url` as the key + # "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32" + # = "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg="; + # }; +, inputMap ? { } + # An alternative to providing a `sha256` handy for flakes + # cabal.project file: + # inputs.pandoc-citeproc.url = "github:jgm/pandoc-citeproc/0.17"; + # inputs.pandoc-citeproc.flake = false; + # outputs = inputs: + # ... + # inputMap."https://github.com/jgm/pandoc-citeproc" = inputs.inputs.pandoc-citeproc; +, extra-hackage-tarballs ? { }, source-repo-override ? + { } # Cabal seems to behave incoherently when + # two source-repository-package entries + # provide the same packages, making it + # impossible to override cabal.project + # with e.g. a cabal.project.local. In CI, + # we want to be able to test against the + # latest versions of various dependencies. + # + # This argument is a map from url to + # a function taking the existing repoData + # and returning the new repoData in its + # place. E.g. + # + # { "https://github.com/input-output-hk/plutus-apps" = orig: orig // { subdirs = (orig.subdirs or [ "." ]) ++ [ "foo" ]; }; } + # + # would result in the "foo" subdirectory of + # any plutus-apps input being used for a + # package. , evalPackages -, supportHpack ? false # Run hpack on package.yaml files with no .cabal file +, supportHpack ? false # Run hpack on package.yaml files with no .cabal file , ignorePackageYaml ? false # Ignore package.yaml files even if they exist -, ... -}@args: +, ... }@args: let inherit (evalPackages.haskell-nix) materialize dotCabal; @@ -72,47 +71,56 @@ let # lazy enough to avoid infinite recursion issues. # Using null as the default also improves performance as they are not forced by the # nix module system for `nix-tools-unchecked`. - nix-tools = if args.nix-tools or null != null - then args.nix-tools - else evalPackages.haskell-nix.nix-tools-unchecked; + nix-tools = if args.nix-tools or null != null then + args.nix-tools + else + evalPackages.haskell-nix.nix-tools-unchecked; forName = pkgs.lib.optionalString (name != null) (" for " + name); nameAndSuffix = suffix: if name == null then suffix else name + "-" + suffix; - ghc' = - if ghcOverride != null - then ghcOverride - else - if ghc != null - then __trace ("WARNING: A `ghc` argument was passed" + forName - + " this has been deprecated in favour of `compiler-nix-name`. " - + "Using `ghc` will break cross compilation setups, as haskell.nix cannot " - + "pick the correct `ghc` package from the respective buildPackages. " - + "For example, use `compiler-nix-name = \"ghc865\";` for GHC 8.6.5.") ghc - else - # Do note that `pkgs = final.buildPackages` in the `overlays/haskell.nix` - # call to this file. And thus `pkgs` here is the proper `buildPackages` - # set and we do not need, nor should pick the compiler from another level - # of `buildPackages`, lest we want to get confusing errors about the Win32 - # package. - # - # > The option `packages.Win32.package.identifier.name' is used but not defined. - # - (compilerSelection pkgs)."${compiler-nix-name}"; + ghc' = if ghcOverride != null then + ghcOverride + else if ghc != null then + __trace ("WARNING: A `ghc` argument was passed" + forName + + " this has been deprecated in favour of `compiler-nix-name`. " + + "Using `ghc` will break cross compilation setups, as haskell.nix cannot " + + "pick the correct `ghc` package from the respective buildPackages. " + + ''For example, use `compiler-nix-name = "ghc865";` for GHC 8.6.5.'') ghc + else + # Do note that `pkgs = final.buildPackages` in the `overlays/haskell.nix` + # call to this file. And thus `pkgs` here is the proper `buildPackages` + # set and we do not need, nor should pick the compiler from another level + # of `buildPackages`, lest we want to get confusing errors about the Win32 + # package. + # + # > The option `packages.Win32.package.identifier.name' is used but not defined. + # + (compilerSelection pkgs)."${compiler-nix-name}"; in let - ghc = if ghc' ? latestVersion - then __trace "WARNING: ${ghc'.version} is out of date, consider using upgrading to ${ghc'.latestVersion}." ghc' - else ghc'; + ghc = if ghc' ? latestVersion then + __trace + "WARNING: ${ghc'.version} is out of date, consider using upgrading to ${ghc'.latestVersion}." + ghc' + else + ghc'; subDir' = src.origSubDir or ""; subDir = pkgs.lib.strings.removePrefix "/" subDir'; cleanedSource = haskellLib.cleanSourceWith { - name = if name != null then "${name}-root-cabal-files" else "source-root-cabal-files"; + name = if name != null then + "${name}-root-cabal-files" + else + "source-root-cabal-files"; src = src.origSrc or src; - filter = path: type: (!(src ? filter) || src.filter path type) && ( - type == "directory" || - pkgs.lib.any (i: (pkgs.lib.hasSuffix i path)) [ ".cabal" "package.yaml" ]); }; + filter = path: type: + (!(src ? filter) || src.filter path type) && (type == "directory" + || pkgs.lib.any (i: (pkgs.lib.hasSuffix i path)) [ + ".cabal" + "package.yaml" + ]); + }; # When there is no `cabal.project` file `cabal-install` behaves as if there was # one containing `packages: ./*.cabal`. Even if there is a `cabal.project.local` @@ -129,53 +137,52 @@ in let # https://github.com/input-output-hk/haskell.nix/pull/1639 # rawCabalProject = '' - ${ - if cabalProject == null - then '' - -- Included to match the implicit project used by `cabal-install` - packages: ./*.cabal - '' - else cabalProject - } - ${ - pkgs.lib.optionalString (cabalProjectLocal != null) '' - -- Added from `cabalProjectLocal` argument to the `cabalProject` function - ${cabalProjectLocal} - '' - } + ${if cabalProject == null then '' + -- Included to match the implicit project used by `cabal-install` + packages: ./*.cabal + '' else + cabalProject} + ${pkgs.lib.optionalString (cabalProjectLocal != null) '' + -- Added from `cabalProjectLocal` argument to the `cabalProject` function + ${cabalProjectLocal} + ''} ''; - index-state-max = - if index-state != null - then index-state - else pkgs.lib.last (builtins.attrNames index-state-hashes); + index-state-max = if index-state != null then + index-state + else + pkgs.lib.last (builtins.attrNames index-state-hashes); # If a hash was not specified find a suitable cached index state to # use that will contain all the packages we need. By using the # first one after the desired index-state we can avoid recalculating # when new index-state-hashes are added. # See https://github.com/input-output-hk/haskell.nix/issues/672 - cached-index-state = if index-sha256 != null - then index-state-max + cached-index-state = if index-sha256 != null then + index-state-max + else + let + suitable-index-states = builtins.filter + (s: s >= index-state-max) # This compare is why we need zulu time + (builtins.attrNames index-state-hashes); + in if builtins.length suitable-index-states == 0 then + index-state-max else - let - suitable-index-states = - builtins.filter - (s: s >= index-state-max) # This compare is why we need zulu time - (builtins.attrNames index-state-hashes); - in - if builtins.length suitable-index-states == 0 - then index-state-max - else pkgs.lib.head suitable-index-states; + pkgs.lib.head suitable-index-states; # Lookup hash for the index state we found - index-sha256-found = if index-sha256 != null - then index-sha256 - else index-state-hashes.${cached-index-state} or null; - -in - assert (if index-sha256-found == null - then throw "Unknown index-state ${index-state-max}, the latest index-state I know about is ${pkgs.lib.last (builtins.attrNames index-state-hashes)}. You may need to update to a newer hackage.nix." else true); + index-sha256-found = if index-sha256 != null then + index-sha256 + else + index-state-hashes.${cached-index-state} or null; + +in assert (if index-sha256-found == null then + throw + "Unknown index-state ${index-state-max}, the latest index-state I know about is ${ + pkgs.lib.last (builtins.attrNames index-state-hashes) + }. You may need to update to a newer hackage.nix." +else + true); let # Deal with source-repository-packages in a way that will work in @@ -192,30 +199,55 @@ let fetchPackageRepo = fetchgit: repoData: let fetched = - if inputMap ? "${repoData.url}/${repoData.rev or repoData.ref}" - then inputMap."${repoData.url}/${repoData.rev or repoData.ref}" - else if inputMap ? ${repoData.url} - then - (if inputMap.${repoData.url}.rev != (repoData.rev or repoData.ref) - then throw "${inputMap.${repoData.url}.rev} may not match ${repoData.rev or repoData.ref} for ${repoData.url} use \"${repoData.url}/${repoData.rev or repoData.ref}\" as the inputMap key if ${repoData.rev or repoData.ref} is a branch or tag that points to ${inputMap.${repoData.url}.rev}." - else inputMap.${repoData.url}) - else if repoData.sha256 != null - then fetchgit { inherit (repoData) url sha256; rev = repoData.rev or repoData.ref; } + if inputMap ? "${repoData.url}/${repoData.rev or repoData.ref}" then + inputMap."${repoData.url}/${repoData.rev or repoData.ref}" + else if inputMap ? ${repoData.url} then + (if inputMap.${repoData.url}.rev + != (repoData.rev or repoData.ref) then + throw '' + ${inputMap.${repoData.url}.rev} may not match ${ + repoData.rev or repoData.ref + } for ${repoData.url} use "${repoData.url}/${ + repoData.rev or repoData.ref + }" as the inputMap key if ${ + repoData.rev or repoData.ref + } is a branch or tag that points to ${ + inputMap.${repoData.url}.rev + }.'' + else + inputMap.${repoData.url}) + else if repoData.sha256 != null then + fetchgit { + inherit (repoData) url sha256; + rev = repoData.rev or repoData.ref; + } else - let drv = builtins.fetchGit - { inherit (repoData) url ; ref = repoData.ref or null; } + let + drv = builtins.fetchGit { + inherit (repoData) url; + ref = repoData.ref or null; + } # fetchGit does not accept "null" as rev, so when it's null # we have to omit the argument completely. - // pkgs.lib.optionalAttrs (repoData ? rev) { inherit (repoData) rev; }; - in __trace "WARNING: No sha256 found for source-repository-package ${repoData.url} ref=${repoData.ref or "(unspecified)"} rev=${repoData.rev or "(unspecified)"} download may fail in restricted mode (hydra)" - (__trace "Consider adding `--sha256: ${hashPath drv}` to the ${cabalProjectFileName} file or passing in a sha256map argument" - drv); + // pkgs.lib.optionalAttrs (repoData ? rev) { + inherit (repoData) rev; + }; + in __trace + "WARNING: No sha256 found for source-repository-package ${repoData.url} ref=${ + repoData.ref or "(unspecified)" + } rev=${ + repoData.rev or "(unspecified)" + } download may fail in restricted mode (hydra)" (__trace + "Consider adding `--sha256: ${ + hashPath drv + }` to the ${cabalProjectFileName} file or passing in a sha256map argument" + drv); in { # Download the source-repository-package commit and add it to a minimal git # repository that `cabal` will be able to access from a non fixed output derivation. location = evalPackages.runCommand "source-repository-package" { - nativeBuildInputs = [ evalPackages.rsync evalPackages.gitMinimal ]; - } '' + nativeBuildInputs = [ evalPackages.rsync evalPackages.gitMinimal ]; + } '' mkdir $out rsync -a --prune-empty-dirs "${fetched}/" "$out/" cd $out @@ -230,26 +262,26 @@ let }; # Parse the `source-repository-package` blocks - sourceRepoPackageResult = pkgs.haskell-nix.haskellLib.parseSourceRepositoryPackages + sourceRepoPackageResult = + pkgs.haskell-nix.haskellLib.parseSourceRepositoryPackages cabalProjectFileName sha256map source-repo-override projectFile; - sourceRepoFixedProjectFile = - sourceRepoPackageResult.initialText + - pkgs.lib.strings.concatMapStrings (block: - if block ? sourceRepo - then - let - f = fetchPackageRepo evalPackages.fetchgit block.sourceRepo; - in '' - - ${block.indentation}source-repository-package - ${block.indentation} type: git - ${block.indentation} location: file://${f.location} - ${block.indentation} subdir: ${builtins.concatStringsSep " " f.subdirs} - ${block.indentation} tag: ${f.tag} - '' + block.followingText - else block.followingText - ) sourceRepoPackageResult.sourceRepos; + sourceRepoFixedProjectFile = sourceRepoPackageResult.initialText + + pkgs.lib.strings.concatMapStrings (block: + if block ? sourceRepo then + let f = fetchPackageRepo evalPackages.fetchgit block.sourceRepo; + in '' + + ${block.indentation}source-repository-package + ${block.indentation} type: git + ${block.indentation} location: file://${f.location} + ${block.indentation} subdir: ${ + builtins.concatStringsSep " " f.subdirs + } + ${block.indentation} tag: ${f.tag} + '' + block.followingText + else + block.followingText) sourceRepoPackageResult.sourceRepos; # we need the repository content twice: # * at eval time (below to build the fixed project file) @@ -260,44 +292,53 @@ let # on the target system would use, so that the derivation is unaffected # and, say, a linux release build job can identify the derivation # as built by a darwin builder, and fetch it from a cache - sourceReposEval = builtins.map (x: (fetchPackageRepo evalPackages.fetchgit x.sourceRepo)) sourceRepoPackageResult.sourceRepos; - sourceReposBuild = builtins.map (x: (fetchPackageRepo pkgs.fetchgit x.sourceRepo).fetched) sourceRepoPackageResult.sourceRepos; + sourceReposEval = + builtins.map (x: (fetchPackageRepo evalPackages.fetchgit x.sourceRepo)) + sourceRepoPackageResult.sourceRepos; + sourceReposBuild = + builtins.map (x: (fetchPackageRepo pkgs.fetchgit x.sourceRepo).fetched) + sourceRepoPackageResult.sourceRepos; # Parse the `repository` blocks - repoResult = pkgs.haskell-nix.haskellLib.parseRepositories - evalPackages cabalProjectFileName sha256map inputMap nix-tools sourceRepoFixedProjectFile; + repoResult = pkgs.haskell-nix.haskellLib.parseRepositories evalPackages + cabalProjectFileName sha256map inputMap nix-tools + sourceRepoFixedProjectFile; in { sourceRepos = sourceReposBuild; inherit (repoResult) repos extra-hackages; makeFixedProjectFile = '' HOME=$(mktemp -d) - cp -f ${evalPackages.writeText "cabal.project" sourceRepoFixedProjectFile} ./cabal.project + cp -f ${ + evalPackages.writeText "cabal.project" sourceRepoFixedProjectFile + } ./cabal.project chmod +w -R ./cabal.project - '' + pkgs.lib.strings.concatStrings ( - map (f: '' - git config --global --add safe.directory ${f.location}/.git - '') sourceReposEval - ); + '' + pkgs.lib.strings.concatStrings (map (f: '' + git config --global --add safe.directory ${f.location}/.git + '') sourceReposEval); # This will be used to replace refernces to the minimal git repos with just the index # of the repo. The index will be used in lib/import-and-filter-project.nix to # lookup the correct repository in `sourceReposBuild`. This avoids having # `/nix/store` paths in the `plan-nix` output so that it can be materialized safely. - replaceLocations = pkgs.lib.strings.concatStrings ( - pkgs.lib.lists.zipListsWith (n: f: '' - (cd $out${subDir'} - substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace file://${f.location} ${builtins.toString n} - for a in $(grep -rl file://${f.location} .plan.nix/*.nix); do - substituteInPlace $a --replace file://${f.location} ${builtins.toString n} - done) - '') - (pkgs.lib.lists.range 0 ((builtins.length sourceReposEval) - 1)) - sourceReposEval - ); + replaceLocations = pkgs.lib.strings.concatStrings + (pkgs.lib.lists.zipListsWith (n: f: '' + (cd $out${subDir'} + substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace file://${f.location} ${ + builtins.toString n + } + for a in $(grep -rl file://${f.location} .plan.nix/*.nix); do + substituteInPlace $a --replace file://${f.location} ${ + builtins.toString n + } + done) + '') (pkgs.lib.lists.range 0 ((builtins.length sourceReposEval) - 1)) + sourceReposEval); }; fixedProject = replaceSourceRepos rawCabalProject; - platformString = p: with p.parsed; "${cpu.name}-${vendor.name}-${kernel.name}"; + platformString = p: + with p.parsed; + "${cpu.name}-${vendor.name}-${kernel.name}"; # Dummy `ghc` that uses the captured output dummy-ghc = evalPackages.writeTextFile { @@ -322,36 +363,46 @@ let ;; ''} --supported-languages*) - cat ${import ./supported-languages.nix { inherit pkgs evalPackages ghc; }} + cat ${ + import ./supported-languages.nix { inherit pkgs evalPackages ghc; } + } ;; --print-global-package-db*) echo "$out/dumby-db" ;; --info*) echo '[("target os", "${ - if pkgs.stdenv.targetPlatform.isLinux - then "OSLinux" - else if pkgs.stdenv.targetPlatform.isDarwin - then "OSDarwin" - else if pkgs.stdenv.targetPlatform.isWindows - then "OSMinGW32" - else if pkgs.stdenv.targetPlatform.isGhcjs - then "OSGhcjs" - else throw "Unknown target os ${pkgs.stdenv.targetPlatform.config}" - }")' + if pkgs.stdenv.targetPlatform.isLinux then + "OSLinux" + else if pkgs.stdenv.targetPlatform.isDarwin then + "OSDarwin" + else if pkgs.stdenv.targetPlatform.isWindows then + "OSMinGW32" + else if pkgs.stdenv.targetPlatform.isGhcjs then + "OSGhcjs" + else + throw "Unknown target os ${pkgs.stdenv.targetPlatform.config}" + }")' echo ',("target arch","${ - if pkgs.stdenv.targetPlatform.isx86_64 - then "ArchX86_64" - else if pkgs.stdenv.targetPlatform.isAarch64 - then "ArchAArch64" - else if pkgs.stdenv.targetPlatform.isJavaScript - then "ArchJavaScript" - else throw "Unknown target arch ${pkgs.stdenv.targetPlatform.config}" + if pkgs.stdenv.targetPlatform.isx86_64 then + "ArchX86_64" + else if pkgs.stdenv.targetPlatform.isAarch64 then + "ArchAArch64" + else if pkgs.stdenv.targetPlatform.isJavaScript then + "ArchJavaScript" + else + throw "Unknown target arch ${pkgs.stdenv.targetPlatform.config}" + }")' + echo ',("target platform string","${ + platformString pkgs.stdenv.targetPlatform + }")' + echo ',("Build platform","${ + platformString pkgs.stdenv.buildPlatform }")' - echo ',("target platform string","${platformString pkgs.stdenv.targetPlatform}")' - echo ',("Build platform","${platformString pkgs.stdenv.buildPlatform}")' echo ',("Host platform","${platformString pkgs.stdenv.hostPlatform}")' - echo ',("Target platform","${platformString pkgs.stdenv.targetPlatform}")' + echo ',("Target platform","${ + platformString pkgs.stdenv.targetPlatform + }")' echo ']' ;; --print-libdir*) @@ -367,7 +418,7 @@ let }; dummy-ghc-pkg-dump = import ./dummy-ghc-pkg-dump { - inherit pkgs evalPackages; + inherit evalPackages; ghc-src = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; ghc-version = ghc.version; }; @@ -412,23 +463,30 @@ let }) (evalPackages.runCommand (nameAndSuffix "plan-to-nix-pkgs") { nativeBuildInputs = # The things needed from nix-tools - [ nix-tools.exes.make-install-plan + [ + nix-tools.exes.make-install-plan nix-tools.exes.plan-to-nix nix-tools.exes.cabal - ] - ++ pkgs.lib.optional supportHpack nix-tools.exes.hpack - ++ [dummy-ghc dummy-ghc-pkg evalPackages.rsync evalPackages.gitMinimal evalPackages.allPkgConfigWrapper ]; + ] ++ pkgs.lib.optional supportHpack nix-tools.exes.hpack ++ [ + dummy-ghc + dummy-ghc-pkg + evalPackages.rsync + evalPackages.gitMinimal + evalPackages.allPkgConfigWrapper + ]; # Needed or stack-to-nix will die on unicode inputs - LOCALE_ARCHIVE = pkgs.lib.optionalString (evalPackages.stdenv.buildPlatform.libc == "glibc") "${evalPackages.glibcLocales}/lib/locale/locale-archive"; + LOCALE_ARCHIVE = pkgs.lib.optionalString + (evalPackages.stdenv.buildPlatform.libc == "glibc") + "${evalPackages.glibcLocales}/lib/locale/locale-archive"; LANG = "en_US.UTF-8"; meta.platforms = pkgs.lib.platforms.all; preferLocalBuild = false; outputs = [ - "out" # The results of plan-to-nix + "out" # The results of plan-to-nix # These two output will be present if in cabal configure failed. # They are used to provide passthru.json and passthru.freeze that # check first for cabal configure failure. - "freeze" # The `cabal.project.freeze` file created by `cabal v2-freeze` + "freeze" # The `cabal.project.freeze` file created by `cabal v2-freeze` ]; } '' tmp=$(mktemp -d) @@ -439,9 +497,11 @@ let # message to prevent headaches (#290). if [ -z "$(ls -A ${cleanedSource})" ]; then echo "cleaned source is empty. Did you forget to 'git add -A'?" - ${pkgs.lib.optionalString (__length fixedProject.sourceRepos == 0) '' - exit 1 - ''} + ${ + pkgs.lib.optionalString (__length fixedProject.sourceRepos == 0) '' + exit 1 + '' + } else rsync -a ${cleanedSource}/ ./ fi @@ -459,12 +519,10 @@ let # hpack allows globbing, and turns that into module lists # without the source available (we cleanSourceWith'd it), # this may not produce the right result. - if supportHpack - then '' + if supportHpack then '' echo No .cabal file found, running hpack on $hpackFile hpack $hpackFile - '' - else '' + '' else '' echo "WARNING $hpackFile has no .cabal file and \`supportHpack\` was not set." '' } @@ -483,10 +541,10 @@ let export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt export CABAL_DIR=${ - # This creates `.cabal` directory that is as it would have - # been at the time `cached-index-state`. We may include - # some packages that will be excluded by `index-state-max` - # which is used by cabal (cached-index-state >= index-state-max). + # This creates `.cabal` directory that is as it would have + # been at the time `cached-index-state`. We may include + # some packages that will be excluded by `index-state-max` + # which is used by cabal (cached-index-state >= index-state-max). dotCabal { inherit nix-tools extra-hackage-tarballs; extra-hackage-repos = fixedProject.repos; @@ -496,20 +554,23 @@ let } make-install-plan ${ - # Setting the desired `index-state` here in case it is not - # in the cabal.project file. This will further restrict the - # packages used by the solver (cached-index-state >= index-state-max). - pkgs.lib.optionalString (index-state != null) "--index-state=${index-state}" - } \ + # Setting the desired `index-state` here in case it is not + # in the cabal.project file. This will further restrict the + # packages used by the solver (cached-index-state >= index-state-max). + pkgs.lib.optionalString (index-state != null) + "--index-state=${index-state}" + } \ -w ${ - # We are using `-w` rather than `--with-ghc` here to override - # the `with-compiler:` in the `cabal.project` file. - ghc.targetPrefix}ghc \ + # We are using `-w` rather than `--with-ghc` here to override + # the `with-compiler:` in the `cabal.project` file. + ghc.targetPrefix}ghc \ --with-ghc-pkg=${ghc.targetPrefix}ghc-pkg \ --enable-tests \ --enable-benchmarks \ - ${pkgs.lib.optionalString (ghc.targetPrefix == "js-unknown-ghcjs-") - "--ghcjs --with-ghcjs=js-unknown-ghcjs-ghc --with-ghcjs-pkg=js-unknown-ghcjs-ghc-pkg"} \ + ${ + pkgs.lib.optionalString (ghc.targetPrefix == "js-unknown-ghcjs-") + "--ghcjs --with-ghcjs=js-unknown-ghcjs-ghc --with-ghcjs-pkg=js-unknown-ghcjs-ghc-pkg" + } \ ${configureArgs} mkdir -p $out @@ -539,7 +600,9 @@ let # run `plan-to-nix` in $out. This should produce files right there with the # proper relative paths. - (cd $out${subDir'} && plan-to-nix --full ${if ignorePackageYaml then "--ignore-package-yaml" else ""} --plan-json $tmp${subDir'}/dist-newstyle/cache/plan.json -o .) + (cd $out${subDir'} && plan-to-nix --full ${ + if ignorePackageYaml then "--ignore-package-yaml" else "" + } --plan-json $tmp${subDir'}/dist-newstyle/cache/plan.json -o .) substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace "$out" "." substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace "$CABAL_DIR" "" diff --git a/lib/dummy-ghc-pkg-dump/configure.ac b/lib/dummy-ghc-pkg-dump/configure.ac index 49d1e413a8..bb64dd159e 100644 --- a/lib/dummy-ghc-pkg-dump/configure.ac +++ b/lib/dummy-ghc-pkg-dump/configure.ac @@ -1,13 +1,22 @@ AC_INIT([The Glorious Glasgow Haskell Compilation System], [0.00], [glasgow-haskell-bugs@haskell.org], [ghc-AC_PACKAGE_VERSION]) -AC_CONFIG_MACRO_DIRS([m4]) - # Set this to YES for a released version, otherwise NO : ${RELEASE=NO} +dnl ** Make sure we do not have a bogus source directory +AC_CONFIG_SRCDIR(ghc/Main.hs) + +dnl ** Output code to perform substitutions +AC_CONFIG_FILES + dnl ** Find unixy sort and find commands, dnl ** which are needed by FP_SETUP_PROJECT_VERSION FP_PROG_FIND FP_PROG_SORT +dnl ** FP_SETUP_VERSION assumes to be in the source directory +pushd ${srcdir} FP_SETUP_PROJECT_VERSION +popd + +AC_OUTPUT diff --git a/lib/dummy-ghc-pkg-dump/default.nix b/lib/dummy-ghc-pkg-dump/default.nix index cc71359544..0cc5b2817b 100644 --- a/lib/dummy-ghc-pkg-dump/default.nix +++ b/lib/dummy-ghc-pkg-dump/default.nix @@ -1,7 +1,7 @@ -{ pkgs, evalPackages, ghc-version, ghc-src }: +{ evalPackages, ghc-version, ghc-src }: let - inherit (pkgs) lib stdenv; + inherit (evalPackages) lib stdenv; varname = builtins.replaceStrings [ "-" ] [ "_" ]; @@ -53,23 +53,80 @@ let ] ++ lib.optionals (!stdenv.targetPlatform.isGhcjs) [ "terminfo" ] ++ (if stdenv.targetPlatform.isWindows then [ "Win32" ] else [ "unix" ]); - configure = evalPackages.runCommand "autoreconf" { - nativeBuildInputs = with evalPackages; [ autotools coreutils findutils ]; - } '' - mkdir -p $out - cd $out - cp ./configure.ac . - ln -s ${ghc-src}/m4 . - autoreconf -i - rm m4 - ''; + configure = ghc-src: + let + ghc-m4-src = builtins.path { + filter = path: type: lib.hasPrefix "${ghc-src}/m4" path; + path = ghc-src; + name = "ghc-src-m4"; + }; + in evalPackages.runCommand "configure" { + nativeBuildInputs = with evalPackages; [ + autoconf + automake + coreutils + findutils + ]; + } '' + set -euo pipefail + + mkdir -p $out + cd $out + + cp -v ${./configure.ac} configure.ac + aclocal --verbose -I "${ghc-m4-src}/m4" + autoconf --verbose + ''; + + # config-status = ghc-src: + # evalPackages.runCommand "config.status" { + # nativeBuildInputs = [ (configure ghc-src) ]; + # } '' + # mkdir -p $out/bin + # cp -v config.status $out/bin/config.status + # ''; + + x = ghc-src: + evalPackages.runCommand "x" { + + nativeBuildInputs = [ + evalPackages.haskell-nix.nix-tools-unchecked.exes.cabal2json + evalPackages.jq + ]; + + } '' + set -euo pipefail + + mkdir -p $out + cd $out + + # Copy the cabal.in files + pushd ${ghc-src} + CABAL_IN_FILES=(*/*.cabal.in libraries/*/*.cabal.in) + cp --no-preserve all --parents "''${CABAL_IN_FILES[@]}" "$out" + popd + + # Run configure script (only for the project version) + ${configure ghc-src}/configure --srcdir=${ghc-src} + + # Substitute config variables in the cabal files + CABAL_FILES=(''${CABAL_IN_FILES[@]%.in}) + ./config.status $(printf -- '--file %s ' "''${CABAL_FILES[@]}") + + cabal2json --help + + # Convert to json + for f in ''${CABAL_FILES[@]}; do + cabal2json --out="$f.json" "$f" + done + ''; in evalPackages.runCommand "dummy-ghc-pkg-dump" { nativeBuildInputs = [ evalPackages.haskell-nix.nix-tools-unchecked.exes.cabal2json evalPackages.jq ]; - passthru = { inherit configure; }; + passthru = { inherit configure x; }; } '' PACKAGE_VERSION=${ghc-version} ProjectVersion=${ghc-version} @@ -93,14 +150,6 @@ in evalPackages.runCommand "dummy-ghc-pkg-dump" { # The project patchlevel is zero unless stated otherwise test -z "$ProjectPatchLevel" && ProjectPatchLevel=0 - # Save split version of ProjectPatchLevel - ProjectPatchLevel1=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1/'` - ProjectPatchLevel2=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3/'` - - # The project patchlevel1/2 is zero unless stated otherwise - test -z "$ProjectPatchLevel1" && ProjectPatchLevel1=0 - test -z "$ProjectPatchLevel2" && ProjectPatchLevel2=0 - # AC_SUBST([ProjectPatchLevel1]) # AC_SUBST([ProjectPatchLevel2]) @@ -137,6 +186,15 @@ in evalPackages.runCommand "dummy-ghc-pkg-dump" { ??) ProjectVersionForLibUpperHalf=''${VERSION_MAJOR}.''${VERSION_MINOR} ;; *) echo bad minor version in $PACKAGE_VERSION; exit 1 ;; esac + + # Save split version of ProjectPatchLevel + ProjectPatchLevel1=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1/'` + ProjectPatchLevel2=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3/'` + + # The project patchlevel1/2 is zero unless stated otherwise + test -z "$ProjectPatchLevel1" && ProjectPatchLevel1=0 + test -z "$ProjectPatchLevel2" && ProjectPatchLevel2=0 + # GHC HEAD uses patch level version > 20000000 case $ProjectPatchLevel1 in ?) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}0''${ProjectPatchLevel1} ;; diff --git a/overlays/haskell.nix b/overlays/haskell.nix index fc9d9ec54e..edb62d2e4d 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -595,28 +595,31 @@ final: prev: { }; dummy-ghc-pkg-dump = import ../lib/dummy-ghc-pkg-dump { - pkgs = final.buildPackages.pkgs; + # FIXME: just for testing + evalPackages = final; + ghc-version = "0.0.0"; + ghc-src = final.ghc.src; }; - + # Takes a haskell src directory runs cabal new-configure and plan-to-nix. # Resulting nix files are added to nix-plan subdirectory. callCabalProjectToNix = import ../lib/call-cabal-project-to-nix.nix { + pkgs = final.buildPackages.pkgs; index-state-hashes = import indexStateHashesPath; inherit (final.buildPackages.haskell-nix) haskellLib; - pkgs = final.buildPackages.pkgs; inherit (final.buildPackages.pkgs) cacert; }; # Loads a plan and filters the package directories using cleanSourceWith importAndFilterProject = import ../lib/import-and-filter-project.nix { - inherit (final.buildPackages.haskell-nix) haskellLib; pkgs = final.buildPackages.pkgs; + inherit (final.buildPackages.haskell-nix) haskellLib; }; # Loads a plan and filters the package directories using cleanSourceWith loadCabalPlan = import ../lib/load-cabal-plan.nix { - inherit (final.buildPackages.haskell-nix) haskellLib; pkgs = final.buildPackages.pkgs; + inherit (final.buildPackages.haskell-nix) haskellLib; }; # References to the unpacked sources, for caching in a Hydra jobset. From 66075969f940a355b993ed0f257ae87323d1b22e Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Thu, 12 Dec 2024 16:41:11 +0800 Subject: [PATCH 09/16] feat: update Cabal-syntax-json in nix-tools --- nix-tools/cabal.project | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nix-tools/cabal.project b/nix-tools/cabal.project index e960f8a0a1..1018fd72ef 100644 --- a/nix-tools/cabal.project +++ b/nix-tools/cabal.project @@ -36,5 +36,5 @@ source-repository-package source-repository-package type: git location: https://github.com/andreabedini/Cabal-syntax-json.git - tag: c6c01db076117c309f8ec2e0b8f58b105479f391 - --sha256: sha256-Vj66Sdeq3lizcZxSBJ8QQhPVJ7QDXRdpvDX65RF51oY= + tag: 7a80221047fb5dd66a091f4a7248e0afa3bcc248 + --sha256: sha256-R55nljZMnc6s+Apc4uaZal9ExDauxYq/pV7RxQHwzVc= From 943e083fd98ca91de9f7101ad1cc93d334cb10c5 Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Thu, 12 Dec 2024 16:51:16 +0800 Subject: [PATCH 10/16] WIP --- lib/call-cabal-project-to-nix.nix | 3 +-- lib/dummy-ghc-pkg-dump/default.nix | 41 ++++++++---------------------- overlays/haskell.nix | 3 +-- 3 files changed, 13 insertions(+), 34 deletions(-) diff --git a/lib/call-cabal-project-to-nix.nix b/lib/call-cabal-project-to-nix.nix index 1f15708c09..edbdcd5c2b 100644 --- a/lib/call-cabal-project-to-nix.nix +++ b/lib/call-cabal-project-to-nix.nix @@ -417,8 +417,7 @@ let ''; }; - dummy-ghc-pkg-dump = import ./dummy-ghc-pkg-dump { - inherit evalPackages; + dummy-ghc-pkg-dump = evalPackages.callPackage ./dummy-ghc-pkg-dump { ghc-src = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; ghc-version = ghc.version; }; diff --git a/lib/dummy-ghc-pkg-dump/default.nix b/lib/dummy-ghc-pkg-dump/default.nix index 0cc5b2817b..8b7fb31a9c 100644 --- a/lib/dummy-ghc-pkg-dump/default.nix +++ b/lib/dummy-ghc-pkg-dump/default.nix @@ -1,8 +1,7 @@ -{ evalPackages, ghc-version, ghc-src }: +{ lib, stdenv, runCommand, autoconf, automake, coreutils, findutils, jq +, haskell-nix, ghc-version, ghc-src }: let - inherit (evalPackages) lib stdenv; - varname = builtins.replaceStrings [ "-" ] [ "_" ]; ghc-pkgs = [ @@ -60,13 +59,8 @@ let path = ghc-src; name = "ghc-src-m4"; }; - in evalPackages.runCommand "configure" { - nativeBuildInputs = with evalPackages; [ - autoconf - automake - coreutils - findutils - ]; + in runCommand "configure" { + nativeBuildInputs = [ autoconf automake coreutils findutils ]; } '' set -euo pipefail @@ -78,22 +72,14 @@ let autoconf --verbose ''; - # config-status = ghc-src: - # evalPackages.runCommand "config.status" { - # nativeBuildInputs = [ (configure ghc-src) ]; - # } '' - # mkdir -p $out/bin - # cp -v config.status $out/bin/config.status - # ''; - x = ghc-src: - evalPackages.runCommand "x" { - + runCommand "x" { nativeBuildInputs = [ - evalPackages.haskell-nix.nix-tools-unchecked.exes.cabal2json - evalPackages.jq + # FIXME: for testing + haskell-nix.nix-tools.exes.cabal2json + # haskell-nix.nix-tools-unchecked.exes.cabal2json + jq ]; - } '' set -euo pipefail @@ -113,19 +99,14 @@ let CABAL_FILES=(''${CABAL_IN_FILES[@]%.in}) ./config.status $(printf -- '--file %s ' "''${CABAL_FILES[@]}") - cabal2json --help - # Convert to json for f in ''${CABAL_FILES[@]}; do cabal2json --out="$f.json" "$f" done ''; -in evalPackages.runCommand "dummy-ghc-pkg-dump" { - nativeBuildInputs = [ - evalPackages.haskell-nix.nix-tools-unchecked.exes.cabal2json - evalPackages.jq - ]; +in runCommand "dummy-ghc-pkg-dump" { + nativeBuildInputs = [ haskell-nix.nix-tools-unchecked.exes.cabal2json jq ]; passthru = { inherit configure x; }; } '' PACKAGE_VERSION=${ghc-version} diff --git a/overlays/haskell.nix b/overlays/haskell.nix index edb62d2e4d..e6d1c4b8e9 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -594,9 +594,8 @@ final: prev: { }; - dummy-ghc-pkg-dump = import ../lib/dummy-ghc-pkg-dump { + dummy-ghc-pkg-dump = final.callPackage ../lib/dummy-ghc-pkg-dump { # FIXME: just for testing - evalPackages = final; ghc-version = "0.0.0"; ghc-src = final.ghc.src; }; From 97efe37fbfe80e767e886e944545f0e7570e3a6e Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Thu, 12 Dec 2024 18:24:40 +0800 Subject: [PATCH 11/16] WIP --- lib/dummy-ghc-pkg-dump/configure.ac | 8 ++++---- lib/dummy-ghc-pkg-dump/default.nix | 32 +++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/lib/dummy-ghc-pkg-dump/configure.ac b/lib/dummy-ghc-pkg-dump/configure.ac index bb64dd159e..35a5396783 100644 --- a/lib/dummy-ghc-pkg-dump/configure.ac +++ b/lib/dummy-ghc-pkg-dump/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([The Glorious Glasgow Haskell Compilation System], [0.00], [glasgow-haskell-bugs@haskell.org], [ghc-AC_PACKAGE_VERSION]) +AC_INIT([The Glorious Glasgow Haskell Compilation System], [0.0.0], [glasgow-haskell-bugs@haskell.org]) # Set this to YES for a released version, otherwise NO : ${RELEASE=NO} @@ -6,9 +6,6 @@ AC_INIT([The Glorious Glasgow Haskell Compilation System], [0.00], [glasgow-hask dnl ** Make sure we do not have a bogus source directory AC_CONFIG_SRCDIR(ghc/Main.hs) -dnl ** Output code to perform substitutions -AC_CONFIG_FILES - dnl ** Find unixy sort and find commands, dnl ** which are needed by FP_SETUP_PROJECT_VERSION FP_PROG_FIND @@ -19,4 +16,7 @@ pushd ${srcdir} FP_SETUP_PROJECT_VERSION popd +dnl ** Output code to perform substitutions +AC_CONFIG_FILES + AC_OUTPUT diff --git a/lib/dummy-ghc-pkg-dump/default.nix b/lib/dummy-ghc-pkg-dump/default.nix index 8b7fb31a9c..a5e34373b1 100644 --- a/lib/dummy-ghc-pkg-dump/default.nix +++ b/lib/dummy-ghc-pkg-dump/default.nix @@ -73,7 +73,15 @@ let ''; x = ghc-src: - runCommand "x" { + let + ## GHC version + flags = (lib.optional stdenv.targetPlatform.isx86_64 "--arch x86_64") + ++ (lib.optional stdenv.targetPlatform.isAarch64 "--arch aarch64") + ++ (lib.optional stdenv.targetPlatform.isLinux "--os linux") + ++ (lib.optional stdenv.targetPlatform.isDarwin "--os osx") + ++ (lib.optional stdenv.targetPlatform.isGhcjs "--arch javascript"); + + in runCommand "x" { nativeBuildInputs = [ # FIXME: for testing haskell-nix.nix-tools.exes.cabal2json @@ -82,26 +90,32 @@ let ]; } '' set -euo pipefail + shopt -s globstar mkdir -p $out cd $out + # Run configure script (only for the project version) + ${configure ghc-src}/configure --srcdir=${ghc-src} + # Copy the cabal.in files pushd ${ghc-src} - CABAL_IN_FILES=(*/*.cabal.in libraries/*/*.cabal.in) - cp --no-preserve all --parents "''${CABAL_IN_FILES[@]}" "$out" + cp --no-preserve all --parents */*.cabal */*.cabal.in libraries/*/*.cabal libraries/*/*.cabal.in "$out" popd - # Run configure script (only for the project version) - ${configure ghc-src}/configure --srcdir=${ghc-src} + find # Substitute config variables in the cabal files - CABAL_FILES=(''${CABAL_IN_FILES[@]%.in}) - ./config.status $(printf -- '--file %s ' "''${CABAL_FILES[@]}") + FILES=( **/*.cabal.in ) + ./config.status $(printf -- '--file %s ' ''${FILES[@]%.in}) # Convert to json - for f in ''${CABAL_FILES[@]}; do - cabal2json --out="$f.json" "$f" + for f in **/*.cabal; do + # FIXME + if [[ $f == rts/rts.cabal ]]; then + continue + fi + cabal2json ${lib.concatStringsSep " " flags} --out="$f.json" "$f" done ''; From c8799d93473bdbf15c20bb64cdd91d28318eb748 Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Thu, 12 Dec 2024 18:35:04 +0800 Subject: [PATCH 12/16] WIP --- lib/dummy-ghc-pkg-dump/default.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/dummy-ghc-pkg-dump/default.nix b/lib/dummy-ghc-pkg-dump/default.nix index a5e34373b1..cff708100b 100644 --- a/lib/dummy-ghc-pkg-dump/default.nix +++ b/lib/dummy-ghc-pkg-dump/default.nix @@ -109,6 +109,10 @@ let FILES=( **/*.cabal.in ) ./config.status $(printf -- '--file %s ' ''${FILES[@]%.in}) + FLAGS=(${lib.concatStringsSep " " flags}) + VERSION=$(cabal2json ghc/ghc-bin.cabal | jq .version) + FLAGS+=(--compiler ghc-$VERSION) + # Convert to json for f in **/*.cabal; do # FIXME From 2453c6c248d56dd73fc543beb62cf7e914f07177 Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Mon, 16 Dec 2024 16:35:07 +0800 Subject: [PATCH 13/16] WIP --- lib/call-cabal-project-to-nix.nix | 541 ++++++++++++---------------- lib/dummy-ghc-pkg-dump/configure.ac | 14 +- lib/dummy-ghc-pkg-dump/default.nix | 384 +++++--------------- lib/dummy-ghc-pkg-dump/script.jq | 33 ++ nix-tools/flake.nix | 99 +++-- nix-tools/overlay.nix | 3 +- overlays/haskell.nix | 9 +- 7 files changed, 419 insertions(+), 664 deletions(-) create mode 100644 lib/dummy-ghc-pkg-dump/script.jq diff --git a/lib/call-cabal-project-to-nix.nix b/lib/call-cabal-project-to-nix.nix index edbdcd5c2b..e585772bbf 100644 --- a/lib/call-cabal-project-to-nix.nix +++ b/lib/call-cabal-project-to-nix.nix @@ -1,69 +1,69 @@ -{ pkgs, cacert, index-state-hashes, haskellLib }: - -{ name ? src.name or null # optional name for better error messages -, src, materialized-dir ? ../materialized -, compiler-nix-name # The name of the ghc compiler to use eg. "ghc884" -, index-state ? null # Hackage index-state, eg. "2019-10-10T00:00:00Z" -, index-sha256 ? null # The hash of the truncated hackage index-state -, plan-sha256 ? - null # The hash of the plan-to-nix output (makes the plan-to-nix step a fixed output derivation) -, materialized ? null # Location of a materialized copy of the nix files -, checkMaterialization ? - null # If true the nix files will be generated used to check plan-sha256 and material -, cabalProjectFileName ? "cabal.project", cabalProject ? null -, cabalProjectLocal ? null, cabalProjectFreeze ? null, caller ? - "callCabalProjectToNix" # Name of the calling function for better warning messages -, compilerSelection ? p: p.haskell-nix.compiler -, ghc ? null # Deprecated in favour of `compiler-nix-name` -, ghcOverride ? - null # Used when we need to set ghc explicitly during bootstrapping +{ pkgs, runCommand, cacert, index-state-hashes, haskellLib }: +{ name ? src.name or null # optional name for better error messages +, src +, materialized-dir ? ../materialized +, compiler-nix-name # The name of the ghc compiler to use eg. "ghc884" +, index-state ? null # Hackage index-state, eg. "2019-10-10T00:00:00Z" +, index-sha256 ? null # The hash of the truncated hackage index-state +, plan-sha256 ? null # The hash of the plan-to-nix output (makes the plan-to-nix step a fixed output derivation) +, materialized ? null # Location of a materialized copy of the nix files +, checkMaterialization ? null # If true the nix files will be generated used to check plan-sha256 and material +, cabalProjectFileName ? "cabal.project" +, cabalProject ? null +, cabalProjectLocal ? null +, cabalProjectFreeze ? null +, caller ? "callCabalProjectToNix" # Name of the calling function for better warning messages +, compilerSelection ? p: p.haskell-nix.compiler +, ghc ? null # Deprecated in favour of `compiler-nix-name` +, ghcOverride ? null # Used when we need to set ghc explicitly during bootstrapping , configureArgs ? "" # Extra arguments to pass to `cabal v2-configure`. - # `--enable-tests --enable-benchmarks` are included by default. - # If the tests and benchmarks are not needed and they - # cause the wrong plan to be chosen, then we can use - # `configureArgs = "--disable-tests --disable-benchmarks";` -, sha256map ? null - # An alternative to adding `--sha256` comments into the - # cabal.project file: - # sha256map = - # { # For a `source-repository-package` use the `location` and `tag` as the key - # "https://github.com/jgm/pandoc-citeproc"."0.17" - # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; - # # For a `repository` use the `url` as the key - # "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32" - # = "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg="; - # }; -, inputMap ? { } - # An alternative to providing a `sha256` handy for flakes - # cabal.project file: - # inputs.pandoc-citeproc.url = "github:jgm/pandoc-citeproc/0.17"; - # inputs.pandoc-citeproc.flake = false; - # outputs = inputs: - # ... - # inputMap."https://github.com/jgm/pandoc-citeproc" = inputs.inputs.pandoc-citeproc; -, extra-hackage-tarballs ? { }, source-repo-override ? - { } # Cabal seems to behave incoherently when - # two source-repository-package entries - # provide the same packages, making it - # impossible to override cabal.project - # with e.g. a cabal.project.local. In CI, - # we want to be able to test against the - # latest versions of various dependencies. - # - # This argument is a map from url to - # a function taking the existing repoData - # and returning the new repoData in its - # place. E.g. - # - # { "https://github.com/input-output-hk/plutus-apps" = orig: orig // { subdirs = (orig.subdirs or [ "." ]) ++ [ "foo" ]; }; } - # - # would result in the "foo" subdirectory of - # any plutus-apps input being used for a - # package. + # `--enable-tests --enable-benchmarks` are included by default. + # If the tests and benchmarks are not needed and they + # cause the wrong plan to be chosen, then we can use + # `configureArgs = "--disable-tests --disable-benchmarks";` +, sha256map ? null + # An alternative to adding `--sha256` comments into the + # cabal.project file: + # sha256map = + # { # For a `source-repository-package` use the `location` and `tag` as the key + # "https://github.com/jgm/pandoc-citeproc"."0.17" + # = "0dxx8cp2xndpw3jwiawch2dkrkp15mil7pyx7dvd810pwc22pm2q"; + # # For a `repository` use the `url` as the key + # "https://raw.githubusercontent.com/input-output-hk/hackage-overlay-ghcjs/bfc363b9f879c360e0a0460ec0c18ec87222ec32" + # = "sha256-g9xGgJqYmiczjxjQ5JOiK5KUUps+9+nlNGI/0SpSOpg="; + # }; +, inputMap ? {} + # An alternative to providing a `sha256` handy for flakes + # cabal.project file: + # inputs.pandoc-citeproc.url = "github:jgm/pandoc-citeproc/0.17"; + # inputs.pandoc-citeproc.flake = false; + # outputs = inputs: + # ... + # inputMap."https://github.com/jgm/pandoc-citeproc" = inputs.inputs.pandoc-citeproc; +, extra-hackage-tarballs ? {} +, source-repo-override ? {} # Cabal seems to behave incoherently when + # two source-repository-package entries + # provide the same packages, making it + # impossible to override cabal.project + # with e.g. a cabal.project.local. In CI, + # we want to be able to test against the + # latest versions of various dependencies. + # + # This argument is a map from url to + # a function taking the existing repoData + # and returning the new repoData in its + # place. E.g. + # + # { "https://github.com/input-output-hk/plutus-apps" = orig: orig // { subdirs = (orig.subdirs or [ "." ]) ++ [ "foo" ]; }; } + # + # would result in the "foo" subdirectory of + # any plutus-apps input being used for a + # package. , evalPackages -, supportHpack ? false # Run hpack on package.yaml files with no .cabal file +, supportHpack ? false # Run hpack on package.yaml files with no .cabal file , ignorePackageYaml ? false # Ignore package.yaml files even if they exist -, ... }@args: +, ... +}@args: let inherit (evalPackages.haskell-nix) materialize dotCabal; @@ -71,56 +71,46 @@ let # lazy enough to avoid infinite recursion issues. # Using null as the default also improves performance as they are not forced by the # nix module system for `nix-tools-unchecked`. - nix-tools = if args.nix-tools or null != null then - args.nix-tools - else - evalPackages.haskell-nix.nix-tools-unchecked; + nix-tools = if args.nix-tools or null != null + then args.nix-tools + else evalPackages.haskell-nix.nix-tools-unchecked; forName = pkgs.lib.optionalString (name != null) (" for " + name); nameAndSuffix = suffix: if name == null then suffix else name + "-" + suffix; - ghc' = if ghcOverride != null then - ghcOverride - else if ghc != null then - __trace ("WARNING: A `ghc` argument was passed" + forName - + " this has been deprecated in favour of `compiler-nix-name`. " - + "Using `ghc` will break cross compilation setups, as haskell.nix cannot " - + "pick the correct `ghc` package from the respective buildPackages. " - + ''For example, use `compiler-nix-name = "ghc865";` for GHC 8.6.5.'') ghc - else - # Do note that `pkgs = final.buildPackages` in the `overlays/haskell.nix` - # call to this file. And thus `pkgs` here is the proper `buildPackages` - # set and we do not need, nor should pick the compiler from another level - # of `buildPackages`, lest we want to get confusing errors about the Win32 - # package. - # - # > The option `packages.Win32.package.identifier.name' is used but not defined. - # - (compilerSelection pkgs)."${compiler-nix-name}"; + ghc' = + if ghcOverride != null + then ghcOverride + else + if ghc != null + then __trace ("WARNING: A `ghc` argument was passed" + forName + + " this has been deprecated in favour of `compiler-nix-name`. " + + "Using `ghc` will break cross compilation setups, as haskell.nix cannot " + + "pick the correct `ghc` package from the respective buildPackages. " + + "For example, use `compiler-nix-name = \"ghc865\";` for GHC 8.6.5.") ghc + else + # Do note that `pkgs = final.buildPackages` in the `overlays/haskell.nix` + # call to this file. And thus `pkgs` here is the proper `buildPackages` + # set and we do not need, nor should pick the compiler from another level + # of `buildPackages`, lest we want to get confusing errors about the Win32 + # package. + # + # > The option `packages.Win32.package.identifier.name' is used but not defined. + # + (compilerSelection pkgs)."${compiler-nix-name}"; in let - ghc = if ghc' ? latestVersion then - __trace - "WARNING: ${ghc'.version} is out of date, consider using upgrading to ${ghc'.latestVersion}." - ghc' - else - ghc'; - + ghc = if ghc' ? latestVersion + then __trace "WARNING: ${ghc'.version} is out of date, consider using upgrading to ${ghc'.latestVersion}." ghc' + else ghc'; subDir' = src.origSubDir or ""; subDir = pkgs.lib.strings.removePrefix "/" subDir'; cleanedSource = haskellLib.cleanSourceWith { - name = if name != null then - "${name}-root-cabal-files" - else - "source-root-cabal-files"; + name = if name != null then "${name}-root-cabal-files" else "source-root-cabal-files"; src = src.origSrc or src; - filter = path: type: - (!(src ? filter) || src.filter path type) && (type == "directory" - || pkgs.lib.any (i: (pkgs.lib.hasSuffix i path)) [ - ".cabal" - "package.yaml" - ]); - }; + filter = path: type: (!(src ? filter) || src.filter path type) && ( + type == "directory" || + pkgs.lib.any (i: (pkgs.lib.hasSuffix i path)) [ ".cabal" "package.yaml" ]); }; # When there is no `cabal.project` file `cabal-install` behaves as if there was # one containing `packages: ./*.cabal`. Even if there is a `cabal.project.local` @@ -137,52 +127,53 @@ in let # https://github.com/input-output-hk/haskell.nix/pull/1639 # rawCabalProject = '' - ${if cabalProject == null then '' - -- Included to match the implicit project used by `cabal-install` - packages: ./*.cabal - '' else - cabalProject} - ${pkgs.lib.optionalString (cabalProjectLocal != null) '' - -- Added from `cabalProjectLocal` argument to the `cabalProject` function - ${cabalProjectLocal} - ''} + ${ + if cabalProject == null + then '' + -- Included to match the implicit project used by `cabal-install` + packages: ./*.cabal + '' + else cabalProject + } + ${ + pkgs.lib.optionalString (cabalProjectLocal != null) '' + -- Added from `cabalProjectLocal` argument to the `cabalProject` function + ${cabalProjectLocal} + '' + } ''; - index-state-max = if index-state != null then - index-state - else - pkgs.lib.last (builtins.attrNames index-state-hashes); + index-state-max = + if index-state != null + then index-state + else pkgs.lib.last (builtins.attrNames index-state-hashes); # If a hash was not specified find a suitable cached index state to # use that will contain all the packages we need. By using the # first one after the desired index-state we can avoid recalculating # when new index-state-hashes are added. # See https://github.com/input-output-hk/haskell.nix/issues/672 - cached-index-state = if index-sha256 != null then - index-state-max - else - let - suitable-index-states = builtins.filter - (s: s >= index-state-max) # This compare is why we need zulu time - (builtins.attrNames index-state-hashes); - in if builtins.length suitable-index-states == 0 then - index-state-max + cached-index-state = if index-sha256 != null + then index-state-max else - pkgs.lib.head suitable-index-states; + let + suitable-index-states = + builtins.filter + (s: s >= index-state-max) # This compare is why we need zulu time + (builtins.attrNames index-state-hashes); + in + if builtins.length suitable-index-states == 0 + then index-state-max + else pkgs.lib.head suitable-index-states; # Lookup hash for the index state we found - index-sha256-found = if index-sha256 != null then - index-sha256 - else - index-state-hashes.${cached-index-state} or null; - -in assert (if index-sha256-found == null then - throw - "Unknown index-state ${index-state-max}, the latest index-state I know about is ${ - pkgs.lib.last (builtins.attrNames index-state-hashes) - }. You may need to update to a newer hackage.nix." -else - true); + index-sha256-found = if index-sha256 != null + then index-sha256 + else index-state-hashes.${cached-index-state} or null; + +in + assert (if index-sha256-found == null + then throw "Unknown index-state ${index-state-max}, the latest index-state I know about is ${pkgs.lib.last (builtins.attrNames index-state-hashes)}. You may need to update to a newer hackage.nix." else true); let # Deal with source-repository-packages in a way that will work in @@ -199,55 +190,30 @@ let fetchPackageRepo = fetchgit: repoData: let fetched = - if inputMap ? "${repoData.url}/${repoData.rev or repoData.ref}" then - inputMap."${repoData.url}/${repoData.rev or repoData.ref}" - else if inputMap ? ${repoData.url} then - (if inputMap.${repoData.url}.rev - != (repoData.rev or repoData.ref) then - throw '' - ${inputMap.${repoData.url}.rev} may not match ${ - repoData.rev or repoData.ref - } for ${repoData.url} use "${repoData.url}/${ - repoData.rev or repoData.ref - }" as the inputMap key if ${ - repoData.rev or repoData.ref - } is a branch or tag that points to ${ - inputMap.${repoData.url}.rev - }.'' - else - inputMap.${repoData.url}) - else if repoData.sha256 != null then - fetchgit { - inherit (repoData) url sha256; - rev = repoData.rev or repoData.ref; - } + if inputMap ? "${repoData.url}/${repoData.rev or repoData.ref}" + then inputMap."${repoData.url}/${repoData.rev or repoData.ref}" + else if inputMap ? ${repoData.url} + then + (if inputMap.${repoData.url}.rev != (repoData.rev or repoData.ref) + then throw "${inputMap.${repoData.url}.rev} may not match ${repoData.rev or repoData.ref} for ${repoData.url} use \"${repoData.url}/${repoData.rev or repoData.ref}\" as the inputMap key if ${repoData.rev or repoData.ref} is a branch or tag that points to ${inputMap.${repoData.url}.rev}." + else inputMap.${repoData.url}) + else if repoData.sha256 != null + then fetchgit { inherit (repoData) url sha256; rev = repoData.rev or repoData.ref; } else - let - drv = builtins.fetchGit { - inherit (repoData) url; - ref = repoData.ref or null; - } + let drv = builtins.fetchGit + { inherit (repoData) url ; ref = repoData.ref or null; } # fetchGit does not accept "null" as rev, so when it's null # we have to omit the argument completely. - // pkgs.lib.optionalAttrs (repoData ? rev) { - inherit (repoData) rev; - }; - in __trace - "WARNING: No sha256 found for source-repository-package ${repoData.url} ref=${ - repoData.ref or "(unspecified)" - } rev=${ - repoData.rev or "(unspecified)" - } download may fail in restricted mode (hydra)" (__trace - "Consider adding `--sha256: ${ - hashPath drv - }` to the ${cabalProjectFileName} file or passing in a sha256map argument" - drv); + // pkgs.lib.optionalAttrs (repoData ? rev) { inherit (repoData) rev; }; + in __trace "WARNING: No sha256 found for source-repository-package ${repoData.url} ref=${repoData.ref or "(unspecified)"} rev=${repoData.rev or "(unspecified)"} download may fail in restricted mode (hydra)" + (__trace "Consider adding `--sha256: ${hashPath drv}` to the ${cabalProjectFileName} file or passing in a sha256map argument" + drv); in { # Download the source-repository-package commit and add it to a minimal git # repository that `cabal` will be able to access from a non fixed output derivation. location = evalPackages.runCommand "source-repository-package" { - nativeBuildInputs = [ evalPackages.rsync evalPackages.gitMinimal ]; - } '' + nativeBuildInputs = [ evalPackages.rsync evalPackages.gitMinimal ]; + } '' mkdir $out rsync -a --prune-empty-dirs "${fetched}/" "$out/" cd $out @@ -262,26 +228,26 @@ let }; # Parse the `source-repository-package` blocks - sourceRepoPackageResult = - pkgs.haskell-nix.haskellLib.parseSourceRepositoryPackages + sourceRepoPackageResult = pkgs.haskell-nix.haskellLib.parseSourceRepositoryPackages cabalProjectFileName sha256map source-repo-override projectFile; - sourceRepoFixedProjectFile = sourceRepoPackageResult.initialText - + pkgs.lib.strings.concatMapStrings (block: - if block ? sourceRepo then - let f = fetchPackageRepo evalPackages.fetchgit block.sourceRepo; - in '' - - ${block.indentation}source-repository-package - ${block.indentation} type: git - ${block.indentation} location: file://${f.location} - ${block.indentation} subdir: ${ - builtins.concatStringsSep " " f.subdirs - } - ${block.indentation} tag: ${f.tag} - '' + block.followingText - else - block.followingText) sourceRepoPackageResult.sourceRepos; + sourceRepoFixedProjectFile = + sourceRepoPackageResult.initialText + + pkgs.lib.strings.concatMapStrings (block: + if block ? sourceRepo + then + let + f = fetchPackageRepo evalPackages.fetchgit block.sourceRepo; + in '' + + ${block.indentation}source-repository-package + ${block.indentation} type: git + ${block.indentation} location: file://${f.location} + ${block.indentation} subdir: ${builtins.concatStringsSep " " f.subdirs} + ${block.indentation} tag: ${f.tag} + '' + block.followingText + else block.followingText + ) sourceRepoPackageResult.sourceRepos; # we need the repository content twice: # * at eval time (below to build the fixed project file) @@ -292,53 +258,46 @@ let # on the target system would use, so that the derivation is unaffected # and, say, a linux release build job can identify the derivation # as built by a darwin builder, and fetch it from a cache - sourceReposEval = - builtins.map (x: (fetchPackageRepo evalPackages.fetchgit x.sourceRepo)) - sourceRepoPackageResult.sourceRepos; - sourceReposBuild = - builtins.map (x: (fetchPackageRepo pkgs.fetchgit x.sourceRepo).fetched) - sourceRepoPackageResult.sourceRepos; + sourceReposEval = builtins.map (x: (fetchPackageRepo evalPackages.fetchgit x.sourceRepo)) sourceRepoPackageResult.sourceRepos; + sourceReposBuild = builtins.map (x: (fetchPackageRepo pkgs.fetchgit x.sourceRepo).fetched) sourceRepoPackageResult.sourceRepos; # Parse the `repository` blocks - repoResult = pkgs.haskell-nix.haskellLib.parseRepositories evalPackages - cabalProjectFileName sha256map inputMap nix-tools - sourceRepoFixedProjectFile; + repoResult = pkgs.haskell-nix.haskellLib.parseRepositories + evalPackages cabalProjectFileName sha256map inputMap nix-tools sourceRepoFixedProjectFile; in { sourceRepos = sourceReposBuild; inherit (repoResult) repos extra-hackages; makeFixedProjectFile = '' HOME=$(mktemp -d) - cp -f ${ - evalPackages.writeText "cabal.project" sourceRepoFixedProjectFile - } ./cabal.project + cp -f ${evalPackages.writeText "cabal.project" sourceRepoFixedProjectFile} ./cabal.project chmod +w -R ./cabal.project - '' + pkgs.lib.strings.concatStrings (map (f: '' - git config --global --add safe.directory ${f.location}/.git - '') sourceReposEval); + '' + pkgs.lib.strings.concatStrings ( + map (f: '' + git config --global --add safe.directory ${f.location}/.git + '') sourceReposEval + ); # This will be used to replace refernces to the minimal git repos with just the index # of the repo. The index will be used in lib/import-and-filter-project.nix to # lookup the correct repository in `sourceReposBuild`. This avoids having # `/nix/store` paths in the `plan-nix` output so that it can be materialized safely. - replaceLocations = pkgs.lib.strings.concatStrings - (pkgs.lib.lists.zipListsWith (n: f: '' - (cd $out${subDir'} - substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace file://${f.location} ${ - builtins.toString n - } - for a in $(grep -rl file://${f.location} .plan.nix/*.nix); do - substituteInPlace $a --replace file://${f.location} ${ - builtins.toString n - } - done) - '') (pkgs.lib.lists.range 0 ((builtins.length sourceReposEval) - 1)) - sourceReposEval); + replaceLocations = pkgs.lib.strings.concatStrings ( + pkgs.lib.lists.zipListsWith (n: f: '' + (cd $out${subDir'} + substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace file://${f.location} ${builtins.toString n} + for a in $(grep -rl file://${f.location} .plan.nix/*.nix); do + substituteInPlace $a --replace file://${f.location} ${builtins.toString n} + done) + '') + (pkgs.lib.lists.range 0 ((builtins.length sourceReposEval) - 1)) + sourceReposEval + ); }; fixedProject = replaceSourceRepos rawCabalProject; - platformString = p: - with p.parsed; - "${cpu.name}-${vendor.name}-${kernel.name}"; + ghcSrc = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; + + platformString = p: with p.parsed; "${cpu.name}-${vendor.name}-${kernel.name}"; # Dummy `ghc` that uses the captured output dummy-ghc = evalPackages.writeTextFile { @@ -363,46 +322,36 @@ let ;; ''} --supported-languages*) - cat ${ - import ./supported-languages.nix { inherit pkgs evalPackages ghc; } - } + cat ${import ./supported-languages.nix { inherit pkgs evalPackages ghc; }} ;; --print-global-package-db*) echo "$out/dumby-db" ;; --info*) echo '[("target os", "${ - if pkgs.stdenv.targetPlatform.isLinux then - "OSLinux" - else if pkgs.stdenv.targetPlatform.isDarwin then - "OSDarwin" - else if pkgs.stdenv.targetPlatform.isWindows then - "OSMinGW32" - else if pkgs.stdenv.targetPlatform.isGhcjs then - "OSGhcjs" - else - throw "Unknown target os ${pkgs.stdenv.targetPlatform.config}" - }")' + if pkgs.stdenv.targetPlatform.isLinux + then "OSLinux" + else if pkgs.stdenv.targetPlatform.isDarwin + then "OSDarwin" + else if pkgs.stdenv.targetPlatform.isWindows + then "OSMinGW32" + else if pkgs.stdenv.targetPlatform.isGhcjs + then "OSGhcjs" + else throw "Unknown target os ${pkgs.stdenv.targetPlatform.config}" + }")' echo ',("target arch","${ - if pkgs.stdenv.targetPlatform.isx86_64 then - "ArchX86_64" - else if pkgs.stdenv.targetPlatform.isAarch64 then - "ArchAArch64" - else if pkgs.stdenv.targetPlatform.isJavaScript then - "ArchJavaScript" - else - throw "Unknown target arch ${pkgs.stdenv.targetPlatform.config}" - }")' - echo ',("target platform string","${ - platformString pkgs.stdenv.targetPlatform - }")' - echo ',("Build platform","${ - platformString pkgs.stdenv.buildPlatform + if pkgs.stdenv.targetPlatform.isx86_64 + then "ArchX86_64" + else if pkgs.stdenv.targetPlatform.isAarch64 + then "ArchAArch64" + else if pkgs.stdenv.targetPlatform.isJavaScript + then "ArchJavaScript" + else throw "Unknown target arch ${pkgs.stdenv.targetPlatform.config}" }")' + echo ',("target platform string","${platformString pkgs.stdenv.targetPlatform}")' + echo ',("Build platform","${platformString pkgs.stdenv.buildPlatform}")' echo ',("Host platform","${platformString pkgs.stdenv.hostPlatform}")' - echo ',("Target platform","${ - platformString pkgs.stdenv.targetPlatform - }")' + echo ',("Target platform","${platformString pkgs.stdenv.targetPlatform}")' echo ']' ;; --print-libdir*) @@ -421,7 +370,7 @@ let ghc-src = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; ghc-version = ghc.version; }; - + # Dummy `ghc-pkg` that uses the captured output dummy-ghc-pkg = evalPackages.writeTextFile { name = "dummy-pkg-" + ghc.name; @@ -462,30 +411,23 @@ let }) (evalPackages.runCommand (nameAndSuffix "plan-to-nix-pkgs") { nativeBuildInputs = # The things needed from nix-tools - [ - nix-tools.exes.make-install-plan + [ nix-tools.exes.make-install-plan nix-tools.exes.plan-to-nix nix-tools.exes.cabal - ] ++ pkgs.lib.optional supportHpack nix-tools.exes.hpack ++ [ - dummy-ghc - dummy-ghc-pkg - evalPackages.rsync - evalPackages.gitMinimal - evalPackages.allPkgConfigWrapper - ]; + ] + ++ pkgs.lib.optional supportHpack nix-tools.exes.hpack + ++ [dummy-ghc dummy-ghc-pkg evalPackages.rsync evalPackages.gitMinimal evalPackages.allPkgConfigWrapper ]; # Needed or stack-to-nix will die on unicode inputs - LOCALE_ARCHIVE = pkgs.lib.optionalString - (evalPackages.stdenv.buildPlatform.libc == "glibc") - "${evalPackages.glibcLocales}/lib/locale/locale-archive"; + LOCALE_ARCHIVE = pkgs.lib.optionalString (evalPackages.stdenv.buildPlatform.libc == "glibc") "${evalPackages.glibcLocales}/lib/locale/locale-archive"; LANG = "en_US.UTF-8"; meta.platforms = pkgs.lib.platforms.all; preferLocalBuild = false; outputs = [ - "out" # The results of plan-to-nix + "out" # The results of plan-to-nix # These two output will be present if in cabal configure failed. # They are used to provide passthru.json and passthru.freeze that # check first for cabal configure failure. - "freeze" # The `cabal.project.freeze` file created by `cabal v2-freeze` + "freeze" # The `cabal.project.freeze` file created by `cabal v2-freeze` ]; } '' tmp=$(mktemp -d) @@ -496,11 +438,9 @@ let # message to prevent headaches (#290). if [ -z "$(ls -A ${cleanedSource})" ]; then echo "cleaned source is empty. Did you forget to 'git add -A'?" - ${ - pkgs.lib.optionalString (__length fixedProject.sourceRepos == 0) '' - exit 1 - '' - } + ${pkgs.lib.optionalString (__length fixedProject.sourceRepos == 0) '' + exit 1 + ''} else rsync -a ${cleanedSource}/ ./ fi @@ -518,10 +458,12 @@ let # hpack allows globbing, and turns that into module lists # without the source available (we cleanSourceWith'd it), # this may not produce the right result. - if supportHpack then '' + if supportHpack + then '' echo No .cabal file found, running hpack on $hpackFile hpack $hpackFile - '' else '' + '' + else '' echo "WARNING $hpackFile has no .cabal file and \`supportHpack\` was not set." '' } @@ -540,10 +482,10 @@ let export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt export CABAL_DIR=${ - # This creates `.cabal` directory that is as it would have - # been at the time `cached-index-state`. We may include - # some packages that will be excluded by `index-state-max` - # which is used by cabal (cached-index-state >= index-state-max). + # This creates `.cabal` directory that is as it would have + # been at the time `cached-index-state`. We may include + # some packages that will be excluded by `index-state-max` + # which is used by cabal (cached-index-state >= index-state-max). dotCabal { inherit nix-tools extra-hackage-tarballs; extra-hackage-repos = fixedProject.repos; @@ -553,23 +495,20 @@ let } make-install-plan ${ - # Setting the desired `index-state` here in case it is not - # in the cabal.project file. This will further restrict the - # packages used by the solver (cached-index-state >= index-state-max). - pkgs.lib.optionalString (index-state != null) - "--index-state=${index-state}" - } \ + # Setting the desired `index-state` here in case it is not + # in the cabal.project file. This will further restrict the + # packages used by the solver (cached-index-state >= index-state-max). + pkgs.lib.optionalString (index-state != null) "--index-state=${index-state}" + } \ -w ${ - # We are using `-w` rather than `--with-ghc` here to override - # the `with-compiler:` in the `cabal.project` file. - ghc.targetPrefix}ghc \ + # We are using `-w` rather than `--with-ghc` here to override + # the `with-compiler:` in the `cabal.project` file. + ghc.targetPrefix}ghc \ --with-ghc-pkg=${ghc.targetPrefix}ghc-pkg \ --enable-tests \ --enable-benchmarks \ - ${ - pkgs.lib.optionalString (ghc.targetPrefix == "js-unknown-ghcjs-") - "--ghcjs --with-ghcjs=js-unknown-ghcjs-ghc --with-ghcjs-pkg=js-unknown-ghcjs-ghc-pkg" - } \ + ${pkgs.lib.optionalString (ghc.targetPrefix == "js-unknown-ghcjs-") + "--ghcjs --with-ghcjs=js-unknown-ghcjs-ghc --with-ghcjs-pkg=js-unknown-ghcjs-ghc-pkg"} \ ${configureArgs} mkdir -p $out @@ -599,9 +538,7 @@ let # run `plan-to-nix` in $out. This should produce files right there with the # proper relative paths. - (cd $out${subDir'} && plan-to-nix --full ${ - if ignorePackageYaml then "--ignore-package-yaml" else "" - } --plan-json $tmp${subDir'}/dist-newstyle/cache/plan.json -o .) + (cd $out${subDir'} && plan-to-nix --full ${if ignorePackageYaml then "--ignore-package-yaml" else ""} --plan-json $tmp${subDir'}/dist-newstyle/cache/plan.json -o .) substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace "$out" "." substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace "$CABAL_DIR" "" diff --git a/lib/dummy-ghc-pkg-dump/configure.ac b/lib/dummy-ghc-pkg-dump/configure.ac index 35a5396783..d44712f3b6 100644 --- a/lib/dummy-ghc-pkg-dump/configure.ac +++ b/lib/dummy-ghc-pkg-dump/configure.ac @@ -1,4 +1,12 @@ -AC_INIT([The Glorious Glasgow Haskell Compilation System], [0.0.0], [glasgow-haskell-bugs@haskell.org]) +m4_include([fp_check_prog.m4]) +m4_include([fp_prog_find.m4]) +m4_include([fp_prog_sort.m4]) +m4_include([fp_setup_project_version.m4]) + +AC_INIT([The Glorious Glasgow Haskell Compilation System], + [0.0.0], + [glasgow-haskell-bugs@haskell.org], + [ghc]) # Set this to YES for a released version, otherwise NO : ${RELEASE=NO} @@ -6,12 +14,14 @@ AC_INIT([The Glorious Glasgow Haskell Compilation System], [0.0.0], [glasgow-has dnl ** Make sure we do not have a bogus source directory AC_CONFIG_SRCDIR(ghc/Main.hs) +dnl ---------------------------------------------------------- dnl ** Find unixy sort and find commands, dnl ** which are needed by FP_SETUP_PROJECT_VERSION + FP_PROG_FIND FP_PROG_SORT -dnl ** FP_SETUP_VERSION assumes to be in the source directory +dnl ---------------------------------------------------------- pushd ${srcdir} FP_SETUP_PROJECT_VERSION popd diff --git a/lib/dummy-ghc-pkg-dump/default.nix b/lib/dummy-ghc-pkg-dump/default.nix index cff708100b..b69109a7d7 100644 --- a/lib/dummy-ghc-pkg-dump/default.nix +++ b/lib/dummy-ghc-pkg-dump/default.nix @@ -1,305 +1,89 @@ -{ lib, stdenv, runCommand, autoconf, automake, coreutils, findutils, jq -, haskell-nix, ghc-version, ghc-src }: +{ + autoconf, + cabal2json, + coreutils, + findutils, + ghc-src, + ghc-version, + jq, + lib, + runCommand, + stdenv, +}: let - varname = builtins.replaceStrings [ "-" ] [ "_" ]; - - ghc-pkgs = [ - "Cabal" - "array" - "base" - "binary" - "bytestring" - "containers" - "deepseq" - "directory" - "filepath" - "ghc-boot" - "ghc-boot-th" - "ghc-compact" - "ghc-heap" - "ghc-prim" - "ghci" - "integer-gmp" - "mtl" - "parsec" - "pretty" - "process" - "rts" - "template-haskell" - "text" - "time" - "transformers" - ] ++ lib.optionals (!stdenv.targetPlatform.isGhcjs - || builtins.compareVersions ghc-version "9.0" > 0) [ - # GHCJS 8.10 does not have these - "Cabal-syntax" - "exceptions" - "file-io" - "ghc" - "ghc-bignum" - "ghc-experimental" - "ghc-internal" - "ghc-platform" - "ghc-toolchain" - "haskeline" - "hpc" - "libiserv" - "os-string" - "semaphore-compat" - "stm" - "xhtml" - ] ++ lib.optionals (!stdenv.targetPlatform.isGhcjs) [ "terminfo" ] - ++ (if stdenv.targetPlatform.isWindows then [ "Win32" ] else [ "unix" ]); - - configure = ghc-src: - let - ghc-m4-src = builtins.path { - filter = path: type: lib.hasPrefix "${ghc-src}/m4" path; - path = ghc-src; - name = "ghc-src-m4"; - }; - in runCommand "configure" { - nativeBuildInputs = [ autoconf automake coreutils findutils ]; - } '' - set -euo pipefail - - mkdir -p $out - cd $out - - cp -v ${./configure.ac} configure.ac - aclocal --verbose -I "${ghc-m4-src}/m4" - autoconf --verbose - ''; - - x = ghc-src: - let - ## GHC version - flags = (lib.optional stdenv.targetPlatform.isx86_64 "--arch x86_64") - ++ (lib.optional stdenv.targetPlatform.isAarch64 "--arch aarch64") - ++ (lib.optional stdenv.targetPlatform.isLinux "--os linux") - ++ (lib.optional stdenv.targetPlatform.isDarwin "--os osx") - ++ (lib.optional stdenv.targetPlatform.isGhcjs "--arch javascript"); - - in runCommand "x" { - nativeBuildInputs = [ - # FIXME: for testing - haskell-nix.nix-tools.exes.cabal2json - # haskell-nix.nix-tools-unchecked.exes.cabal2json - jq - ]; - } '' - set -euo pipefail - shopt -s globstar - - mkdir -p $out - cd $out - - # Run configure script (only for the project version) - ${configure ghc-src}/configure --srcdir=${ghc-src} - - # Copy the cabal.in files - pushd ${ghc-src} - cp --no-preserve all --parents */*.cabal */*.cabal.in libraries/*/*.cabal libraries/*/*.cabal.in "$out" - popd - - find - - # Substitute config variables in the cabal files - FILES=( **/*.cabal.in ) - ./config.status $(printf -- '--file %s ' ''${FILES[@]%.in}) - - FLAGS=(${lib.concatStringsSep " " flags}) - VERSION=$(cabal2json ghc/ghc-bin.cabal | jq .version) - FLAGS+=(--compiler ghc-$VERSION) - - # Convert to json - for f in **/*.cabal; do - # FIXME - if [[ $f == rts/rts.cabal ]]; then - continue - fi - cabal2json ${lib.concatStringsSep " " flags} --out="$f.json" "$f" - done - ''; - -in runCommand "dummy-ghc-pkg-dump" { - nativeBuildInputs = [ haskell-nix.nix-tools-unchecked.exes.cabal2json jq ]; - passthru = { inherit configure x; }; -} '' - PACKAGE_VERSION=${ghc-version} - ProjectVersion=${ghc-version} - - # The following logic is from GHC m4/setup_project_version.m4 - - # Split PACKAGE_VERSION into (possibly empty) parts - VERSION_MAJOR=`echo $PACKAGE_VERSION | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1'/` - VERSION_TMP=`echo $PACKAGE_VERSION | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3'/` - VERSION_MINOR=`echo $VERSION_TMP | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1'/` - ProjectPatchLevel=`echo $VERSION_TMP | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3'/` - - # Calculate project version as an integer, using 2 digits for minor version - case $VERSION_MINOR in - ?) ProjectVersionInt=''${VERSION_MAJOR}0''${VERSION_MINOR} ;; - ??) ProjectVersionInt=''${VERSION_MAJOR}''${VERSION_MINOR} ;; - *) echo bad minor version in $PACKAGE_VERSION; exit 1 ;; - esac - # AC_SUBST([ProjectVersionInt]) - - # The project patchlevel is zero unless stated otherwise - test -z "$ProjectPatchLevel" && ProjectPatchLevel=0 - - # AC_SUBST([ProjectPatchLevel1]) - # AC_SUBST([ProjectPatchLevel2]) - - # Remove dots from the patch level; this allows us to have versions like 6.4.1.20050508 - ProjectPatchLevel=`echo $ProjectPatchLevel | sed 's/\.//'` - - # AC_SUBST([ProjectPatchLevel]) - - # The version of the GHC package changes every day, since the - # patchlevel is the current date. We don't want to force - # recompilation of the entire compiler when this happens, so for - # GHC HEAD we omit the patchlevel from the package version number. - # - # The ProjectPatchLevel1 > 20000000 iff GHC HEAD. If it's for a stable - # release like 7.10.1 or for a release candidate such as 7.10.1.20141224 - # then we don't omit the patchlevel components. - - ProjectVersionMunged="$ProjectVersion" - if test "$ProjectPatchLevel1" -gt 20000000; then - ProjectVersionMunged="''${VERSION_MAJOR}.''${VERSION_MINOR}" - fi - # AC_SUBST([ProjectVersionMunged]) - - # The version used for libraries tightly coupled with GHC (e.g. - # ghc-internal) which need a major version bump for every minor/patchlevel - # GHC version. - # Example: for GHC=9.10.1, ProjectVersionForLib=9.1001 - # - # Just like with project version munged, we don't want to use the - # patchlevel version which changes every day, so if using GHC HEAD, the - # patchlevel = 00. - case $VERSION_MINOR in - ?) ProjectVersionForLibUpperHalf=''${VERSION_MAJOR}.0''${VERSION_MINOR} ;; - ??) ProjectVersionForLibUpperHalf=''${VERSION_MAJOR}.''${VERSION_MINOR} ;; - *) echo bad minor version in $PACKAGE_VERSION; exit 1 ;; - esac - - # Save split version of ProjectPatchLevel - ProjectPatchLevel1=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\1/'` - ProjectPatchLevel2=`echo $ProjectPatchLevel | sed 's/^\([^.]*\)\(\.\{0,1\}\(.*\)\)$/\3/'` - - # The project patchlevel1/2 is zero unless stated otherwise - test -z "$ProjectPatchLevel1" && ProjectPatchLevel1=0 - test -z "$ProjectPatchLevel2" && ProjectPatchLevel2=0 - - # GHC HEAD uses patch level version > 20000000 - case $ProjectPatchLevel1 in - ?) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}0''${ProjectPatchLevel1} ;; - ??) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}''${ProjectPatchLevel1} ;; - *) ProjectVersionForLib=''${ProjectVersionForLibUpperHalf}00 - esac - - PKGS="" - ${lib.concatStrings (builtins.map (name: '' - cabal_file="" - if [ -f ${ghc-src}/libraries/${name}/${name}.cabal ]; then - cabal_file=${ghc-src}/libraries/${name}/${name}.cabal - elif [ -f ${ghc-src}/libraries/Cabal/${name}/${name}.cabal ]; then - cabal_file=${ghc-src}/libraries/Cabal/${name}/${name}.cabal - elif [ -f ${ghc-src}/libraries/${name}/${name}/${name}.cabal ]; then - cabal_file=${ghc-src}/libraries/${name}/${name}/${name}.cabal - elif [ -f ${ghc-src}/compiler/${name}.cabal ]; then - cabal_file=${ghc-src}/compiler/${name}.cabal - elif [ -f ${ghc-src}/compiler/${name}.cabal.in ]; then - cabal_file=${ghc-src}/compiler/${name}.cabal.in - elif [ -f ${ghc-src}/libraries/${name}/${name}.cabal.in ]; then - cabal_file=${ghc-src}/libraries/${name}/${name}.cabal.in - fi - if [[ "$cabal_file" != "" ]]; then - fixed_cabal_file=$(mktemp) - cat $cabal_file | sed -e "s/@ProjectVersionMunged@/$ProjectVersionMunged/g" -e "s/@ProjectVersionForLib@/$ProjectVersionForLib/g" -e 's/default: *@[A-Za-z0-9]*@/default: False/g' -e 's/@Suffix@//g' > $fixed_cabal_file - json_cabal_file=$(mktemp) - cabal2json $fixed_cabal_file > $json_cabal_file - - exposed_modules="$(jq -r '.library."exposed-modules"[]|select(type=="array")[]' $json_cabal_file)" - reexported_modules="$(jq -r '.library."reexported-modules"//[]|.[]|select(type=="array")[]' $json_cabal_file)" - - # FIXME This is a bandaid. Rather than doing this, conditionals should be interpreted. - ${ - lib.optionalString stdenv.targetPlatform.isGhcjs '' - exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.arch == "javascript")|.then[]' $json_cabal_file)" - '' - } - ${ - lib.optionalString stdenv.targetPlatform.isWindows '' - exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.os == "windows")|.then[]' $json_cabal_file)" - '' + ghc-m4-src = builtins.path { + filter = path: type: lib.hasPrefix "${ghc-src}/m4" path; + path = ghc-src; + name = "ghc-src-m4"; + }; + + configure = + runCommand "dummy-ghc-configure" + { + nativeBuildInputs = [ + autoconf + coreutils + findutils + ]; } - ${ - lib.optionalString (!stdenv.targetPlatform.isWindows) '' - exposed_modules+=" $(jq -r '.library."exposed-modules"[]|select(type=="object" and .if.not.os == "windows")|.then[]' $json_cabal_file)" - '' + '' + set -euo pipefail + autoconf --warnings all --include "${ghc-m4-src}/m4" --output=$out ${./configure.ac} + ''; + + # cabal2json = builtins.fetchClosure { + # fromStore = "https://cache.zw3rk.com"; + # fromPath = /nix/store/q1kqwvqmwqcqaq82gaf951mq39v4sc91-Cabal-syntax-json-exe-cabal2json-0.1.0.0; + # }; + + cabal2json-flags = + with stdenv.targetPlatform; + lib.cli.toGNUCommandLineShell { } { + arch = + lib.optional isx86_64 "x86_64" + ++ lib.optional isAarch64 "aarch64" + ++ lib.optional isGhcjs "javascript"; + os = lib.optional isLinux "linux" ++ lib.optional isDarwin "osx"; + }; + + cabal-files = + runCommand "dummy-ghc-cabal-files" + { + nativeBuildInputs = [ cabal2json ]; } - - EXPOSED_MODULES_${ - varname name - }="$(tr '\n' ' ' <<< "$exposed_modules $reexported_modules")" - DEPS_${ - varname name - }="$(jq -r '.library."build-depends"[]|select(type=="array")[],select(type=="object" and .if.not.flag != "vendor-filepath").then[]' $json_cabal_file | sed 's/^\([A-Za-z0-9-]*\).*$/\1/g' | sort -u | tr '\n' ' ')" - VER_${varname name}="$(jq -r '.version' $json_cabal_file)" - PKGS+=" ${name}" - LAST_PKG="${name}" - fi - '') ghc-pkgs)} - - ${ # There is no .cabal file for system-cxx-std-lib - lib.optionalString (builtins.compareVersions ghc-version "9.2" >= 0) - (let name = "system-cxx-std-lib"; - in '' - EXPOSED_MODULES_${varname name}="" - DEPS_${varname name}="" - VER_${varname name}="1.0" - PKGS+=" ${name}" - LAST_PKG="${name}" - '') - # ghcjs packages (before the ghc JS backend). TODO remove this when GHC 8.10 support is dropped - + lib.optionalString (stdenv.targetPlatform.isGhcjs - && builtins.compareVersions ghc-version "9" < 0) '' - EXPOSED_MODULES_${ - varname "ghcjs-prim" - }="GHCJS.Prim GHCJS.Prim.Internal GHCJS.Prim.Internal.Build" - DEPS_${varname "ghcjs-prim"}="base ghc-prim" - VER_${varname "ghcjs-prim"}="0.1.1.0" - EXPOSED_MODULES_${ - varname "ghcjs-th" - }="GHCJS.Prim.TH.Eval GHCJS.Prim.TH.Types" - DEPS_${ - varname "ghcjs-th" - }="base binary bytestring containers ghc-prim ghci template-haskell" - VER_${varname "ghcjs-th"}="0.1.0.0" - PKGS+=" ghcjs-prim ghcjs-th" - LAST_PKG="ghcjs-th" - ''} - for pkg in $PKGS; do - varname="$(echo $pkg | tr "-" "_")" - ver="VER_$varname" - exposed_mods="EXPOSED_MODULES_$varname" - deps="DEPS_$varname" - echo "name: $pkg" >> $out - echo "version: ''${!ver}" >> $out - echo "exposed-modules: ''${!exposed_mods}" >> $out - echo "depends:" >> $out - for dep in ''${!deps}; do - ver_dep="VER_$(echo $dep | tr "-" "_")" - if [[ "''${!ver_dep}" != "" ]]; then - echo " $dep-''${!ver_dep}" >> $out - fi - done - if [[ "$pkg" != "$LAST_PKG" ]]; then - echo '---' >> $out - fi - done + '' + set -euo pipefail + shopt -s globstar + + mkdir -p $out + cd $out + + # Run configure script (only for the project version) + ${configure} --srcdir=${ghc-src} PACKAGE_VERSION=${ghc-version} + + # Copy the cabal.in files + pushd ${ghc-src} + cp --no-preserve all --parents */*.cabal */*.cabal.in libraries/*/*.cabal libraries/*/*.cabal.in "$out" + popd + + # Substitute config variables in the cabal files + FILES=( **/*.cabal.in ) + ./config.status $(printf -- '--file %s ' "''${FILES[@]%.in}") + + # Convert to json + for f in **/*.cabal; do + # FIXME + if [[ $f == rts/rts.cabal ]]; then + continue + fi + cabal2json ${cabal2json-flags} --compiler ghc-${ghc-version} --out="$f.json" "$f" + done + ''; + +in +runCommand "dummy-ghc-pkg-dump" { } '' + set -eo pipefail + shopt -s globstar + ${lib.getExe jq} --null-input --raw-output --from-file ${./script.jq} ${cabal-files}/**/*.cabal.json >$out '' diff --git a/lib/dummy-ghc-pkg-dump/script.jq b/lib/dummy-ghc-pkg-dump/script.jq new file mode 100644 index 0000000000..f88f9e4bd5 --- /dev/null +++ b/lib/dummy-ghc-pkg-dump/script.jq @@ -0,0 +1,33 @@ +def pkg_id: + "\(.name)-\(.version)" + ; + +def build_depends($inputs): + ."build-depends" | map(.package | strings | $inputs[.] | pkg_id) | join(" ") + ; + +def exposed_modules: + ."exposed-modules" + | map(strings) + | join(" ") + ; + +[ inputs | { key: "\(.name)", value: . } ] +| from_entries as $inputs + +| $inputs +| map( + .name as $name + | .version as $version + | .components + | to_entries + | map( + # only libraries + select(.key | startswith("lib")) + | .value + | "name: \($name)" + , "version: \($version)" + , "exposed-modules: \(exposed_modules)" + , "build-depends: \(build_depends($inputs))" + ) | join("\n") +) | join("\n---\n") diff --git a/nix-tools/flake.nix b/nix-tools/flake.nix index 1aba66988c..ea3eb9c1c1 100644 --- a/nix-tools/flake.nix +++ b/nix-tools/flake.nix @@ -4,15 +4,10 @@ haskellNix.url = "github:input-output-hk/haskell.nix"; }; - outputs = inputs@{ self, nixpkgs, haskellNix, ... }: let - systems = [ - "x86_64-linux" - "x86_64-darwin" - "aarch64-linux" - "aarch64-darwin" - ]; + systems = + [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; inherit (nixpkgs) lib; @@ -23,31 +18,30 @@ mkTarball = pkgs: let - toolset = - let pkgs' = pkgs.extend self.overlays.default; in + toolset = let + pkgs' = pkgs.extend self.overlays.default; # We need to use haskell.nix compilers here - pkgs'.nix-tools-set { compilerSelection = lib.mkForce (p: p.haskell-nix.compiler); }; + in pkgs'.nix-tools-set { + compilerSelection = lib.mkForce (p: p.haskell-nix.compiler); + }; # tarball filename e.g. nix-tools-0.1.0.0-x86_64-unknown-linux-musl.tar.gz - tarball-filename = "${toolset.name}-${pkgs.hostPlatform.config}.tar.gz"; - in - pkgs.runCommand tarball-filename - { preferLocalBuild = true; } - '' - mkdir -p ${toolset.name}/bin - cp --verbose --target-directory ${toolset.name}/bin ${toolset}/bin/* - - mkdir -p $out - tar cvzf $out/${tarball-filename} ${toolset.name} - - mkdir -p $out/nix-support - echo "file binary-dist $out/${tarball-filename}" >> $out/nix-support/hydra-build-products - ''; - + tarball-filename = + "${toolset.name}-${pkgs.hostPlatform.config}.tar.gz"; + in pkgs.runCommand tarball-filename { preferLocalBuild = true; } '' + mkdir -p ${toolset.name}/bin + cp --verbose --target-directory ${toolset.name}/bin ${toolset}/bin/* + + mkdir -p $out + tar cvzf $out/${tarball-filename} ${toolset.name} + + mkdir -p $out/nix-support + echo "file binary-dist $out/${tarball-filename}" >> $out/nix-support/hydra-build-products + ''; + static-nix-tools-outputs = import ./static/outputs.nix inputs; - - in { + in { inherit static-nix-tools-outputs; # this is not per-system! @@ -56,46 +50,43 @@ legacyPackages = forAllSystems (pkgs: pkgs); lib = { - nix-tools = system: (haskellNix.legacyPackages.${system}.extend self.overlays.default).nix-tools; - haskell-nix = system: (haskellNix.legacyPackages.${system}.extend self.overlays.default).haskell-nix; + nix-tools = system: + (haskellNix.legacyPackages.${system}.extend + self.overlays.default).nix-tools; + haskell-nix = system: + (haskellNix.legacyPackages.${system}.extend + self.overlays.default).haskell-nix; }; project = forAllSystems (pkgs: pkgs.nix-tools.project); - packages = forAllSystems (pkgs: - lib.mapAttrs' - (_n: v: { name = v.exeName; value = v; }) - pkgs.nix-tools.project.flake'.packages); + packages = forAllSystems (pkgs: pkgs.nix-tools.exes); checks = forAllSystems (pkgs: pkgs.nix-tools.project.flake'.checks // { truncate-index = import ./tests/truncate-index.nix { inherit pkgs; }; }); - devShells = forAllSystems (pkgs: - { default = pkgs.nix-tools.project.shell; }); - - hydraJobs = forAllSystems - (pkgs: - # project's hydraJobs - pkgs.nix-tools.project.flake'.hydraJobs - # tarballs with static builds. - // lib.optionalAttrs (pkgs.buildPlatform.system == "x86_64-linux") - { binary-tarball = mkTarball pkgs.pkgsCross.musl64; } - # aarch64-multiplatform-musl cross compile is currently broken - # // lib.optionalAttrs (pkgs.buildPlatform.system == "aarch64-linux") - # { binary-tarball = mkTarball pkgs.pkgsCross.aarch64-multiplatform-musl; } - // { - static = static-nix-tools-outputs.hydraJobs.${pkgs.system}; - } - ); + devShells = + forAllSystems (pkgs: { default = pkgs.nix-tools.project.shell; }); + + hydraJobs = forAllSystems (pkgs: + # project's hydraJobs + pkgs.nix-tools.project.flake'.hydraJobs + # tarballs with static builds. + // lib.optionalAttrs (pkgs.buildPlatform.system == "x86_64-linux") { + binary-tarball = mkTarball pkgs.pkgsCross.musl64; + } + # aarch64-multiplatform-musl cross compile is currently broken + # // lib.optionalAttrs (pkgs.buildPlatform.system == "aarch64-linux") + # { binary-tarball = mkTarball pkgs.pkgsCross.aarch64-multiplatform-musl; } + // { + static = static-nix-tools-outputs.hydraJobs.${pkgs.system}; + }); }; nixConfig = { - extra-substituters = [ - "https://cache.iog.io" - "https://cache.zw3rk.com" - ]; + extra-substituters = [ "https://cache.iog.io" "https://cache.zw3rk.com" ]; extra-trusted-public-keys = [ "hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ=" "loony-tools:pr9m4BkM/5/eSTZlkQyRt57Jz7OMBxNSUiMC4FkcNfk=" diff --git a/nix-tools/overlay.nix b/nix-tools/overlay.nix index 6035cda448..f76e04a8cf 100644 --- a/nix-tools/overlay.nix +++ b/nix-tools/overlay.nix @@ -61,14 +61,13 @@ let warning = final.lib.mapAttrs (_: _: - final.lib.warn + abort '' The package nix-tools is now compiled with a single GHC version. You can use the function nix-tools-set to compile nix-tools using a specific compiler: nix-tools-set { compiler-nix-name = " "ghcXYZ" "; } '' - toolset ) final.haskell-nix.compiler; diff --git a/overlays/haskell.nix b/overlays/haskell.nix index e6d1c4b8e9..a65a1a7ae4 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -13,6 +13,7 @@ final: prev: { # Additional user-provided mappings to augment ./../lib/pkgconf-nixpkgs-map.nix extraPkgconfigMappings = prev.haskell-nix.extraPkgconfigMappings or {}; + # Nix Flake based source pins. # To update all inputs, get unstable Nix and then `nix flake update --recreate-lock-file` # Or `nix-shell -p nixVersions.latest --run "nix --experimental-features 'nix-command flakes' flake update --recreate-lock-file"` @@ -596,29 +597,29 @@ final: prev: { dummy-ghc-pkg-dump = final.callPackage ../lib/dummy-ghc-pkg-dump { # FIXME: just for testing - ghc-version = "0.0.0"; + ghc-version = final.ghc.version; ghc-src = final.ghc.src; }; # Takes a haskell src directory runs cabal new-configure and plan-to-nix. # Resulting nix files are added to nix-plan subdirectory. callCabalProjectToNix = import ../lib/call-cabal-project-to-nix.nix { - pkgs = final.buildPackages.pkgs; index-state-hashes = import indexStateHashesPath; inherit (final.buildPackages.haskell-nix) haskellLib; + pkgs = final.buildPackages.pkgs; inherit (final.buildPackages.pkgs) cacert; }; # Loads a plan and filters the package directories using cleanSourceWith importAndFilterProject = import ../lib/import-and-filter-project.nix { - pkgs = final.buildPackages.pkgs; inherit (final.buildPackages.haskell-nix) haskellLib; + pkgs = final.buildPackages.pkgs; }; # Loads a plan and filters the package directories using cleanSourceWith loadCabalPlan = import ../lib/load-cabal-plan.nix { - pkgs = final.buildPackages.pkgs; inherit (final.buildPackages.haskell-nix) haskellLib; + pkgs = final.buildPackages.pkgs; }; # References to the unpacked sources, for caching in a Hydra jobset. From d1b183fc3781b3a32798ccf07699eb288654a2a2 Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Mon, 16 Dec 2024 15:08:06 +0800 Subject: [PATCH 14/16] refactor: nix-tools/flake.nix --- nix-tools/flake.nix | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/nix-tools/flake.nix b/nix-tools/flake.nix index ea3eb9c1c1..f7485852b8 100644 --- a/nix-tools/flake.nix +++ b/nix-tools/flake.nix @@ -1,33 +1,36 @@ { inputs = { - nixpkgs.follows = "haskellNix/nixpkgs"; haskellNix.url = "github:input-output-hk/haskell.nix"; }; - outputs = inputs@{ self, nixpkgs, haskellNix, ... }: + outputs = inputs@{ self, haskellNix, ... }: let systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; - inherit (nixpkgs) lib; + inherit (haskellNix) lib; # keep it simple (from https://ayats.org/blog/no-flake-utils/) forAllSystems = f: - nixpkgs.lib.genAttrs systems (system: - f (haskellNix.legacyPackages.${system}.extend self.overlays.default)); + lib.genAttrs systems (system: + let + # NOTE: this instantiation of nixpkgs already includes haskell.nix + # configuration and overlays. + pkgs = haskellNix.legacyPackages.${system}; + # Here we add our own overlay + in f (pkgs.extend self.overlays.default)); mkTarball = pkgs: let - toolset = let - pkgs' = pkgs.extend self.overlays.default; - # We need to use haskell.nix compilers here - in pkgs'.nix-tools-set { + # We need to use haskell.nix compilers here + toolset = pkgs.nix-tools-set { compilerSelection = lib.mkForce (p: p.haskell-nix.compiler); }; # tarball filename e.g. nix-tools-0.1.0.0-x86_64-unknown-linux-musl.tar.gz tarball-filename = "${toolset.name}-${pkgs.hostPlatform.config}.tar.gz"; + in pkgs.runCommand tarball-filename { preferLocalBuild = true; } '' mkdir -p ${toolset.name}/bin cp --verbose --target-directory ${toolset.name}/bin ${toolset}/bin/* From a90525a94111b4109d9ca78075baf3b74d48c0d1 Mon Sep 17 00:00:00 2001 From: Auto Update Bot <no-reply@iohk.io> Date: Thu, 12 Dec 2024 09:30:18 +0000 Subject: [PATCH 15/16] update nix-tools-static.nix --- nix-tools-static.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nix-tools-static.nix b/nix-tools-static.nix index 9ab307a25f..9f482e67bf 100644 --- a/nix-tools-static.nix +++ b/nix-tools-static.nix @@ -1,22 +1,22 @@ -pkgs: let baseurl = "https://github.com/input-output-hk/haskell.nix/releases/download/nix-tools-0.2.6/"; in { +pkgs: let baseurl = "https://github.com/input-output-hk/haskell.nix/releases/download/nix-tools-0.2.9/"; in { aarch64-darwin = pkgs.fetchurl { name = "aarch64-darwin-nix-tools-static"; url = "${baseurl}aarch64-darwin-nix-tools-static.zip"; - sha256 = "sha256-9WpTIWlpUvG3pI+tcbAMh6sMH0QO/coZrxDYWD43iq0="; + sha256 = "sha256-cXfdL4jgKYetMoOkNAis6dj7Fyy1llxNgKQtRJTwjhQ="; }; x86_64-darwin = pkgs.fetchurl { name = "x86_64-darwin-nix-tools-static"; url = "${baseurl}x86_64-darwin-nix-tools-static.zip"; - sha256 = "sha256-UUr9bo2OpLPsvHRSeO2B6DKVDVTsHepRlTqN6UZoZ2M="; + sha256 = "sha256-D4Dpiigr2IfsSIFqVEt1syBVCQbPdP7bX5fnhFCGZe0="; }; aarch64-linux = pkgs.fetchurl { name = "aarch64-linux-nix-tools-static"; url = "${baseurl}aarch64-linux-nix-tools-static.zip"; - sha256 = "sha256-96s6RXN8st0JK0eYSOkTJvnlTxYVdE81+ZUGJEsC46A="; + sha256 = "sha256-nVaz5VXhB5ZBT46FucisZCRrE+B1MlONO+4CEWKpwPY="; }; x86_64-linux = pkgs.fetchurl { name = "x86_64-linux-nix-tools-static"; url = "${baseurl}x86_64-linux-nix-tools-static.zip"; - sha256 = "sha256-LMFVUKNycjVFBb3ChZsPbRNgab50zOHl7nMBrDdeTrQ="; + sha256 = "sha256-W0ZCDTV800dhMY/HgAeiyWnCW7f1kqFadYo6R6GadqI="; }; } From 60afd88ebcb1d9febee41b4237ed89060e96cec8 Mon Sep 17 00:00:00 2001 From: Andrea Bedini <andrea.bedini@tweag.io> Date: Mon, 16 Dec 2024 17:36:55 +0800 Subject: [PATCH 16/16] WIP --- lib/call-cabal-project-to-nix.nix | 27 ++++++++----- lib/dummy-ghc-pkg-dump/configure.ac | 32 --------------- lib/dummy-ghc-pkg-dump/default.nix | 60 ++++++++++++++++++++++------- overlays/haskell.nix | 17 ++++---- 4 files changed, 71 insertions(+), 65 deletions(-) delete mode 100644 lib/dummy-ghc-pkg-dump/configure.ac diff --git a/lib/call-cabal-project-to-nix.nix b/lib/call-cabal-project-to-nix.nix index e585772bbf..2f25f3ec4e 100644 --- a/lib/call-cabal-project-to-nix.nix +++ b/lib/call-cabal-project-to-nix.nix @@ -1,4 +1,12 @@ -{ pkgs, runCommand, cacert, index-state-hashes, haskellLib }: +{ pkgs +, cacert +, index-state-hashes +, haskell-nix +}: + +let inherit (haskell-nix) haskellLib; +in + { name ? src.name or null # optional name for better error messages , src , materialized-dir ? ../materialized @@ -65,7 +73,7 @@ , ... }@args: let - inherit (evalPackages.haskell-nix) materialize dotCabal; + inherit (evalPackages.haskell-nix) dummy-ghc-pkg-dump materialize dotCabal; # These defaults are here rather than in modules/cabal-project.nix to make them # lazy enough to avoid infinite recursion issues. @@ -102,6 +110,7 @@ in let ghc = if ghc' ? latestVersion then __trace "WARNING: ${ghc'.version} is out of date, consider using upgrading to ${ghc'.latestVersion}." ghc' else ghc'; + subDir' = src.origSubDir or ""; subDir = pkgs.lib.strings.removePrefix "/" subDir'; @@ -295,8 +304,6 @@ let fixedProject = replaceSourceRepos rawCabalProject; - ghcSrc = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; - platformString = p: with p.parsed; "${cpu.name}-${vendor.name}-${kernel.name}"; # Dummy `ghc` that uses the captured output @@ -366,11 +373,6 @@ let ''; }; - dummy-ghc-pkg-dump = evalPackages.callPackage ./dummy-ghc-pkg-dump { - ghc-src = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; - ghc-version = ghc.version; - }; - # Dummy `ghc-pkg` that uses the captured output dummy-ghc-pkg = evalPackages.writeTextFile { name = "dummy-pkg-" + ghc.name; @@ -388,7 +390,12 @@ let ;; ''} 'dump --global -v0') - cat ${dummy-ghc-pkg-dump} + cat ${ + dummy-ghc-pkg-dump { + ghc-src = (ghc.raw-src or ghc.buildGHC.raw-src) evalPackages; + ghc-version = ghc.version; + } + } ;; *) echo "Unknown argument '$*'. " >&2 diff --git a/lib/dummy-ghc-pkg-dump/configure.ac b/lib/dummy-ghc-pkg-dump/configure.ac deleted file mode 100644 index d44712f3b6..0000000000 --- a/lib/dummy-ghc-pkg-dump/configure.ac +++ /dev/null @@ -1,32 +0,0 @@ -m4_include([fp_check_prog.m4]) -m4_include([fp_prog_find.m4]) -m4_include([fp_prog_sort.m4]) -m4_include([fp_setup_project_version.m4]) - -AC_INIT([The Glorious Glasgow Haskell Compilation System], - [0.0.0], - [glasgow-haskell-bugs@haskell.org], - [ghc]) - -# Set this to YES for a released version, otherwise NO -: ${RELEASE=NO} - -dnl ** Make sure we do not have a bogus source directory -AC_CONFIG_SRCDIR(ghc/Main.hs) - -dnl ---------------------------------------------------------- -dnl ** Find unixy sort and find commands, -dnl ** which are needed by FP_SETUP_PROJECT_VERSION - -FP_PROG_FIND -FP_PROG_SORT - -dnl ---------------------------------------------------------- -pushd ${srcdir} -FP_SETUP_PROJECT_VERSION -popd - -dnl ** Output code to perform substitutions -AC_CONFIG_FILES - -AC_OUTPUT diff --git a/lib/dummy-ghc-pkg-dump/default.nix b/lib/dummy-ghc-pkg-dump/default.nix index b69109a7d7..e556443527 100644 --- a/lib/dummy-ghc-pkg-dump/default.nix +++ b/lib/dummy-ghc-pkg-dump/default.nix @@ -1,16 +1,21 @@ { autoconf, - cabal2json, coreutils, findutils, - ghc-src, - ghc-version, + haskell-nix, jq, lib, runCommand, stdenv, + writeText, }: +let + inherit (haskell-nix.nix-tools-unchecked.exes) cabal2json; +in + +{ ghc-src, ghc-version }: + let ghc-m4-src = builtins.path { filter = path: type: lib.hasPrefix "${ghc-src}/m4" path; @@ -18,6 +23,41 @@ let name = "ghc-src-m4"; }; + configure-ac = writeText "configure.ac" '' + m4_include([fp_check_prog.m4]) + m4_include([fp_prog_find.m4]) + m4_include([fp_prog_sort.m4]) + m4_include([fp_setup_project_version.m4]) + + AC_INIT([The Glorious Glasgow Haskell Compilation System], + [${ghc-version}], + [glasgow-haskell-bugs@haskell.org], + [ghc]) + + # Set this to YES for a released version, otherwise NO + : ''${RELEASE=NO} + + dnl ** Make sure we do not have a bogus source directory + AC_CONFIG_SRCDIR(ghc/Main.hs) + + dnl ---------------------------------------------------------- + dnl ** Find unixy sort and find commands, + dnl ** which are needed by FP_SETUP_PROJECT_VERSION + + FP_PROG_FIND + FP_PROG_SORT + + dnl ---------------------------------------------------------- + pushd ''${srcdir} + FP_SETUP_PROJECT_VERSION + popd + + dnl ** Output code to perform substitutions + AC_CONFIG_FILES + + AC_OUTPUT + ''; + configure = runCommand "dummy-ghc-configure" { @@ -28,15 +68,9 @@ let ]; } '' - set -euo pipefail - autoconf --warnings all --include "${ghc-m4-src}/m4" --output=$out ${./configure.ac} + autoconf --warnings all --include "${ghc-m4-src}/m4" --output=$out ${configure-ac} ''; - # cabal2json = builtins.fetchClosure { - # fromStore = "https://cache.zw3rk.com"; - # fromPath = /nix/store/q1kqwvqmwqcqaq82gaf951mq39v4sc91-Cabal-syntax-json-exe-cabal2json-0.1.0.0; - # }; - cabal2json-flags = with stdenv.targetPlatform; lib.cli.toGNUCommandLineShell { } { @@ -60,7 +94,7 @@ let cd $out # Run configure script (only for the project version) - ${configure} --srcdir=${ghc-src} PACKAGE_VERSION=${ghc-version} + ${configure} --srcdir=${ghc-src} # Copy the cabal.in files pushd ${ghc-src} @@ -68,8 +102,8 @@ let popd # Substitute config variables in the cabal files - FILES=( **/*.cabal.in ) - ./config.status $(printf -- '--file %s ' "''${FILES[@]%.in}") + CABAL_IN=( **/*.cabal.in ) + ./config.status $(printf -- '--file %s ' "''${CABAL_IN[@]%.in}") # Convert to json for f in **/*.cabal; do diff --git a/overlays/haskell.nix b/overlays/haskell.nix index a65a1a7ae4..bfc5c1beec 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -167,7 +167,11 @@ final: prev: { }; # Package sets for all stackage snapshots. - snapshots = import ../snapshots.nix { inherit (final) lib ghc-boot-packages; inherit mkPkgSet stackage excludeBootPackages; }; + snapshots = import ../snapshots.nix { + inherit (final) lib ghc-boot-packages; + inherit mkPkgSet stackage excludeBootPackages; + }; + # Pick a recent LTS snapshot to be our "default" package set. haskellPackages = if final.stdenv.targetPlatform.isAarch64 && final.stdenv.buildPlatform.isAarch64 @@ -595,19 +599,12 @@ final: prev: { }; - dummy-ghc-pkg-dump = final.callPackage ../lib/dummy-ghc-pkg-dump { - # FIXME: just for testing - ghc-version = final.ghc.version; - ghc-src = final.ghc.src; - }; + dummy-ghc-pkg-dump = final.callPackage ../lib/dummy-ghc-pkg-dump { }; # Takes a haskell src directory runs cabal new-configure and plan-to-nix. # Resulting nix files are added to nix-plan subdirectory. - callCabalProjectToNix = import ../lib/call-cabal-project-to-nix.nix { + callCabalProjectToNix = final.buildPackages.callPackage ../lib/call-cabal-project-to-nix.nix { index-state-hashes = import indexStateHashesPath; - inherit (final.buildPackages.haskell-nix) haskellLib; - pkgs = final.buildPackages.pkgs; - inherit (final.buildPackages.pkgs) cacert; }; # Loads a plan and filters the package directories using cleanSourceWith