Sven Tennie pushed to branch wip/supersven/libDir-setting at Glasgow Haskell Compiler / GHC

Commits:

5 changed files:

Changes:

  • CLAUDE.md
    1
    +# CLAUDE.md
    
    2
    +
    
    3
    +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
    
    4
    +
    
    5
    +## Overview
    
    6
    +
    
    7
    +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.
    
    8
    +
    
    9
    +## Build & Test Workflow
    
    10
    +
    
    11
    +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:
    
    12
    +
    
    13
    +```sh
    
    14
    +source source-env.sh
    
    15
    +```
    
    16
    +
    
    17
    +### Setup (once per checkout)
    
    18
    +
    
    19
    +```sh
    
    20
    +source source-env.sh && .gitlab/ci.sh setup       # fetch/verify toolchain, update cabal index
    
    21
    +source source-env.sh && .gitlab/ci.sh configure   # run ./boot + ./configure
    
    22
    +```
    
    23
    +
    
    24
    +`configure` respects `CONFIGURE_ARGS`. On Windows this runs with `--enable-tarballs-autodownload` automatically.
    
    25
    +
    
    26
    +### Building
    
    27
    +
    
    28
    +```sh
    
    29
    +source source-env.sh && .gitlab/ci.sh build_hadrian
    
    30
    +```
    
    31
    +
    
    32
    +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`.
    
    33
    +
    
    34
    +### Testing
    
    35
    +
    
    36
    +```sh
    
    37
    +source source-env.sh && .gitlab/ci.sh test_hadrian
    
    38
    +```
    
    39
    +
    
    40
    +`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:
    
    41
    +
    
    42
    +```sh
    
    43
    +# Run a specific test
    
    44
    +source source-env.sh
    
    45
    +RUNTEST_ARGS="--only=T1234" .gitlab/ci.sh test_hadrian
    
    46
    +
    
    47
    +# Run tests in a directory
    
    48
    +RUNTEST_ARGS="--test-root-dirs=testsuite/tests/typecheck" .gitlab/ci.sh test_hadrian
    
    49
    +
    
    50
    +# Skip performance tests
    
    51
    +RUNTEST_ARGS="--skip-perf" .gitlab/ci.sh test_hadrian
    
    52
    +
    
    53
    +# Accept new test output
    
    54
    +RUNTEST_ARGS="-a --only=T1234" .gitlab/ci.sh test_hadrian
    
    55
    +```
    
    56
    +
    
    57
    +Set `VERBOSE=1` to get verbose Hadrian output. Set `IGNORE_PERF_FAILURES=all` to ignore performance regressions.
    
    58
    +
    
    59
    +### Cleaning
    
    60
    +
    
    61
    +```sh
    
    62
    +source source-env.sh && .gitlab/ci.sh clean
    
    63
    +```
    
    64
    +
    
    65
    +### What `source-env.sh` sets
    
    66
    +
    
    67
    +`source-env.sh` encodes the Windows x86_64 validate CI configuration:
    
    68
    +
    
    69
    +| Variable | Value |
    
    70
    +|---|---|
    
    71
    +| `BUILD_FLAVOUR` | `validate` |
    
    72
    +| `BIN_DIST_NAME` | `ghc-x86_64-windows-validate` |
    
    73
    +| `BIGNUM_BACKEND` | `gmp` |
    
    74
    +| `FETCH_GHC_VERSION` | `9.10.3` |
    
    75
    +| `CONFIGURE_ARGS` | `--enable-strict-ghc-toolchain-check` |
    
    76
    +| `HADRIAN_ARGS` | `--docs=no-sphinx-pdfs` |
    
    77
    +| `MSYSTEM` | `CLANG64` |
    
    78
    +
    
    79
    +Override individual variables after sourcing as needed (e.g. `RUNTEST_ARGS="--only=T1234"`).
    
    80
    +
    
    81
    +### Build flavours
    
    82
    +
    
    83
    +Select with `BUILD_FLAVOUR=<name>`:
    
    84
    +- `quick``-O0` everywhere except compiler itself; 2-3x faster than default
    
    85
    +- `quickest``-O0` everywhere, vanilla-only libraries; fastest but may not pass all tests
    
    86
    +- `default` — full optimised build
    
    87
    +- `validate` — used by CI; includes `-dcore-lint` and error checks
    
    88
    +- `perf` — fully optimised with split sections; used by CI release builds
    
    89
    +- `devel1` / `devel2` — debug builds with `-DDEBUG` and `-dcore-lint`
    
    90
    +
    
    91
    +Flavour transformers append with `+` (e.g. `BUILD_FLAVOUR=validate+werror`).
    
    92
    +
    
    93
    +### GHCi session for fast type-checking feedback
    
    94
    +
    
    95
    +```sh
    
    96
    +./hadrian/ghci -j8              # Load GHC compiler into GHCi (type-check only)
    
    97
    +ghcid --command="./hadrian/ghci"
    
    98
    +```
    
    99
    +
    
    100
    +This does not go through `ci.sh` and is fine for quick edit-check cycles.
    
    101
    +
    
    102
    +### Linting
    
    103
    +
    
    104
    +CI linters run as separate jobs. Locally:
    
    105
    +```sh
    
    106
    +source source-env.sh && .gitlab/ci.sh run_hadrian lint:compiler   # hlint on compiler/
    
    107
    +source source-env.sh && .gitlab/ci.sh run_hadrian lint:base       # hlint on libraries/base/
    
    108
    +```
    
    109
    +
    
    110
    +Other linters (under `linters/`) check whitespace, commit messages, Note cross-references, and submodule refs.
    
    111
    +
    
    112
    +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/*/`.
    
    113
    +
    
    114
    +## IDE Setup
    
    115
    +
    
    116
    +The `hie.yaml` at the root configures HLS/ghcide via hie-bios. On Windows, replace the program path:
    
    117
    +```yaml
    
    118
    +cradle: {bios: {program: "./hadrian/hie-bios.bat"}}
    
    119
    +```
    
    120
    +
    
    121
    +## Architecture
    
    122
    +
    
    123
    +GHC is a multi-stage self-hosted compiler. The build proceeds:
    
    124
    +- **Stage0**: bootstrap GHC (pre-installed) builds Hadrian and the Stage1 compiler
    
    125
    +- **Stage1** (`_build/stage0/bin/ghc`): used to build Stage2 and core libraries
    
    126
    +- **Stage2** (`_build/stage1/bin/ghc`): the shipped compiler; what `build test` uses by default
    
    127
    +
    
    128
    +### Compiler pipeline (`compiler/`)
    
    129
    +
    
    130
    +Source flows through these phases, each in its own `GHC/` subdirectory:
    
    131
    +
    
    132
    +1. **Parser** (`GHC/Parser.y`, `GHC/Parser/`) — Alex/Happy lexer+parser → `HsSyn` AST
    
    133
    +2. **Renamer** (`GHC/Rename/`) — resolves names, scope checking → renamed `HsSyn`
    
    134
    +3. **Type checker** (`GHC/Tc/`) — Hindley-Milner + type classes + GADTs → typed AST
    
    135
    +4. **Desugarer** (`GHC/HsToCore/`) — `HsSyn`**Core IR** (`GHC/Core/`)
    
    136
    +5. **Core optimiser** (`GHC/Core/Opt/`) — simplifier, strictness analysis, specialisation, CSE, etc.
    
    137
    +6. **STG** (`GHC/CoreToStg/`, `GHC/Stg/`) — Core → Spineless Tagless G-machine IR
    
    138
    +7. **Cmm** (`GHC/StgToCmm/`, `GHC/Cmm/`) — STG → C-- IR (low-level portable assembly)
    
    139
    +8. **Backends** (`GHC/CmmToAsm/`, `GHC/CmmToC.hs`, `GHC/CmmToLlvm/`, `GHC/StgToJS/`) — Cmm → native asm / C / LLVM IR / JavaScript
    
    140
    +9. **Bytecode** (`GHC/ByteCode/`, `GHC/StgToByteCode.hs`) — for GHCi interpreter
    
    141
    +
    
    142
    +Key supporting modules:
    
    143
    +- `GHC/Driver/` — top-level driver, `DynFlags`, pipeline orchestration, `--make` mode
    
    144
    +- `GHC/Iface/` — interface files (`.hi`) read/write
    
    145
    +- `GHC/Plugins.hs` — plugin API
    
    146
    +- `GHC.hs` — the public GHC API entry point
    
    147
    +- `GHC/Prelude.hs` — re-exported prelude used throughout the compiler
    
    148
    +
    
    149
    +### Runtime System (`rts/`)
    
    150
    +
    
    151
    +Written in C and Cmm. Key subsystems:
    
    152
    +- **Scheduler** (`Schedule.c`) — green thread scheduling
    
    153
    +- **Garbage collector** (`sm/`) — generational GC
    
    154
    +- **Linker** (`linker/`, `Linker.c`) — dynamic object loading for GHCi
    
    155
    +- **STM** (`STM.c`) — software transactional memory
    
    156
    +- **Profiling** (`Profiling.c`, `LdvProfile.c`, `RetainerProfile.c`)
    
    157
    +- **Event log** (`eventlog/`)
    
    158
    +
    
    159
    +### Boot libraries (`libraries/`)
    
    160
    +
    
    161
    +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).
    
    162
    +
    
    163
    +### Build system (`hadrian/`)
    
    164
    +
    
    165
    +Hadrian source is in `hadrian/src/`. Key files:
    
    166
    +- `hadrian/src/Flavour.hs` — flavour definitions
    
    167
    +- `hadrian/src/UserSettings.hs` — override point (copy to `hadrian/UserSettings.hs`)
    
    168
    +- `hadrian/doc/` — documentation for flavours, expressions, user settings, testsuite
    
    169
    +
    
    170
    +## Changelog
    
    171
    +
    
    172
    +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.
    
    173
    +
    
    174
    +```
    
    175
    +section: compiler
    
    176
    +synopsis: Brief description of the change.
    
    177
    +issues: #NNNNN
    
    178
    +mrs: !NNNNN
    
    179
    +
    
    180
    +description: {
    
    181
    +  Optional extended RST description.
    
    182
    +}
    
    183
    +```
    
    184
    +
    
    185
    +## Notes / Commentary Convention
    
    186
    +
    
    187
    +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]`.
    
    188
    +
    
    189
    +## Contribution Checklist
    
    190
    +
    
    191
    +- All commits must be individually buildable or squashed
    
    192
    +- Commit messages describe what they do; reference tickets with `#NNNNN`
    
    193
    +- Add testcases in `testsuite/tests/` (see `testsuite/driver/README.md` for how)
    
    194
    +- Update the user's guide (`docs/users_guide/`) for user-visible changes
    
    195
    +- Apply `~user-facing` label on GitLab if the change could break user programs

  • hadrian/src/Rules/BinaryDist.hs
    ... ... @@ -226,7 +226,7 @@ bindistRules = do
    226 226
             let bindistSettings = bindistFilesDir -/- "lib" -/- "settings"
    
    227 227
                 bindistContext = vanillaContext Stage1 compiler
    
    228 228
             bindistSettingsContent <- interpretInContext bindistContext $
    
    229
    -            generateSettings bindistSettings False
    
    229
    +            generateSettings bindistSettings False (bindistFilesDir -/- "lib" -/- "package.conf.d")
    
    230 230
             writeFile' bindistSettings bindistSettingsContent
    
    231 231
     
    
    232 232
             copyDirectory (rtsIncludeDir)         bindistFilesDir
    

  • hadrian/src/Rules/Generate.hs
    ... ... @@ -257,8 +257,17 @@ generateRules = do
    257 257
     
    
    258 258
         forM_ allStages $ \stage -> do
    
    259 259
             let prefix = root -/- stageString stage -/- "lib"
    
    260
    -            go gen file = generate file (semiEmptyTarget (succStage stage)) gen
    
    261
    -        (prefix -/- "settings") %> \out -> go (generateSettings out True) out
    
    260
    +            -- Stage0 compiler builds Stage1, Stage1 -> Stage2, etc.
    
    261
    +            buildStage = succStage stage
    
    262
    +            go gen file = generate file (semiEmptyTarget buildStage) gen
    
    263
    +        (prefix -/- "settings") %> \out -> do
    
    264
    +            let get_pkg_db stg = packageDbPath (PackageDbLoc stg Final)
    
    265
    +            pkgDb <- case buildStage of
    
    266
    +                Stage0 {} -> error "Unable to generate settings for stage0. This should never be reached."
    
    267
    +                Stage1 -> get_pkg_db Stage1
    
    268
    +                Stage2 -> get_pkg_db Stage1
    
    269
    +                Stage3 -> get_pkg_db Stage2
    
    270
    +            go (generateSettings out True pkgDb) out
    
    262 271
             (prefix -/- "targets" -/- "default.target") %> \out -> go (show <$> expr getTargetTarget) out
    
    263 272
     
    
    264 273
       where
    
    ... ... @@ -461,20 +470,14 @@ ghcWrapper stage = do
    461 470
                                    ++ [ "$@" ]
    
    462 471
     
    
    463 472
     -- | Generate settings file, optionally including LibDir.
    
    473
    +-- pkgDb: absolute path to the package DB for the "Relative Global Package DB"
    
    474
    +--   setting. Callers determine the correct path (in-tree or bindist).
    
    464 475
     -- For bindists, we omit LibDir so it defaults to topdir at runtime.
    
    465
    -generateSettings :: FilePath -> Bool -> Expr String
    
    466
    -generateSettings settingsFile includeLibDir = do
    
    476
    +generateSettings :: FilePath -> Bool -> FilePath -> Expr String
    
    477
    +generateSettings settingsFile includeLibDir package_db_path = do
    
    467 478
         ctx <- getContext
    
    468 479
         stage <- getStage
    
    469 480
     
    
    470
    -    package_db_path <- expr $ do
    
    471
    -      let get_pkg_db stg = packageDbPath (PackageDbLoc stg Final)
    
    472
    -      case stage of
    
    473
    -        Stage0 {} -> error "Unable to generate settings for stage0"
    
    474
    -        Stage1 -> get_pkg_db Stage1
    
    475
    -        Stage2 -> get_pkg_db Stage1
    
    476
    -        Stage3 -> get_pkg_db Stage2
    
    477
    -
    
    478 481
         -- The unit-id of the base package which is always linked against (#25382)
    
    479 482
         base_unit_id <- expr $ do
    
    480 483
           case stage of
    

  • source-env.sh
    1
    +export BIGNUM_BACKEND="gmp"
    
    2
    +export BIN_DIST_NAME="ghc-x86_64-windows-validate"
    
    3
    +export BUILD_FLAVOUR="validate"
    
    4
    +export CABAL_INSTALL_VERSION="3.14.2.0"
    
    5
    +export CONFIGURE_ARGS="--enable-strict-ghc-toolchain-check"
    
    6
    +export FETCH_GHC_VERSION="9.10.3"
    
    7
    +export HADRIAN_ARGS="--docs=no-sphinx-pdfs"
    
    8
    +export INSTALL_CONFIGURE_ARGS="--enable-strict-ghc-toolchain-check"
    
    9
    +export LANG="en_US.UTF-8"
    
    10
    +export MSYSTEM="CLANG64"
    
    11
    +export RUNTEST_ARGS=""
    
    12
    +export TEST_ENV="x86_64-windows-validate"
    
    13
    +export CI_JOB_NAME="x86_64-windows-validate"
    
    14
    +export CPUS=2
    \ No newline at end of file

  • testsuite/ghc-config/ghc-config.hs
    ... ... @@ -38,8 +38,8 @@ main = do
    38 38
       getGhcFieldOrFail fields "GhcUnregisterised" "Unregisterised"
    
    39 39
       getGhcFieldOrFail fields "GhcWithSMP" "Support SMP"
    
    40 40
       getGhcFieldOrFail fields "GhcRTSWays" "RTS ways"
    
    41
    -  getGhcFieldOrFail fields "GhcLibdir" "LibDir"
    
    42
    -  getGhcFieldOrFail fields "GhcGlobalPackageDb" "Global Package DB"
    
    41
    +  getGhcFieldOrFailFixSlashes fields "GhcLibdir" "LibDir"
    
    42
    +  getGhcFieldOrFailFixSlashes fields "GhcGlobalPackageDb" "Global Package DB"
    
    43 43
       getGhcFieldOrDefault fields "TargetRTSLinkerOnlySupportsSharedLibs" "target RTS linker only supports shared libraries" "NO"
    
    44 44
       getGhcFieldOrDefault fields "GhcDynamic" "GHC Dynamic" "NO"
    
    45 45
       getGhcFieldOrDefault fields "GhcProfiled" "GHC Profiled" "NO"
    
    ... ... @@ -56,6 +56,10 @@ getGhcFieldOrFail :: [(String,String)] -> String -> String -> IO ()
    56 56
     getGhcFieldOrFail fields mkvar key
    
    57 57
        = getGhcField fields mkvar key id (fail ("No field: " ++ key))
    
    58 58
     
    
    59
    +getGhcFieldOrFailFixSlashes :: [(String,String)] -> String -> String -> IO ()
    
    60
    +getGhcFieldOrFailFixSlashes fields mkvar key
    
    61
    +   = getGhcField fields mkvar key fixSlashes (fail ("No field: " ++ key))
    
    62
    +
    
    59 63
     getGhcFieldOrDefault :: [(String,String)] -> String -> String -> String -> IO ()
    
    60 64
     getGhcFieldOrDefault fields mkvar key deflt
    
    61 65
       = getGhcField fields mkvar key id on_fail