[Git][ghc/ghc][wip/supersven/libDir-setting] 5 commits: Infra (drop later)
Sven Tennie pushed to branch wip/supersven/libDir-setting at Glasgow Haskell Compiler / GHC Commits: ebb6a162 by GHC GitLab CI at 2026-04-28T09:19:34+02:00 Infra (drop later) - - - - - 9415a08b by GHC GitLab CI at 2026-04-28T17:07:20+02:00 WIP - - - - - 63bcda0f by GHC GitLab CI at 2026-05-01T10:11:54+02:00 WORKS - remove LibDir from settings - - - - - 17b5ac74 by GHC GitLab CI at 2026-05-02T14:48:19+02:00 WIP - - - - - 2debb44b by GHC GitLab CI at 2026-05-02T18:45:02+02:00 Cleanup - - - - - 5 changed files: - + CLAUDE.md - hadrian/src/Rules/BinaryDist.hs - hadrian/src/Rules/Generate.hs - + source-env.sh - testsuite/ghc-config/ghc-config.hs Changes: ===================================== CLAUDE.md ===================================== @@ -0,0 +1,195 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +This is the source tree for **GHC** (Glasgow Haskell Compiler), a self-hosted optimising compiler for Haskell. The compiler is itself written in Haskell. GHC uses the **Hadrian** build system (based on Shake) instead of Make. + +## Build & Test Workflow + +All build and test commands go through `.gitlab/ci.sh`, which is the single CI driver. Run it from the repository root. **Always source `source-env.sh` first** — it sets all required environment variables for the Windows validate CI configuration: + +```sh +source source-env.sh +``` + +### Setup (once per checkout) + +```sh +source source-env.sh && .gitlab/ci.sh setup # fetch/verify toolchain, update cabal index +source source-env.sh && .gitlab/ci.sh configure # run ./boot + ./configure +``` + +`configure` respects `CONFIGURE_ARGS`. On Windows this runs with `--enable-tarballs-autodownload` automatically. + +### Building + +```sh +source source-env.sh && .gitlab/ci.sh build_hadrian +``` + +Build output goes to `_build/`; the stage2 compiler ends up at `_build/stage1/bin/ghc`. The bindist is produced at `${BIN_DIST_NAME}.tar.xz`. + +### Testing + +```sh +source source-env.sh && .gitlab/ci.sh test_hadrian +``` + +`test_hadrian` installs the bindist under `_build/install/`, then runs the testsuite against it. Override `RUNTEST_ARGS` to pass extra flags to the test driver: + +```sh +# Run a specific test +source source-env.sh +RUNTEST_ARGS="--only=T1234" .gitlab/ci.sh test_hadrian + +# Run tests in a directory +RUNTEST_ARGS="--test-root-dirs=testsuite/tests/typecheck" .gitlab/ci.sh test_hadrian + +# Skip performance tests +RUNTEST_ARGS="--skip-perf" .gitlab/ci.sh test_hadrian + +# Accept new test output +RUNTEST_ARGS="-a --only=T1234" .gitlab/ci.sh test_hadrian +``` + +Set `VERBOSE=1` to get verbose Hadrian output. Set `IGNORE_PERF_FAILURES=all` to ignore performance regressions. + +### Cleaning + +```sh +source source-env.sh && .gitlab/ci.sh clean +``` + +### What `source-env.sh` sets + +`source-env.sh` encodes the Windows x86_64 validate CI configuration: + +| Variable | Value | +|---|---| +| `BUILD_FLAVOUR` | `validate` | +| `BIN_DIST_NAME` | `ghc-x86_64-windows-validate` | +| `BIGNUM_BACKEND` | `gmp` | +| `FETCH_GHC_VERSION` | `9.10.3` | +| `CONFIGURE_ARGS` | `--enable-strict-ghc-toolchain-check` | +| `HADRIAN_ARGS` | `--docs=no-sphinx-pdfs` | +| `MSYSTEM` | `CLANG64` | + +Override individual variables after sourcing as needed (e.g. `RUNTEST_ARGS="--only=T1234"`). + +### Build flavours + +Select with `BUILD_FLAVOUR=<name>`: +- `quick` — `-O0` everywhere except compiler itself; 2-3x faster than default +- `quickest` — `-O0` everywhere, vanilla-only libraries; fastest but may not pass all tests +- `default` — full optimised build +- `validate` — used by CI; includes `-dcore-lint` and error checks +- `perf` — fully optimised with split sections; used by CI release builds +- `devel1` / `devel2` — debug builds with `-DDEBUG` and `-dcore-lint` + +Flavour transformers append with `+` (e.g. `BUILD_FLAVOUR=validate+werror`). + +### GHCi session for fast type-checking feedback + +```sh +./hadrian/ghci -j8 # Load GHC compiler into GHCi (type-check only) +ghcid --command="./hadrian/ghci" +``` + +This does not go through `ci.sh` and is fine for quick edit-check cycles. + +### Linting + +CI linters run as separate jobs. Locally: +```sh +source source-env.sh && .gitlab/ci.sh run_hadrian lint:compiler # hlint on compiler/ +source source-env.sh && .gitlab/ci.sh run_hadrian lint:base # hlint on libraries/base/ +``` + +Other linters (under `linters/`) check whitespace, commit messages, Note cross-references, and submodule refs. + +Tests are declared in `all.T` files (Python-based). Tests live under `testsuite/tests/` organised by compiler phase/feature, plus per-library tests in `libraries/*/`. + +## IDE Setup + +The `hie.yaml` at the root configures HLS/ghcide via hie-bios. On Windows, replace the program path: +```yaml +cradle: {bios: {program: "./hadrian/hie-bios.bat"}} +``` + +## Architecture + +GHC is a multi-stage self-hosted compiler. The build proceeds: +- **Stage0**: bootstrap GHC (pre-installed) builds Hadrian and the Stage1 compiler +- **Stage1** (`_build/stage0/bin/ghc`): used to build Stage2 and core libraries +- **Stage2** (`_build/stage1/bin/ghc`): the shipped compiler; what `build test` uses by default + +### Compiler pipeline (`compiler/`) + +Source flows through these phases, each in its own `GHC/` subdirectory: + +1. **Parser** (`GHC/Parser.y`, `GHC/Parser/`) — Alex/Happy lexer+parser → `HsSyn` AST +2. **Renamer** (`GHC/Rename/`) — resolves names, scope checking → renamed `HsSyn` +3. **Type checker** (`GHC/Tc/`) — Hindley-Milner + type classes + GADTs → typed AST +4. **Desugarer** (`GHC/HsToCore/`) — `HsSyn` → **Core IR** (`GHC/Core/`) +5. **Core optimiser** (`GHC/Core/Opt/`) — simplifier, strictness analysis, specialisation, CSE, etc. +6. **STG** (`GHC/CoreToStg/`, `GHC/Stg/`) — Core → Spineless Tagless G-machine IR +7. **Cmm** (`GHC/StgToCmm/`, `GHC/Cmm/`) — STG → C-- IR (low-level portable assembly) +8. **Backends** (`GHC/CmmToAsm/`, `GHC/CmmToC.hs`, `GHC/CmmToLlvm/`, `GHC/StgToJS/`) — Cmm → native asm / C / LLVM IR / JavaScript +9. **Bytecode** (`GHC/ByteCode/`, `GHC/StgToByteCode.hs`) — for GHCi interpreter + +Key supporting modules: +- `GHC/Driver/` — top-level driver, `DynFlags`, pipeline orchestration, `--make` mode +- `GHC/Iface/` — interface files (`.hi`) read/write +- `GHC/Plugins.hs` — plugin API +- `GHC.hs` — the public GHC API entry point +- `GHC/Prelude.hs` — re-exported prelude used throughout the compiler + +### Runtime System (`rts/`) + +Written in C and Cmm. Key subsystems: +- **Scheduler** (`Schedule.c`) — green thread scheduling +- **Garbage collector** (`sm/`) — generational GC +- **Linker** (`linker/`, `Linker.c`) — dynamic object loading for GHCi +- **STM** (`STM.c`) — software transactional memory +- **Profiling** (`Profiling.c`, `LdvProfile.c`, `RetainerProfile.c`) +- **Event log** (`eventlog/`) + +### Boot libraries (`libraries/`) + +Core libraries shipped with GHC: `base`, `ghc-prim`, `ghc-bignum`, `ghc-boot`, `ghci`, `template-haskell`, `ghc-compact`, `ghc-experimental`, and others. Changes to `base` require a [CLC proposal](https://github.com/haskell/core-libraries-committee). + +### Build system (`hadrian/`) + +Hadrian source is in `hadrian/src/`. Key files: +- `hadrian/src/Flavour.hs` — flavour definitions +- `hadrian/src/UserSettings.hs` — override point (copy to `hadrian/UserSettings.hs`) +- `hadrian/doc/` — documentation for flavours, expressions, user settings, testsuite + +## Changelog + +Every user-facing MR must add a fragment in `changelog.d/` (use a descriptive filename, not a ticket number alone). Required fields: `section`, `synopsis`, `mrs`, `issues`. Apply label `no-changelog` if no entry is needed. + +``` +section: compiler +synopsis: Brief description of the change. +issues: #NNNNN +mrs: !NNNNN + +description: { + Optional extended RST description. +} +``` + +## Notes / Commentary Convention + +GHC uses "Note [Title]" comments extensively for cross-referencing design decisions. When making a non-obvious change, add or update a Note and reference it from the relevant code locations with `-- See Note [Title]`. + +## Contribution Checklist + +- All commits must be individually buildable or squashed +- Commit messages describe what they do; reference tickets with `#NNNNN` +- Add testcases in `testsuite/tests/` (see `testsuite/driver/README.md` for how) +- Update the user's guide (`docs/users_guide/`) for user-visible changes +- Apply `~user-facing` label on GitLab if the change could break user programs ===================================== hadrian/src/Rules/BinaryDist.hs ===================================== @@ -226,7 +226,7 @@ bindistRules = do let bindistSettings = bindistFilesDir -/- "lib" -/- "settings" bindistContext = vanillaContext Stage1 compiler bindistSettingsContent <- interpretInContext bindistContext $ - generateSettings bindistSettings False + generateSettings bindistSettings False (bindistFilesDir -/- "lib" -/- "package.conf.d") writeFile' bindistSettings bindistSettingsContent copyDirectory (rtsIncludeDir) bindistFilesDir ===================================== hadrian/src/Rules/Generate.hs ===================================== @@ -257,8 +257,17 @@ generateRules = do forM_ allStages $ \stage -> do let prefix = root -/- stageString stage -/- "lib" - go gen file = generate file (semiEmptyTarget (succStage stage)) gen - (prefix -/- "settings") %> \out -> go (generateSettings out True) out + -- Stage0 compiler builds Stage1, Stage1 -> Stage2, etc. + buildStage = succStage stage + go gen file = generate file (semiEmptyTarget buildStage) gen + (prefix -/- "settings") %> \out -> do + let get_pkg_db stg = packageDbPath (PackageDbLoc stg Final) + pkgDb <- case buildStage of + Stage0 {} -> error "Unable to generate settings for stage0. This should never be reached." + Stage1 -> get_pkg_db Stage1 + Stage2 -> get_pkg_db Stage1 + Stage3 -> get_pkg_db Stage2 + go (generateSettings out True pkgDb) out (prefix -/- "targets" -/- "default.target") %> \out -> go (show <$> expr getTargetTarget) out where @@ -461,20 +470,14 @@ ghcWrapper stage = do ++ [ "$@" ] -- | Generate settings file, optionally including LibDir. +-- pkgDb: absolute path to the package DB for the "Relative Global Package DB" +-- setting. Callers determine the correct path (in-tree or bindist). -- For bindists, we omit LibDir so it defaults to topdir at runtime. -generateSettings :: FilePath -> Bool -> Expr String -generateSettings settingsFile includeLibDir = do +generateSettings :: FilePath -> Bool -> FilePath -> Expr String +generateSettings settingsFile includeLibDir package_db_path = do ctx <- getContext stage <- getStage - package_db_path <- expr $ do - let get_pkg_db stg = packageDbPath (PackageDbLoc stg Final) - case stage of - Stage0 {} -> error "Unable to generate settings for stage0" - Stage1 -> get_pkg_db Stage1 - Stage2 -> get_pkg_db Stage1 - Stage3 -> get_pkg_db Stage2 - -- The unit-id of the base package which is always linked against (#25382) base_unit_id <- expr $ do case stage of ===================================== source-env.sh ===================================== @@ -0,0 +1,14 @@ +export BIGNUM_BACKEND="gmp" +export BIN_DIST_NAME="ghc-x86_64-windows-validate" +export BUILD_FLAVOUR="validate" +export CABAL_INSTALL_VERSION="3.14.2.0" +export CONFIGURE_ARGS="--enable-strict-ghc-toolchain-check" +export FETCH_GHC_VERSION="9.10.3" +export HADRIAN_ARGS="--docs=no-sphinx-pdfs" +export INSTALL_CONFIGURE_ARGS="--enable-strict-ghc-toolchain-check" +export LANG="en_US.UTF-8" +export MSYSTEM="CLANG64" +export RUNTEST_ARGS="" +export TEST_ENV="x86_64-windows-validate" +export CI_JOB_NAME="x86_64-windows-validate" +export CPUS=2 \ No newline at end of file ===================================== testsuite/ghc-config/ghc-config.hs ===================================== @@ -38,8 +38,8 @@ main = do getGhcFieldOrFail fields "GhcUnregisterised" "Unregisterised" getGhcFieldOrFail fields "GhcWithSMP" "Support SMP" getGhcFieldOrFail fields "GhcRTSWays" "RTS ways" - getGhcFieldOrFail fields "GhcLibdir" "LibDir" - getGhcFieldOrFail fields "GhcGlobalPackageDb" "Global Package DB" + getGhcFieldOrFailFixSlashes fields "GhcLibdir" "LibDir" + getGhcFieldOrFailFixSlashes fields "GhcGlobalPackageDb" "Global Package DB" getGhcFieldOrDefault fields "TargetRTSLinkerOnlySupportsSharedLibs" "target RTS linker only supports shared libraries" "NO" getGhcFieldOrDefault fields "GhcDynamic" "GHC Dynamic" "NO" getGhcFieldOrDefault fields "GhcProfiled" "GHC Profiled" "NO" @@ -56,6 +56,10 @@ getGhcFieldOrFail :: [(String,String)] -> String -> String -> IO () getGhcFieldOrFail fields mkvar key = getGhcField fields mkvar key id (fail ("No field: " ++ key)) +getGhcFieldOrFailFixSlashes :: [(String,String)] -> String -> String -> IO () +getGhcFieldOrFailFixSlashes fields mkvar key + = getGhcField fields mkvar key fixSlashes (fail ("No field: " ++ key)) + getGhcFieldOrDefault :: [(String,String)] -> String -> String -> String -> IO () getGhcFieldOrDefault fields mkvar key deflt = getGhcField fields mkvar key id on_fail View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/da963128be8dd55ed30d44b85b8718a... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/da963128be8dd55ed30d44b85b8718a... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Sven Tennie (@supersven)