From bfc0f7fcf4757ddd48acd5f745f26f8d1c7c3b17 Mon Sep 17 00:00:00 2001 From: brandon s allbery kf8nh Date: Wed, 18 Mar 2026 21:53:16 -0400 Subject: [PATCH] clean up bootstrap JSON generation The primary entrypoint is now `make bootstrap-jsons`, which is now documented and called out in `bootstrap/README.md`. It automatically tries to obtain ghc versions from first `ghcup`, falls back to Nix if `nix-shell` is found, and if all else fails warns the user to install the appropriate ghcs. The Nix script can still be used directly, but now obtains the list of ghc versions from the `Makefile`. --- .github/workflows/bootstrap.yml | 2 +- Makefile | 68 ++++++++++++++----- bootstrap/README.md | 19 ++---- bootstrap/cabal-bootstrap-gen.cabal | 9 +-- bootstrap/generate_bootstrap_plans | 26 ++++--- .../{linux-9.10.2.json => linux-9.10.3.json} | 12 ++-- 6 files changed, 85 insertions(+), 51 deletions(-) rename bootstrap/{linux-9.10.2.json => linux-9.10.3.json} (98%) diff --git a/.github/workflows/bootstrap.yml b/.github/workflows/bootstrap.yml index 5527e3ea4c8..dfbe06f2ff7 100644 --- a/.github/workflows/bootstrap.yml +++ b/.github/workflows/bootstrap.yml @@ -19,7 +19,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - ghc: ["9.2.8", "9.4.8", "9.6.7", "9.8.4", "9.10.2", "9.12.2"] + ghc: ["9.2.8", "9.4.8", "9.6.7", "9.8.4", "9.10.3", "9.12.2"] include: - os: macos-latest ghc: "9.2.8" diff --git a/Makefile b/Makefile index 9b0cae9f668..4bc65bb74f8 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ FORMAT_DIRS_TODO := \ solver-benchmarks .PHONY: style-todo -style-todo: ## Configured for fourmolu, avoiding GHC parser failures +style-todo: ## Configured for fourmolu, avoiding GHC parser failures. @fourmolu -q $(FORMAT_DIRS_TODO) > /dev/null .PHONY: style @@ -85,7 +85,7 @@ lint-json: ## Run HLint in JSON mode. # local checks .PHONY: checks -checks: whitespace users-guide-typos markdown-typos style lint-json ## Run all local checks; whitespace, typos, style, and lint. +checks: whitespace users-guide-typos markdown-typos style lint-json ## Run all local checks: whitespace, typos, style, and lint. # source generation: SPDX @@ -265,17 +265,53 @@ tags: ## Generate editor tags, vim ctags and emacs etags. # bootstrapping ############################################################################## +BOOT_GHCUP := $(shell ghcup --version 2>/dev/null) +BOOT_NIX := $(shell nix-shell --version 2>/dev/null) +CABALCONF := $(shell if test -f $$HOME/.config/cabal/config; then echo CABAL_CONFIG=$$HOME/.config/cabal/config; fi) + bootstrap-json-%: phony - cabal build --project-file=cabal.bootstrap.project --with-compiler=ghc-$* --dry-run cabal-install:exe:cabal - cp dist-newstyle/cache/plan.json bootstrap/linux-$*.plan.json + ghcup install ghc "$*" --no-verbose --no-guess-version + $(MAKE) "bootstrap-subr-$*" + +# "subroutine", make style +bootstrap-subr-%: phony + rm -rf dist-bootstrap + $(CABALBUILD) --distdir=dist-bootstrap --project-file=cabal.bootstrap.project --with-compiler=ghc-$* --dry-run \ + cabal-install:exe:cabal + cp dist-bootstrap/cache/plan.json bootstrap/linux-$*.plan.json @# -v0 to avoid build output on stdout - cd bootstrap && cabal run -v0 cabal-bootstrap-gen -- linux-$*.plan.json \ + cd bootstrap && $(CABALCONF) $(CABALRUN) -v0 cabal-bootstrap-gen -- linux-$*.plan.json \ | python3 -m json.tool > linux-$*.json -BOOTSTRAP_GHC_VERSIONS := 9.2.8 9.4.8 9.6.7 9.8.4 9.10.2 9.12.2 +BOOTSTRAP_GHC_VERSIONS := 9.2.8 9.4.8 9.6.7 9.8.4 9.10.3 9.12.2 .PHONY: bootstrap-jsons -bootstrap-jsons: $(BOOTSTRAP_GHC_VERSIONS:%=bootstrap-json-%) +bootstrap-jsons: ## Generate bootstrap JSONs for Linux (autodetects method). +ifeq ($(BOOT_GHCUP), ) +ifeq ($(BOOT_NIX), ) + @echo If you do not have ghcs $(BOOTSTRAP_GHC_VERSIONS), you will need to install them manually. + $(MAKE) bootstrap-jsons-no-dl +else + $(MAKE) bootstrap-jsons-nix +endif +else + $(MAKE) bootstrap-jsons-ghcup +endif + +.PHONY: bootstrap-jsons-no-dl +bootstrap-jsons-no-dl: $(BOOTSTRAP_GHC_VERSIONS:%=bootstrap-subr-%) ## Generate bootstrap JSONs for Linux using existing ghcs. + +.PHONY: bootstrap-jsons-nix +bootstrap-jsons-nix: ## Generate bootstrap JSONs for Linux using Nix-provided ghcs. + cd ./bootstrap && $(CABALCONF) ./generate_bootstrap_plans + +.PHONY: bootstrap-jsons-ghcup +bootstrap-jsons-ghcup: $(BOOTSTRAP_GHC_VERSIONS:%=bootstrap-json-%) ## Generate bootstrap JSONs for Linux using ghcup. + +# this lets the Nix bootstrap script use the Makefile's definitions instead of hardcoding them itself +.PHONY: bootstrap-jsons-nix-helper +bootstrap-jsons-nix-helper: + @echo "$(BOOTSTRAP_GHC_VERSIONS)" # documentation ############################################################################## @@ -290,12 +326,12 @@ else PROCS := $(shell nproc) endif -PHONY: help +.PHONY: help help: ## Show the commented targets. @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' -PHONY: help-banner +.PHONY: help-banner help-banner: ## Show the help banner. @echo "====================================================================" @echo "ยง all make with no arguments also shows this banner" @@ -303,32 +339,32 @@ help-banner: ## Show the help banner. @echo "====================================================================" .PHONY: typos-install -typos-install: ## Install typos-cli for typos target using cargo +typos-install: ## Install typos-cli for typos target using cargo. cargo install typos-cli GREP_EXCLUDE := grep -v -E 'dist-|cabal-testsuite|python-' FIND_NAMED := find . -type f -name .PHONY: hs-typos -hs-typos: ## Find typos in Haskell source files; .hs, .cabal, etc. +hs-typos: ## Find typos in Haskell source files: .hs, .cabal, etc. typos --config .typos-srcs.toml --force-exclude .PHONY: hs-fix-typos -hs-fix-typos: ## Fix typos in Haskell source files; .hs, .cabal, etc. +hs-fix-typos: ## Fix typos in Haskell source files: .hs, .cabal, etc. typos --config .typos-srcs.toml --write-changes --force-exclude .PHONY: users-guide-typos -users-guide-typos: ## Find typos in users guide +users-guide-typos: ## Find typos in users guide. cd doc && $(FIND_NAMED) '*.rst' | xargs typos --config ../.typos-docs.toml --force-exclude .PHONY: users-guide-fix-typos -users-guide-fix-typos: ## Fix typos in users guide +users-guide-fix-typos: ## Fix typos in users guide. cd doc && $(FIND_NAMED) '*.rst' | xargs typos --config ../.typos-docs.toml --write-changes --force-exclude .PHONY: markdown-typos -markdown-typos: ## Find typos in markdown files +markdown-typos: ## Find typos in markdown files. $(FIND_NAMED) '*.md' | $(GREP_EXCLUDE) | xargs typos --config .typos-docs.toml --force-exclude .PHONY: markdown-fix-typos -markdown-fix-typos: ## Fix typos in markdown files +markdown-fix-typos: ## Fix typos in markdown files. $(FIND_NAMED) '*.md' | $(GREP_EXCLUDE) | xargs typos --config .typos-docs.toml --write-changes --force-exclude diff --git a/bootstrap/README.md b/bootstrap/README.md index e41f13d691c..4082e1c4f75 100644 --- a/bootstrap/README.md +++ b/bootstrap/README.md @@ -33,7 +33,7 @@ in the same way as it is shown for Linux above. On a system with functional `cab 1. Install the same GHC version as you will use to bootstrap on the host system. -2. Build a dependency description file (`$PLATFORM-$GHCVER.json`, e.g. `macosx-8.8.4.json`) by running: +2. Build a dependency description file (`$PLATFORM-$GHCVER.json`, e.g. `macosx-8.8.4.json`). ```sh cabal build --with-compiler=/path/to/ghc --dry-run cabal-install:exe:cabal @@ -45,15 +45,8 @@ in the same way as it is shown for Linux above. On a system with functional `cab 3. You may need to tweak `bootstrap/$PLATFORM-$GHCVER.json` file manually, for example, to toggle flags. -There are rules in the top-level `Makefile` for generation of these files. - -# Updating Bootstrap Plans - -In order to update the bootstrap plans on linux there is the convenient `./generate_bootstrap_plans` -script. You can modify this script with the GHC versions you want to generate the plans for and -then run it to generate the plans. - -``` -./generate_bootstrap_plans -``` - +The top level `Makefile` has a rule `bootstrap-jsons` to generate Linux bootstrap files for all +supported ghc versions, or `bootstrap-json-$GHCVER` for a single ghc version. The rules know +how to obtain the requisite ghc versions via `ghcup` or Nix; if you have neither, you will +have to obtain versioned ghc binaries from `downloads.haskell.org` or other suitable +repository. diff --git a/bootstrap/cabal-bootstrap-gen.cabal b/bootstrap/cabal-bootstrap-gen.cabal index 47ed4be45d0..3b4a9f3bd52 100644 --- a/bootstrap/cabal-bootstrap-gen.cabal +++ b/bootstrap/cabal-bootstrap-gen.cabal @@ -9,8 +9,8 @@ executable cabal-bootstrap-gen main-is: Main.hs build-depends: , aeson ^>=1.5.2.0 || ^>=2.0.3.0 || ^>=2.1.0.0 || ^>=2.2.0.0 - , base ^>=4.12.0.0 || ^>=4.13.0.0 || ^>=4.14.0.0 || ^>=4.15.0.0 || ^>=4.16.0.0 || ^>=4.17.0.0 || ^>=4.18.0.0 || ^>=4.19.0.0 || ^>=4.20.0.0 - , bytestring ^>=0.10.8.2 || ^>=0.11.0.0 + , base >=4.12.0.0 && < 5 + , bytestring >=0.10.8.2 && <0.13 , Cabal ^>=3.14.1.0 || ^>=3.16.0.0 , Cabal-syntax ^>=3.14.1.0 || ^>=3.16.0.0 -- For the release process, we need the last *two* Cabal-syntax @@ -20,7 +20,8 @@ executable cabal-bootstrap-gen -- rerun `make bootstrap-jsons`. , cabal-install-parsers ^>=0.6 , cabal-plan ^>=0.7.0.0 - , containers ^>=0.6.0.1 - , text ^>=1.2.3.0 || ^>=2.0.1 + -- upper bound is conjectural + , containers >=0.6.0.1 && <0.10 + , text >=1.2.3.0 && <3 , topograph ^>=1.0.0.1 , transformers ^>=0.5.6.2 || ^>=0.6.0.4 diff --git a/bootstrap/generate_bootstrap_plans b/bootstrap/generate_bootstrap_plans index 4630ad5fa8b..6c45fdd7fcf 100755 --- a/bootstrap/generate_bootstrap_plans +++ b/bootstrap/generate_bootstrap_plans @@ -1,23 +1,27 @@ -nix build nixpkgs#jq.bin -o jq -PATH+=:$PWD/jq-bin/bin +#! /bin/sh +nix build nixpkgs#jq.bin -o jq --extra-experimental-features nix-command --extra-experimental-features flakes +PATH="$PATH:$PWD/jq-bin/bin" ghcs_nix="https://gitlab.haskell.org/bgamari/ghcs-nix/-/archive/master/ghcs-nix-master.tar.gz" -nix build -f "$ghcs_nix" ghc-9_6_5 -o boot_ghc +nix build -f "$ghcs_nix" ghc-9_6_5 -o boot_ghc --extra-experimental-features nix-command run() { local ver="$1" local drv="ghc-$ver" echo "$ver" - nix build -f "$ghcs_nix" $drv - (cd ../; rm -r dist-bootstrap; cabal --distdir=dist-bootstrap build --project-file=cabal.bootstrap.project --dry-run cabal-install:exe:cabal -w bootstrap/result/bin/ghc) + nix build -f "$ghcs_nix" $drv --extra-experimental-features nix-command + (cd .. && rm -rf dist-bootstrap && cabal --distdir=dist-bootstrap build --project-file=cabal.bootstrap.project --dry-run cabal-install:exe:cabal -w bootstrap/result/bin/ghc) jq --sort-keys < ../dist-bootstrap/cache/plan.json > "plan-$ver.json" cabal run --with-ghc-pkg $PWD/boot_ghc/bin/ghc-pkg -w $PWD/boot_ghc/bin/ghc -v0 cabal-bootstrap-gen -- "plan-$ver.json" | jq --sort-keys | tee "linux-$(echo $ver | tr "_" ".").json" } -run "9_2_8" -run "9_4_8" -run "9_6_7" -run "9_8_4" -run "9_10_1" -run "9_12_2" +if [ $# -eq 0 ]; then + # get bootstrap ghc list from Makefile instead of hardcoded + # MAKELEVEL silences sub-make output if this is run from the top level Makefile + set -- $(cd ..; MAKELEVEL= make bootstrap-jsons-nix-helper) +fi + +for ghc in "$@"; do + run $(echo "$ghc" | tr . _) +done diff --git a/bootstrap/linux-9.10.2.json b/bootstrap/linux-9.10.3.json similarity index 98% rename from bootstrap/linux-9.10.2.json rename to bootstrap/linux-9.10.3.json index bf35aa995df..894b1d05177 100644 --- a/bootstrap/linux-9.10.2.json +++ b/bootstrap/linux-9.10.3.json @@ -14,11 +14,11 @@ }, { "package": "ghc-internal", - "version": "9.1002.0" + "version": "9.1003.0" }, { "package": "base", - "version": "4.20.1.0" + "version": "4.20.2.0" }, { "package": "array", @@ -30,7 +30,7 @@ }, { "package": "ghc-boot-th", - "version": "9.10.2" + "version": "9.10.3" }, { "package": "pretty", @@ -66,7 +66,7 @@ }, { "package": "os-string", - "version": "2.0.4" + "version": "2.0.7" }, { "package": "filepath", @@ -78,7 +78,7 @@ }, { "package": "unix", - "version": "2.8.6.0" + "version": "2.8.7.0" }, { "package": "directory", @@ -90,7 +90,7 @@ }, { "package": "text", - "version": "2.1.2" + "version": "2.1.3" }, { "package": "parsec",