Sven Tennie pushed to branch wip/supersven/hadrian-cross-stage3 at Glasgow Haskell Compiler / GHC

Commits:

9 changed files:

Changes:

  • .gitignore
    ... ... @@ -120,7 +120,6 @@ _darcs/
    120 120
     /compiler/GHC/CmmToLlvm/Version/Bounds.hs
    
    121 121
     /compiler/ghc.cabal
    
    122 122
     /compiler/ghc.cabal.old
    
    123
    -/distrib/configure.ac
    
    124 123
     /distrib/ghc.iss
    
    125 124
     /docs/index.html
    
    126 125
     /docs/man
    

  • .gitlab/ci.sh
    ... ... @@ -62,9 +62,9 @@ Common Modes:
    62 62
     Environment variables affecting the build:
    
    63 63
     
    
    64 64
       CROSS_TARGET      Triple of cross-compilation target.
    
    65
    -  CROSS_STAGE       The stage of the cross-compiler to build either
    
    66
    -                      * 2: Build a normal cross-compiler bindist
    
    67
    -                      * 3: Build a target executable bindist (with the stage2 cross-compiler)
    
    65
    +  FINAL_CROSS_STAGE The final stage of the cross-compiler to build either
    
    66
    +                      * 2: Build a cross-compiler bindist
    
    67
    +                      * 3: Build a target executable bindist (implies the cross-compiler bindist of 2)
    
    68 68
       VERBOSE           Set to non-empty for verbose build output
    
    69 69
       RUNTEST_ARGS      Arguments passed to runtest.py
    
    70 70
       TEST_WAYS         Testsuite ways to run
    
    ... ... @@ -573,10 +573,18 @@ function build_hadrian() {
    573 573
         export XZ_OPT="${XZ_OPT:-} -T$cores"
    
    574 574
       fi
    
    575 575
     
    
    576
    -  case "${CROSS_STAGE:-2}" in
    
    576
    +  case "${FINAL_CROSS_STAGE:-2}" in
    
    577 577
         2) BINDIST_TARGET="binary-dist";;
    
    578
    -    3) BINDIST_TARGET="binary-dist-stage3";;
    
    579
    -    *) fail "Unknown CROSS_STAGE, must be 2 or 3";;
    
    578
    +    # Stage2 cross-compiler bindists are (almost) a byproduct of Stage3
    
    579
    +    # cross-compiled bindists. So, we bundle both of them when the Stage3
    
    580
    +    # bindist is built.
    
    581
    +    3)
    
    582
    +      BINDIST_TARGET="binary-dist binary-dist-stage3"
    
    583
    +      if [[ -z "${BIN_DIST_NAME_STAGE3:-}" ]]; then
    
    584
    +        fail "FINAL_CROSS_STAGE=3 requires BIN_DIST_NAME_STAGE3 to be set"
    
    585
    +      fi
    
    586
    +      ;;
    
    587
    +    *) fail "Unknown FINAL_CROSS_STAGE, must be 2 or 3";;
    
    580 588
       esac
    
    581 589
     
    
    582 590
       if [[ -n "${REINSTALL_GHC:-}" ]]; then
    
    ... ... @@ -590,6 +598,9 @@ function build_hadrian() {
    590 598
             *)
    
    591 599
               run_hadrian test:all_deps $BINDIST_TARGET
    
    592 600
               mv _build/bindist/ghc*.tar.xz "$BIN_DIST_NAME.tar.xz"
    
    601
    +          if [[ "${FINAL_CROSS_STAGE:-2}" == "3" ]]; then
    
    602
    +            mv _build/bindist-stage3/ghc*.tar.xz "$BIN_DIST_NAME_STAGE3.tar.xz"
    
    603
    +          fi
    
    593 604
               ;;
    
    594 605
         esac
    
    595 606
       fi
    
    ... ... @@ -696,6 +707,26 @@ function test_hadrian() {
    696 707
         # ---
    
    697 708
         # > main = putStrLn "hello world"
    
    698 709
         run diff -w expected actual
    
    710
    +
    
    711
    +    if [[ "${FINAL_CROSS_STAGE:-2}" == "3" ]]; then
    
    712
    +      local stage3_dir
    
    713
    +      stage3_dir="$(echo _build/bindist-stage3/ghc-*/)"
    
    714
    +      local stage3_ghc="$stage3_dir/bin/ghc$exe"
    
    715
    +
    
    716
    +      info "Smoke-testing stage3 compiler..."
    
    717
    +      file "$stage3_ghc"
    
    718
    +      run ${CROSS_EMULATOR} "$stage3_ghc" --info
    
    719
    +
    
    720
    +      run ${CROSS_EMULATOR} "$stage3_ghc" -package ghc "$TOP/.gitlab/hello.hs" -o hello-stage3
    
    721
    +
    
    722
    +      if [[ "${CROSS_TARGET:-no_cross_target}" =~ "mingw" ]]; then
    
    723
    +        ${CROSS_EMULATOR:-} ./hello-stage3.exe > actual-stage3
    
    724
    +      else
    
    725
    +        ${CROSS_EMULATOR:-} ./hello-stage3 > actual-stage3
    
    726
    +      fi
    
    727
    +
    
    728
    +      run diff -w expected actual-stage3
    
    729
    +    fi
    
    699 730
       elif [[ -n "${REINSTALL_GHC:-}" ]]; then
    
    700 731
         run_hadrian \
    
    701 732
           test \
    

  • .gitlab/generate-ci/gen_ci.hs
    ... ... @@ -159,7 +159,7 @@ data BuildConfig
    159 159
                     , withNuma       :: Bool
    
    160 160
                     , withZstd       :: Bool
    
    161 161
                     , crossTarget    :: Maybe String
    
    162
    -                , crossStage     :: Maybe Int
    
    162
    +                , finalCrossStage :: Maybe FinalCrossStage
    
    163 163
                     , crossEmulator  :: CrossEmulator
    
    164 164
                     , configureWrapper :: Maybe String
    
    165 165
                     , fullyStatic    :: Bool
    
    ... ... @@ -229,7 +229,7 @@ vanilla = BuildConfig
    229 229
       , withNuma = False
    
    230 230
       , withZstd = False
    
    231 231
       , crossTarget = Nothing
    
    232
    -  , crossStage  = Nothing
    
    232
    +  , finalCrossStage  = Nothing
    
    233 233
       , crossEmulator = NoEmulator
    
    234 234
       , configureWrapper = Nothing
    
    235 235
       , fullyStatic = False
    
    ... ... @@ -275,13 +275,26 @@ static = vanilla { fullyStatic = True }
    275 275
     staticNativeInt :: BuildConfig
    
    276 276
     staticNativeInt = static { bignumBackend = Native }
    
    277 277
     
    
    278
    +-- | The final stage for which binary distributions should be built
    
    279
    +--
    
    280
    +-- `Stage2` builds a cross-compiler (build == host, host /= target). `Stage3`
    
    281
    +-- implies `Stage2` and additionally builds a cross-compiled compiler (build /=
    
    282
    +-- host, host == target).
    
    283
    +data FinalCrossStage = Stage2 | Stage3
    
    284
    +  deriving (Eq, Ord)
    
    285
    +
    
    286
    +crossStageToInt :: FinalCrossStage -> Int
    
    287
    +crossStageToInt Stage2 = 2
    
    288
    +crossStageToInt Stage3 = 3
    
    289
    +
    
    278 290
     crossConfig :: String       -- ^ target triple
    
    279 291
                 -> CrossEmulator -- ^ emulator for testing
    
    280 292
                 -> Maybe String -- ^ Configure wrapper
    
    293
    +            -> FinalCrossStage -- ^ final stage to build
    
    281 294
                 -> BuildConfig
    
    282
    -crossConfig triple emulator configure_wrapper =
    
    295
    +crossConfig triple emulator configure_wrapper crossStage =
    
    283 296
         vanilla { crossTarget = Just triple
    
    284
    -            , crossStage  = Just 2
    
    297
    +            , finalCrossStage  = Just crossStage
    
    285 298
                 , crossEmulator = emulator
    
    286 299
                 , configureWrapper = configure_wrapper
    
    287 300
                 }
    
    ... ... @@ -348,21 +361,48 @@ opsysName Darwin = "darwin"
    348 361
     opsysName FreeBSD14      = "freebsd14"
    
    349 362
     opsysName Windows        = "windows"
    
    350 363
     
    
    364
    +-- | Remove cross-specific prefix for Stage3 bindist names.
    
    365
    +-- We need to pretend to have built the bindist on the target.
    
    366
    +toStage3TargetOpsys :: Opsys -> Opsys
    
    367
    +toStage3TargetOpsys (Linux Debian13Riscv) = Linux Debian13
    
    368
    +toStage3TargetOpsys (Linux Ubuntu2404LoongArch64) = Linux Ubuntu2404
    
    369
    +toStage3TargetOpsys opsys = opsys
    
    370
    +
    
    351 371
     archName :: Arch -> String
    
    352 372
     archName Amd64   = "x86_64"
    
    353 373
     archName AArch64 = "aarch64"
    
    354 374
     archName I386    = "i386"
    
    355 375
     
    
    376
    +-- | First component of a cross target triple, used to name stage3
    
    377
    +-- (target-platform) bindists as if they had been built natively on the target.
    
    378
    +targetArchName :: String -> String
    
    379
    +targetArchName = takeWhile (/= '-')
    
    380
    +
    
    356 381
     binDistName :: Arch -> Opsys -> BuildConfig -> String
    
    357
    -binDistName arch opsys bc = "ghc-" ++ testEnv arch opsys bc
    
    382
    +binDistName arch = binDistNameWith (archName arch)
    
    383
    +
    
    384
    +binDistNameWith :: String -> Opsys -> BuildConfig -> String
    
    385
    +binDistNameWith archN opsys bc = "ghc-" ++ testEnvWith archN opsys bc
    
    386
    +
    
    387
    +stage3BinDistName :: Opsys -> BuildConfig -> Maybe String
    
    388
    +stage3BinDistName opsys bc
    
    389
    +  | Just Stage3 <- finalCrossStage bc
    
    390
    +  , Just triple <- crossTarget bc
    
    391
    +  = Just $ binDistNameWith (targetArchName triple) (toStage3TargetOpsys opsys)
    
    392
    +                          (bc { crossTarget = Nothing })
    
    393
    +  | otherwise
    
    394
    +  = Nothing
    
    358 395
     
    
    359 396
     -- | Test env should create a string which changes whenever the 'BuildConfig' changes.
    
    360 397
     -- Either the change is reflected by modifying the flavourString or directly (as is
    
    361 398
     -- the case for settings which affect environment variables)
    
    362 399
     testEnv :: Arch -> Opsys -> BuildConfig -> String
    
    363
    -testEnv arch opsys bc =
    
    400
    +testEnv arch = testEnvWith (archName arch)
    
    401
    +
    
    402
    +testEnvWith :: String -> Opsys -> BuildConfig -> String
    
    403
    +testEnvWith archN opsys bc =
    
    364 404
       intercalate "-" $ concat
    
    365
    -    [ [ archName arch
    
    405
    +    [ [ archN
    
    366 406
           , opsysName opsys ]
    
    367 407
         , ["int_" ++ bignumString (bignumBackend bc) | bignumBackend bc /= Gmp]
    
    368 408
         , ["unreg" | unregisterised bc ]
    
    ... ... @@ -883,13 +923,14 @@ job arch opsys buildConfig = NamedJob { name = jobName, jobInfo = Job {..} }
    883 923
           [ opsysVariables arch opsys
    
    884 924
           , "TEST_ENV" =: testEnv arch opsys buildConfig
    
    885 925
           , "BIN_DIST_NAME" =: binDistName arch opsys buildConfig
    
    926
    +      , maybe mempty ("BIN_DIST_NAME_STAGE3" =:) (stage3BinDistName opsys buildConfig)
    
    886 927
           , "BUILD_FLAVOUR" =: flavourString jobFlavour
    
    887 928
           , "BIGNUM_BACKEND" =: bignumString (bignumBackend buildConfig)
    
    888 929
           , "CONFIGURE_ARGS" =: configureArgsStr buildConfig
    
    889 930
           , "INSTALL_CONFIGURE_ARGS" =: "--enable-strict-ghc-toolchain-check"
    
    890 931
           , maybe mempty ("CONFIGURE_WRAPPER" =:) (configureWrapper buildConfig)
    
    891 932
           , maybe mempty ("CROSS_TARGET" =:) (crossTarget buildConfig)
    
    892
    -      , maybe mempty (("CROSS_STAGE" =:) . show) (crossStage buildConfig)
    
    933
    +      , maybe mempty (("FINAL_CROSS_STAGE" =:) . show . crossStageToInt) (finalCrossStage buildConfig)
    
    893 934
           , case crossEmulator buildConfig of
    
    894 935
               NoEmulator
    
    895 936
                 -- we need an emulator but it isn't set. Won't run the testsuite
    
    ... ... @@ -922,6 +963,8 @@ job arch opsys buildConfig = NamedJob { name = jobName, jobInfo = Job {..} }
    922 963
         trim :: String -> String
    
    923 964
         trim = dropWhileEnd isSpace . dropWhile isSpace
    
    924 965
     
    
    966
    +    stage3Artifacts = maybe [] (\n -> [n ++ ".tar.xz"]) (stage3BinDistName opsys buildConfig)
    
    967
    +
    
    925 968
         -- Keep in sync with the exclude list in `function clean()` in
    
    926 969
         -- `.gitlab/ci.sh`!
    
    927 970
         jobArtifacts = Artifacts
    
    ... ... @@ -930,6 +973,7 @@ job arch opsys buildConfig = NamedJob { name = jobName, jobInfo = Job {..} }
    930 973
           , artifactPaths = [binDistName arch opsys buildConfig ++ ".tar.xz"
    
    931 974
                             ,"junit.xml"
    
    932 975
                             ,"unexpected-test-output.tar.gz"]
    
    976
    +                        ++ stage3Artifacts
    
    933 977
           , artifactsWhen = ArtifactsAlways
    
    934 978
           }
    
    935 979
     
    
    ... ... @@ -1288,13 +1332,14 @@ alpine_aarch64 = [
    1288 1332
     cross_jobs :: [JobGroup Job]
    
    1289 1333
     cross_jobs = [
    
    1290 1334
         -- x86 -> aarch64
    
    1291
    -    validateBuilds Amd64 (Linux Debian13) (crossConfig "aarch64-linux-gnu" (Emulator "qemu-aarch64 -L /usr/aarch64-linux-gnu") Nothing)
    
    1335
    +    validateBuilds Amd64 (Linux Debian13) (crossConfig "aarch64-linux-gnu" (Emulator "qemu-aarch64 -L /usr/aarch64-linux-gnu") Nothing Stage2)
    
    1292 1336
     
    
    1293
    -    -- x86_64 -> riscv
    
    1294
    -  , addValidateRule RiscV (validateBuilds Amd64 (Linux Debian13Riscv) (crossConfig "riscv64-linux-gnu" (Emulator "qemu-riscv64 -L /usr/riscv64-linux-gnu") Nothing))
    
    1337
    +    -- Stage2: x86_64 (build/host) -> riscv64 (target)
    
    1338
    +    -- Stage3: x86_64 (build) -> riscv64 (host/target)
    
    1339
    +  , addValidateRule RiscV (validateBuilds Amd64 (Linux Debian13Riscv) (crossConfig "riscv64-linux-gnu" (Emulator "qemu-riscv64 -L /usr/riscv64-linux-gnu") Nothing Stage3))
    
    1295 1340
     
    
    1296 1341
         -- x86_64 -> loongarch64
    
    1297
    -  , addValidateRule LoongArch64 (validateBuilds Amd64 (Linux Ubuntu2404LoongArch64) (crossConfig "loongarch64-linux-gnu" (Emulator "qemu-loongarch64 -L /usr/loongarch64-linux-gnu") Nothing))
    
    1342
    +  , addValidateRule LoongArch64 (validateBuilds Amd64 (Linux Ubuntu2404LoongArch64) (crossConfig "loongarch64-linux-gnu" (Emulator "qemu-loongarch64 -L /usr/loongarch64-linux-gnu") Nothing Stage2))
    
    1298 1343
     
    
    1299 1344
         -- Javascript
    
    1300 1345
       , addValidateRule JSBackend (validateBuilds Amd64 (Linux Debian11Js) javascriptConfig)
    
    ... ... @@ -1315,7 +1360,7 @@ cross_jobs = [
    1315 1360
             (validateBuilds AArch64 (Linux Debian12Wine) (winAarch64Config {llvmBootstrap = True}))
    
    1316 1361
       ]
    
    1317 1362
       where
    
    1318
    -    javascriptConfig = (crossConfig "javascript-unknown-ghcjs" (NoEmulatorNeeded TimeoutIncrease) (Just "emconfigure"))
    
    1363
    +    javascriptConfig = (crossConfig "javascript-unknown-ghcjs" (NoEmulatorNeeded TimeoutIncrease) (Just "emconfigure") Stage2)
    
    1319 1364
                              { bignumBackend = Native }
    
    1320 1365
     
    
    1321 1366
         makeWinArmJobs = modifyJobs
    
    ... ... @@ -1354,7 +1399,7 @@ cross_jobs = [
    1354 1399
                 llvm_prefix = "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-"
    
    1355 1400
                 cflags = "-fuse-ld=" ++ llvm_prefix ++ "ld --rtlib=compiler-rt"
    
    1356 1401
     
    
    1357
    -    winAarch64Config = (crossConfig "aarch64-unknown-mingw32" (Emulator "/opt/wine-arm64ec-msys2-deb12/bin/wine") Nothing)
    
    1402
    +    winAarch64Config = (crossConfig "aarch64-unknown-mingw32" (Emulator "/opt/wine-arm64ec-msys2-deb12/bin/wine") Nothing Stage2)
    
    1358 1403
                              { bignumBackend = Native }
    
    1359 1404
     
    
    1360 1405
         make_wasm_jobs cfg =
    
    ... ... @@ -1367,7 +1412,7 @@ cross_jobs = [
    1367 1412
             $ addValidateRule WasmBackend $ validateBuilds Amd64 (Linux AlpineWasm) cfg
    
    1368 1413
     
    
    1369 1414
         wasm_build_config =
    
    1370
    -      (crossConfig "wasm32-wasi" (NoEmulatorNeeded NoTimeoutIncrease) Nothing)
    
    1415
    +      (crossConfig "wasm32-wasi" (NoEmulatorNeeded NoTimeoutIncrease) Nothing Stage2)
    
    1371 1416
             { hostFullyStatic = True
    
    1372 1417
             , buildFlavour    = Release -- TODO: This needs to be validate but wasm backend doesn't pass yet
    
    1373 1418
             , textWithSIMDUTF = True
    

  • .gitlab/jobs.yaml
    ... ... @@ -319,9 +319,9 @@
    319 319
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    320 320
           "CONF_CC_OPTS_STAGE2": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
    
    321 321
           "CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
    
    322
    -      "CROSS_STAGE": "2",
    
    323 322
           "CROSS_TARGET": "aarch64-unknown-mingw32",
    
    324 323
           "CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
    
    324
    +      "FINAL_CROSS_STAGE": "2",
    
    325 325
           "HADRIAN_ARGS": "--docs=none",
    
    326 326
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    327 327
           "LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
    
    ... ... @@ -403,9 +403,9 @@
    403 403
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    404 404
           "CONF_CC_OPTS_STAGE2": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
    
    405 405
           "CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
    
    406
    -      "CROSS_STAGE": "2",
    
    407 406
           "CROSS_TARGET": "aarch64-unknown-mingw32",
    
    408 407
           "CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
    
    408
    +      "FINAL_CROSS_STAGE": "2",
    
    409 409
           "HADRIAN_ARGS": "--docs=none",
    
    410 410
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    411 411
           "LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
    
    ... ... @@ -1127,9 +1127,9 @@
    1127 1127
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    1128 1128
           "CONF_CC_OPTS_STAGE2": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
    
    1129 1129
           "CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
    
    1130
    -      "CROSS_STAGE": "2",
    
    1131 1130
           "CROSS_TARGET": "aarch64-unknown-mingw32",
    
    1132 1131
           "CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
    
    1132
    +      "FINAL_CROSS_STAGE": "2",
    
    1133 1133
           "HADRIAN_ARGS": "--docs=none",
    
    1134 1134
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    1135 1135
           "LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
    
    ... ... @@ -1212,9 +1212,9 @@
    1212 1212
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    1213 1213
           "CONF_CC_OPTS_STAGE2": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
    
    1214 1214
           "CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
    
    1215
    -      "CROSS_STAGE": "2",
    
    1216 1215
           "CROSS_TARGET": "aarch64-unknown-mingw32",
    
    1217 1216
           "CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
    
    1217
    +      "FINAL_CROSS_STAGE": "2",
    
    1218 1218
           "HADRIAN_ARGS": "--docs=none",
    
    1219 1219
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    1220 1220
           "LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
    
    ... ... @@ -2010,8 +2010,8 @@
    2010 2010
           "BIN_DIST_NAME": "ghc-x86_64-linux-alpine3_23-wasm-cross_wasm32-wasi-release+host_fully_static+text_simdutf",
    
    2011 2011
           "BUILD_FLAVOUR": "release+host_fully_static+text_simdutf",
    
    2012 2012
           "CONFIGURE_ARGS": "--with-intree-gmp --with-system-libffi --enable-strict-ghc-toolchain-check",
    
    2013
    -      "CROSS_STAGE": "2",
    
    2014 2013
           "CROSS_TARGET": "wasm32-wasi",
    
    2014
    +      "FINAL_CROSS_STAGE": "2",
    
    2015 2015
           "FIREFOX_LAUNCH_OPTS": "{\"browser\":\"firefox\",\"executablePath\":\"/usr/bin/firefox\"}",
    
    2016 2016
           "HADRIAN_ARGS": "--docs=no-sphinx-pdfs --docs=no-sphinx-man",
    
    2017 2017
           "RUNTEST_ARGS": "",
    
    ... ... @@ -2077,8 +2077,8 @@
    2077 2077
           "BIN_DIST_NAME": "ghc-x86_64-linux-alpine3_23-wasm-int_native-cross_wasm32-wasi-release+host_fully_static+text_simdutf",
    
    2078 2078
           "BUILD_FLAVOUR": "release+host_fully_static+text_simdutf",
    
    2079 2079
           "CONFIGURE_ARGS": "--with-intree-gmp --with-system-libffi --enable-strict-ghc-toolchain-check",
    
    2080
    -      "CROSS_STAGE": "2",
    
    2081 2080
           "CROSS_TARGET": "wasm32-wasi",
    
    2081
    +      "FINAL_CROSS_STAGE": "2",
    
    2082 2082
           "FIREFOX_LAUNCH_OPTS": "{\"browser\":\"firefox\",\"executablePath\":\"/usr/bin/firefox\"}",
    
    2083 2083
           "HADRIAN_ARGS": "--docs=no-sphinx-pdfs --docs=no-sphinx-man",
    
    2084 2084
           "RUNTEST_ARGS": "",
    
    ... ... @@ -2144,8 +2144,8 @@
    2144 2144
           "BIN_DIST_NAME": "ghc-x86_64-linux-alpine3_23-wasm-unreg-cross_wasm32-wasi-release+host_fully_static+text_simdutf",
    
    2145 2145
           "BUILD_FLAVOUR": "release+host_fully_static+text_simdutf",
    
    2146 2146
           "CONFIGURE_ARGS": "--enable-unregisterised --with-intree-gmp --with-system-libffi --enable-strict-ghc-toolchain-check",
    
    2147
    -      "CROSS_STAGE": "2",
    
    2148 2147
           "CROSS_TARGET": "wasm32-wasi",
    
    2148
    +      "FINAL_CROSS_STAGE": "2",
    
    2149 2149
           "FIREFOX_LAUNCH_OPTS": "{\"browser\":\"firefox\",\"executablePath\":\"/usr/bin/firefox\"}",
    
    2150 2150
           "HADRIAN_ARGS": "--docs=no-sphinx-pdfs --docs=no-sphinx-man",
    
    2151 2151
           "RUNTEST_ARGS": "",
    
    ... ... @@ -2212,8 +2212,8 @@
    2212 2212
           "BUILD_FLAVOUR": "validate",
    
    2213 2213
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    2214 2214
           "CONFIGURE_WRAPPER": "emconfigure",
    
    2215
    -      "CROSS_STAGE": "2",
    
    2216 2215
           "CROSS_TARGET": "javascript-unknown-ghcjs",
    
    2216
    +      "FINAL_CROSS_STAGE": "2",
    
    2217 2217
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    2218 2218
           "RUNTEST_ARGS": "-e config.timeout=900",
    
    2219 2219
           "TEST_ENV": "x86_64-linux-deb11-emsdk-closure-int_native-cross_javascript-unknown-ghcjs-validate",
    
    ... ... @@ -2471,8 +2471,8 @@
    2471 2471
           "BUILD_FLAVOUR": "validate",
    
    2472 2472
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    2473 2473
           "CROSS_EMULATOR": "qemu-aarch64 -L /usr/aarch64-linux-gnu",
    
    2474
    -      "CROSS_STAGE": "2",
    
    2475 2474
           "CROSS_TARGET": "aarch64-linux-gnu",
    
    2475
    +      "FINAL_CROSS_STAGE": "2",
    
    2476 2476
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    2477 2477
           "RUNTEST_ARGS": "-e config.timeout=900",
    
    2478 2478
           "TEST_ENV": "x86_64-linux-deb13-cross_aarch64-linux-gnu-validate",
    
    ... ... @@ -2750,7 +2750,8 @@
    2750 2750
           "paths": [
    
    2751 2751
             "ghc-x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-validate.tar.xz",
    
    2752 2752
             "junit.xml",
    
    2753
    -        "unexpected-test-output.tar.gz"
    
    2753
    +        "unexpected-test-output.tar.gz",
    
    2754
    +        "ghc-riscv64-linux-deb13-validate.tar.xz"
    
    2754 2755
           ],
    
    2755 2756
           "reports": {
    
    2756 2757
             "junit": "junit.xml"
    
    ... ... @@ -2792,11 +2793,12 @@
    2792 2793
         "variables": {
    
    2793 2794
           "BIGNUM_BACKEND": "gmp",
    
    2794 2795
           "BIN_DIST_NAME": "ghc-x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-validate",
    
    2796
    +      "BIN_DIST_NAME_STAGE3": "ghc-riscv64-linux-deb13-validate",
    
    2795 2797
           "BUILD_FLAVOUR": "validate",
    
    2796 2798
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    2797 2799
           "CROSS_EMULATOR": "qemu-riscv64 -L /usr/riscv64-linux-gnu",
    
    2798
    -      "CROSS_STAGE": "2",
    
    2799 2800
           "CROSS_TARGET": "riscv64-linux-gnu",
    
    2801
    +      "FINAL_CROSS_STAGE": "3",
    
    2800 2802
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    2801 2803
           "RUNTEST_ARGS": "-e config.timeout=900",
    
    2802 2804
           "TEST_ENV": "x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-validate",
    
    ... ... @@ -3699,8 +3701,8 @@
    3699 3701
           "BUILD_FLAVOUR": "validate",
    
    3700 3702
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    3701 3703
           "CROSS_EMULATOR": "qemu-loongarch64 -L /usr/loongarch64-linux-gnu",
    
    3702
    -      "CROSS_STAGE": "2",
    
    3703 3704
           "CROSS_TARGET": "loongarch64-linux-gnu",
    
    3705
    +      "FINAL_CROSS_STAGE": "2",
    
    3704 3706
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    3705 3707
           "RUNTEST_ARGS": "-e config.timeout=900",
    
    3706 3708
           "TEST_ENV": "x86_64-linux-ubuntu24_04-loongarch-cross_loongarch64-linux-gnu-validate",
    
    ... ... @@ -5995,8 +5997,8 @@
    5995 5997
           "BIN_DIST_NAME": "ghc-x86_64-linux-alpine3_23-wasm-cross_wasm32-wasi-release+host_fully_static+text_simdutf",
    
    5996 5998
           "BUILD_FLAVOUR": "release+host_fully_static+text_simdutf",
    
    5997 5999
           "CONFIGURE_ARGS": "--with-intree-gmp --with-system-libffi --enable-strict-ghc-toolchain-check",
    
    5998
    -      "CROSS_STAGE": "2",
    
    5999 6000
           "CROSS_TARGET": "wasm32-wasi",
    
    6001
    +      "FINAL_CROSS_STAGE": "2",
    
    6000 6002
           "FIREFOX_LAUNCH_OPTS": "{\"browser\":\"firefox\",\"executablePath\":\"/usr/bin/firefox\"}",
    
    6001 6003
           "HADRIAN_ARGS": "--docs=no-sphinx-pdfs --docs=no-sphinx-man",
    
    6002 6004
           "RUNTEST_ARGS": "",
    
    ... ... @@ -6062,8 +6064,8 @@
    6062 6064
           "BIN_DIST_NAME": "ghc-x86_64-linux-alpine3_23-wasm-int_native-cross_wasm32-wasi-release+host_fully_static+text_simdutf",
    
    6063 6065
           "BUILD_FLAVOUR": "release+host_fully_static+text_simdutf",
    
    6064 6066
           "CONFIGURE_ARGS": "--with-intree-gmp --with-system-libffi --enable-strict-ghc-toolchain-check",
    
    6065
    -      "CROSS_STAGE": "2",
    
    6066 6067
           "CROSS_TARGET": "wasm32-wasi",
    
    6068
    +      "FINAL_CROSS_STAGE": "2",
    
    6067 6069
           "FIREFOX_LAUNCH_OPTS": "{\"browser\":\"firefox\",\"executablePath\":\"/usr/bin/firefox\"}",
    
    6068 6070
           "HADRIAN_ARGS": "--docs=no-sphinx-pdfs --docs=no-sphinx-man",
    
    6069 6071
           "RUNTEST_ARGS": "",
    
    ... ... @@ -6129,8 +6131,8 @@
    6129 6131
           "BIN_DIST_NAME": "ghc-x86_64-linux-alpine3_23-wasm-unreg-cross_wasm32-wasi-release+host_fully_static+text_simdutf",
    
    6130 6132
           "BUILD_FLAVOUR": "release+host_fully_static+text_simdutf",
    
    6131 6133
           "CONFIGURE_ARGS": "--enable-unregisterised --with-intree-gmp --with-system-libffi --enable-strict-ghc-toolchain-check",
    
    6132
    -      "CROSS_STAGE": "2",
    
    6133 6134
           "CROSS_TARGET": "wasm32-wasi",
    
    6135
    +      "FINAL_CROSS_STAGE": "2",
    
    6134 6136
           "FIREFOX_LAUNCH_OPTS": "{\"browser\":\"firefox\",\"executablePath\":\"/usr/bin/firefox\"}",
    
    6135 6137
           "HADRIAN_ARGS": "--docs=no-sphinx-pdfs --docs=no-sphinx-man",
    
    6136 6138
           "RUNTEST_ARGS": "",
    
    ... ... @@ -6196,8 +6198,8 @@
    6196 6198
           "BUILD_FLAVOUR": "validate",
    
    6197 6199
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    6198 6200
           "CONFIGURE_WRAPPER": "emconfigure",
    
    6199
    -      "CROSS_STAGE": "2",
    
    6200 6201
           "CROSS_TARGET": "javascript-unknown-ghcjs",
    
    6202
    +      "FINAL_CROSS_STAGE": "2",
    
    6201 6203
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    6202 6204
           "RUNTEST_ARGS": "-e config.timeout=900",
    
    6203 6205
           "TEST_ENV": "x86_64-linux-deb11-emsdk-closure-int_native-cross_javascript-unknown-ghcjs-validate",
    
    ... ... @@ -6451,8 +6453,8 @@
    6451 6453
           "BUILD_FLAVOUR": "validate",
    
    6452 6454
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    6453 6455
           "CROSS_EMULATOR": "qemu-aarch64 -L /usr/aarch64-linux-gnu",
    
    6454
    -      "CROSS_STAGE": "2",
    
    6455 6456
           "CROSS_TARGET": "aarch64-linux-gnu",
    
    6457
    +      "FINAL_CROSS_STAGE": "2",
    
    6456 6458
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    6457 6459
           "RUNTEST_ARGS": "-e config.timeout=900",
    
    6458 6460
           "TEST_ENV": "x86_64-linux-deb13-cross_aarch64-linux-gnu-validate",
    
    ... ... @@ -6726,7 +6728,8 @@
    6726 6728
           "paths": [
    
    6727 6729
             "ghc-x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-validate.tar.xz",
    
    6728 6730
             "junit.xml",
    
    6729
    -        "unexpected-test-output.tar.gz"
    
    6731
    +        "unexpected-test-output.tar.gz",
    
    6732
    +        "ghc-riscv64-linux-deb13-validate.tar.xz"
    
    6730 6733
           ],
    
    6731 6734
           "reports": {
    
    6732 6735
             "junit": "junit.xml"
    
    ... ... @@ -6768,11 +6771,12 @@
    6768 6771
         "variables": {
    
    6769 6772
           "BIGNUM_BACKEND": "gmp",
    
    6770 6773
           "BIN_DIST_NAME": "ghc-x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-validate",
    
    6774
    +      "BIN_DIST_NAME_STAGE3": "ghc-riscv64-linux-deb13-validate",
    
    6771 6775
           "BUILD_FLAVOUR": "validate",
    
    6772 6776
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    6773 6777
           "CROSS_EMULATOR": "qemu-riscv64 -L /usr/riscv64-linux-gnu",
    
    6774
    -      "CROSS_STAGE": "2",
    
    6775 6778
           "CROSS_TARGET": "riscv64-linux-gnu",
    
    6779
    +      "FINAL_CROSS_STAGE": "3",
    
    6776 6780
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    6777 6781
           "RUNTEST_ARGS": "-e config.timeout=900",
    
    6778 6782
           "TEST_ENV": "x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-validate",
    
    ... ... @@ -7662,8 +7666,8 @@
    7662 7666
           "BUILD_FLAVOUR": "validate",
    
    7663 7667
           "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
    
    7664 7668
           "CROSS_EMULATOR": "qemu-loongarch64 -L /usr/loongarch64-linux-gnu",
    
    7665
    -      "CROSS_STAGE": "2",
    
    7666 7669
           "CROSS_TARGET": "loongarch64-linux-gnu",
    
    7670
    +      "FINAL_CROSS_STAGE": "2",
    
    7667 7671
           "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
    
    7668 7672
           "RUNTEST_ARGS": "-e config.timeout=900",
    
    7669 7673
           "TEST_ENV": "x86_64-linux-ubuntu24_04-loongarch-cross_loongarch64-linux-gnu-validate",
    

  • changelog.d/stage3-cross-bindists
    1
    +section: packaging
    
    2
    +synopsis: Fully cross-compiled binary distributions
    
    3
    +mrs: !15417
    
    4
    +issues: #26924
    
    5
    +description: Hadrian can now build cross-compiled binary distributions that run
    
    6
    +  native on another target architecture (e.g. AArch64 -> RISC-V).

  • distrib/configure.ac.in
    ... ... @@ -9,7 +9,7 @@ AC_INIT([The Glorious Glasgow Haskell Compilation System], [@ProjectVersion@], [
    9 9
     dnl See /configure.ac for rationale.
    
    10 10
     AC_PREREQ([2.69])
    
    11 11
     
    
    12
    -AC_CONFIG_MACRO_DIRS([../m4])
    
    12
    +AC_CONFIG_MACRO_DIRS([m4])
    
    13 13
     
    
    14 14
     dnl--------------------------------------------------------------------
    
    15 15
     dnl * Deal with arguments telling us gmp is somewhere odd
    

  • hadrian/src/BindistConfig.hs
    ... ... @@ -24,6 +24,10 @@ crossBindist = BindistConfig { library_stage = Stage2, executable_stage = Stage1
    24 24
     targetBindist ::  BindistConfig
    
    25 25
     targetBindist = BindistConfig { library_stage = Stage2, executable_stage = Stage2 }
    
    26 26
     
    
    27
    +-- | Folder relative to build root ("bindist" or "bindist-stage3")
    
    28
    +bindistFolder :: BindistConfig ->  FilePath
    
    29
    +bindistFolder conf | executable_stage conf == Stage2 = "bindist-stage3"
    
    30
    +bindistFolder _conf = "bindist"
    
    27 31
     
    
    28 32
     -- | The implicit bindist config, if we don't know any better.
    
    29 33
     implicitBindistConfig :: Action BindistConfig
    

  • hadrian/src/Rules/BinaryDist.hs
    ... ... @@ -6,7 +6,6 @@ import Context
    6 6
     import Data.Either
    
    7 7
     import qualified Data.Set as Set
    
    8 8
     import Expression
    
    9
    -import Hadrian.Oracles.Path (fixUnixPathsOnWindows)
    
    10 9
     import Oracles.Flavour
    
    11 10
     import Oracles.Setting
    
    12 11
     import Packages
    
    ... ... @@ -14,66 +13,89 @@ import Rules.Generate (generateSettings)
    14 13
     import Settings
    
    15 14
     import qualified System.Directory.Extra as IO
    
    16 15
     import Settings.Program (programContext)
    
    17
    -import Target
    
    18
    -import Utilities
    
    19 16
     import BindistConfig
    
    20 17
     
    
    21 18
     {-
    
    22 19
     Note [Binary distributions]
    
    23 20
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    24 21
     
    
    25
    -Hadrian produces binary distributions under:
    
    22
    +Hadrian produces binary distributions that run on the build host architecture
    
    23
    +(build == host, target == host || target /= host) under:
    
    26 24
       <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>.tar.xz
    
    27 25
     
    
    28
    -It is generated by creating an archive from:
    
    29
    -  <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/
    
    26
    +For stage3 (build /= host, host == target) bindists, a separate parent folder
    
    27
    +is used:
    
    28
    +  <build root>/bindist-stage3/ghc-<X>.<Y>.<Z>-<arch>-<os>.tar.xz
    
    30 29
     
    
    31
    -It does so by following the steps below.
    
    30
    +While regular bindists are usual same-arch compilers or cross-compilers, stage3
    
    31
    +bindists are cross-compiled compilers.
    
    32 32
     
    
    33
    -- make sure we have a complete stage 2 compiler + haddock
    
    33
    +Bindists are generated by creating an archive from:
    
    34
    +  <build root>/<bindist|bindist-stage3>/ghc-<X>.<Y>.<Z>-<arch>-<os>/
    
    35
    +
    
    36
    +Stage2 cross-compilers are a by-product of creating stage3 cross-compiled
    
    37
    +compilers. The additional build dir (bindist-stage3) lets us keep both, such
    
    38
    +that we can build them in one go on CI.
    
    39
    +Configuration files (e.g. configure script and default.host.target) differ in
    
    40
    +this case and keeping both targets separated also saves us some headache
    
    41
    +dealing with stale files.
    
    42
    +
    
    43
    +This table introduces variables to simplify the following step descriptions:
    
    44
    +
    
    45
    +| compiler kind    | <bindist-dir>  | <executable-stage-dir> | <library-stage-dir> |
    
    46
    +|------------------|----------------|------------------------|---------------------|
    
    47
    +| native           | bindist        | stage1/                | stage1/             |
    
    48
    +| cross-compiler   | bindist        | stage1/                | stage2/             |
    
    49
    +| cross-compiled   | bindist-stage3 | stage2/                | stage2/             |
    
    50
    +
    
    51
    +These are the steps to build a bindist:
    
    52
    +
    
    53
    +- make sure we have a complete compiler + libraries + haddock for the stage(s)
    
    54
    +  to bundle
    
    34 55
     
    
    35 56
     - copy the specific binaries which should be in the bindist to the
    
    36 57
       bin folder and add the version suffix:
    
    37
    -    <build root>/stage1/bin/xxxx
    
    58
    +    <build root>/<executable-stage-dir>/bin/xxxx
    
    38 59
       to
    
    39
    -    <build root/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/bin/xxxx-<VER>
    
    60
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/bin/[<target>-]xxxx-<VER>
    
    61
    +  where the optional <target>- prefix is the cross triple for cross-compilers.
    
    40 62
     
    
    41 63
     - create symlink (or bash) wrapper from unversioned to versioned executable:
    
    42
    -    <build root/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/bin/xxxx
    
    64
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/bin/[<target>-]xxxx
    
    43 65
       points to:
    
    44
    -    <build root/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/bin/xxxx-<VER>
    
    66
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/bin/[<target>-]xxxx-<VER>
    
    45 67
     
    
    46 68
     - copy the lib directories of the compiler we built:
    
    47
    -    <build root>/stage1/lib
    
    69
    +    <build root>/<library-stage-dir>/lib
    
    48 70
       to
    
    49
    -    <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/lib
    
    71
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/lib
    
    50 72
     
    
    51 73
     - copy the generated docs (user guide, haddocks, etc):
    
    52
    -    <build root>/docs/
    
    74
    +    <build root>/doc/
    
    53 75
       to
    
    54
    -    <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/docs/
    
    76
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/doc/
    
    55 77
     
    
    56
    -- use autoreconf to generate a `configure` script from
    
    57
    -  aclocal.m4 and distrib/configure.ac, that we move to:
    
    58
    -    <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/configure
    
    78
    +- use autoreconf to generate a staged `configure` script in
    
    79
    +    <build root>/<executable-stage>/distrib
    
    80
    +  that we move to:
    
    81
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/configure
    
    59 82
     
    
    60 83
     - write a (fixed) Makefile capable of supporting 'make install' to:
    
    61
    -    <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/Makefile
    
    84
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/Makefile
    
    62 85
     
    
    63 86
     - write some (fixed) supporting bash code for the wrapper scripts to:
    
    64
    -    <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/wrappers/<program>
    
    87
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/wrappers/<program>
    
    65 88
     
    
    66 89
       where <program> is the name of the executable that the bash file will
    
    67 90
       help wrapping.
    
    68 91
     
    
    69
    -- copy supporting configure/make related files
    
    70
    -  (see @bindistInstallFiles@) to:
    
    71
    -    <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/<file>
    
    92
    +- copy supporting configure/make related files (see @bindistInstallFiles@) to:
    
    93
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/<file>
    
    72 94
     
    
    73 95
     - create a .tar.xz archive of the directory:
    
    74
    -    <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/
    
    96
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>/
    
    75 97
       at
    
    76
    -    <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>.tar.xz
    
    98
    +    <build root>/<bindist-dir>/ghc-<X>.<Y>.<Z>-<arch>-<os>.tar.xz
    
    77 99
     
    
    78 100
     
    
    79 101
     Note [Wrapper scripts and binary distributions]
    
    ... ... @@ -160,12 +182,12 @@ buildBinDistDir root conf@BindistConfig{..} = do
    160 182
         distDir        <- Context.distDir (vanillaContext library_stage rts)
    
    161 183
     
    
    162 184
         let ghcBuildDir      = root -/- stageString library_stage
    
    163
    -        bindistFilesDir  = root -/- "bindist" -/- ghcVersionPretty
    
    185
    +        bindistFilesDir  = root -/- bindistFolder conf -/- ghcVersionPretty
    
    164 186
             ghcVersionPretty = "ghc-" ++ version ++ "-" ++ targetPlatform
    
    165 187
             rtsIncludeDir    = distDir -/- "include"
    
    166 188
     
    
    167
    -    -- We create the bindist directory at <root>/bindist/ghc-X.Y.Z-platform/
    
    168
    -    -- and populate it with Stage2 build results
    
    189
    +    -- We create the bindist directory at <root>/<bindistFolder>/ghc-X.Y.Z-platform/
    
    190
    +    -- and populate it with build results
    
    169 191
         createDirectory bindistFilesDir
    
    170 192
         createDirectory (bindistFilesDir -/- "bin")
    
    171 193
         createDirectory (bindistFilesDir -/- "lib")
    
    ... ... @@ -231,9 +253,9 @@ buildBinDistDir root conf@BindistConfig{..} = do
    231 253
         -- relocatable. The package DB is always at "package.conf.d" relative to
    
    232 254
         -- the lib dir, matching the known bindist layout.
    
    233 255
         let bindistSettings = bindistFilesDir -/- "lib" -/- "settings"
    
    234
    -        bindistContext = vanillaContext library_stage compiler
    
    256
    +        bindistContext = vanillaContext executable_stage compiler
    
    235 257
         bindistSettingsContent <- interpretInContext bindistContext $
    
    236
    -        generateSettings bindistSettings False "package.conf.d"
    
    258
    +        generateSettings bindistSettings False "package.conf.d" library_stage
    
    237 259
         writeFileAtomic bindistSettings bindistSettingsContent
    
    238 260
     
    
    239 261
         copyDirectory rtsIncludeDir         bindistFilesDir
    
    ... ... @@ -245,10 +267,14 @@ buildBinDistDir root conf@BindistConfig{..} = do
    245 267
         --
    
    246 268
         -- N.B. the ghc-pkg executable may be prefixed with a target triple
    
    247 269
         -- (c.f. #20267).
    
    248
    -
    
    249
    -    -- Not going to work for cross
    
    250
    -    ghcPkgName <- programName (vanillaContext Stage1 ghcPkg)
    
    251
    -    cmd_ (bindistFilesDir -/- "bin" -/- ghcPkgName) ["recache", "--package-db", bindistFilesDir -/- "lib" -/- "package.conf.d" ]
    
    270
    +    -- Recache using the stage1 ghc-pkg executable. This is the unprefixed
    
    271
    +    -- host ghc-pkg for native bindists and the target-triple-prefixed cross
    
    272
    +    -- ghc-pkg for cross bindists; both run on the build host and can handle
    
    273
    +    -- the target package database. The stage3 bindist's package DB is also
    
    274
    +    -- built by the stage1 cross compiler, so stage1 ghc-pkg is correct there
    
    275
    +    -- too.
    
    276
    +    ghcPkgPath <- programPath =<< programContext Stage1 ghcPkg
    
    277
    +    cmd_ ghcPkgPath ["recache", "--package-db", bindistFilesDir -/- "lib" -/- "package.conf.d" ]
    
    252 278
     
    
    253 279
     
    
    254 280
         need ["docs"]
    
    ... ... @@ -344,8 +370,7 @@ bindistRules = do
    344 370
           buildBinDistDir root cfg
    
    345 371
     
    
    346 372
         phony "binary-dist-dir-cross" $ buildBinDistDir root crossBindist
    
    347
    -    -- MP: Not working yet
    
    348
    -    -- phony "binary-dist-dir-stage3" $ buildBinDistDir root targetBindist
    
    373
    +    phony "binary-dist-dir-stage3" $ buildBinDistDir root targetBindist
    
    349 374
     
    
    350 375
         let buildBinDist compressor = do
    
    351 376
               win_host <- isWinHost
    
    ... ... @@ -377,54 +402,27 @@ bindistRules = do
    377 402
           phony (name <> "-dist-xz") $ mk_bindist Xz
    
    378 403
     
    
    379 404
         phony "binary-dist-cross" $ buildBinDistX "binary-dist-dir-cross" "bindist" Xz
    
    380
    -    phony "binary-dist-stage3" $ buildBinDistX "binary-dist-dir-stage3" "bindist" Xz
    
    381
    -
    
    382
    -    -- Prepare binary distribution configure script
    
    383
    -    -- (generated under <ghc root>/distrib/configure by 'autoreconf')
    
    384
    -    root -/- "bindist" -/- "ghc-*" -/- "configure" %> \configurePath -> do
    
    385
    -        need ["distrib" -/- "configure.ac"]
    
    386
    -        ghcRoot <- topDirectory
    
    387
    -        copyFile (ghcRoot -/- "aclocal.m4") (ghcRoot -/- "distrib" -/- "aclocal.m4")
    
    388
    -        copyDirectory (ghcRoot -/- "m4") (ghcRoot -/- "distrib")
    
    389
    -
    
    390
    -        -- Note [Autoreconf unix paths from ACLOCAL_PATH]
    
    391
    -        -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    392
    -        -- On Windows, autoreconf fails when the ACLOCAL_PATH env variable contains Windows-
    
    393
    -        -- style paths. This happens because MSYS2 automatically converts env variables to
    
    394
    -        -- Windows-style paths. To fix this, we convert ACLOCAL_PATH back to Unix style.
    
    395
    -        -- This is done both in the boot Python script and here when building a bindist.
    
    396
    -        win_host <- isWinHost
    
    397
    -        env <- if not win_host
    
    398
    -          then pure []
    
    399
    -          else do
    
    400
    -            aclocalPathMay <- getEnv "ACLOCAL_PATH"
    
    401
    -            case aclocalPathMay of
    
    402
    -              Nothing -> pure []
    
    403
    -              Just aclocalPath -> do
    
    404
    -                unixAclocalPath <- fixUnixPathsOnWindows aclocalPath
    
    405
    -                pure [AddEnv "ACLOCAL_PATH" unixAclocalPath]
    
    406
    -
    
    407
    -        buildWithCmdOptions env $
    
    408
    -            target (vanillaContext Stage1 ghc) (Autoreconf $ ghcRoot -/- "distrib") [] []
    
    409
    -        -- We clean after ourselves, moving the configure script we generated in
    
    410
    -        -- our bindist dir
    
    411
    -        removeFile (ghcRoot -/- "distrib" -/- "aclocal.m4")
    
    412
    -        removeDirectory (ghcRoot -/- "distrib" -/- "m4")
    
    413
    -
    
    414
    -        moveFile (ghcRoot -/- "distrib" -/- "configure") configurePath
    
    415
    -
    
    416
    -    -- Generate the Makefile that enables the "make install" part
    
    417
    -    root -/- "bindist" -/- "ghc-*" -/- "Makefile" %> \makefilePath -> do
    
    418
    -        top <- topDirectory
    
    419
    -        copyFile (top -/- "hadrian" -/- "bindist" -/- "Makefile") makefilePath
    
    420
    -
    
    421
    -    -- Copy various configure-related files needed for a working
    
    422
    -    -- './configure [...] && make install' workflow
    
    423
    -    -- (see the list of files needed in the 'binary-dist' rule above, before
    
    424
    -    -- creating the archive).
    
    425
    -    forM_ bindistInstallFiles $ \file ->
    
    426
    -        root -/- "bindist" -/- "ghc-*" -/- file %> \dest -> do
    
    427
    -            copyFile (fixup file) dest
    
    405
    +    phony "binary-dist-stage3" $ buildBinDistX "binary-dist-dir-stage3" "bindist-stage3" Xz
    
    406
    +
    
    407
    +    forM_ [normalBindist, targetBindist] $ \bindistCfg -> do
    
    408
    +      let bindistFolderName = bindistFolder bindistCfg
    
    409
    +      root -/- bindistFolderName -/- "ghc-*" -/- "configure" %> \configurePath -> do
    
    410
    +          let distribConfigure = root -/- stageString (executable_stage bindistCfg) -/- "distrib" -/- "configure"
    
    411
    +          need [distribConfigure]
    
    412
    +          copyFile distribConfigure configurePath
    
    413
    +
    
    414
    +      -- Generate the Makefile that enables the "make install" part
    
    415
    +      root -/- bindistFolderName -/- "ghc-*" -/- "Makefile" %> \makefilePath -> do
    
    416
    +          top <- topDirectory
    
    417
    +          copyFile (top -/- "hadrian" -/- "bindist" -/- "Makefile") makefilePath
    
    418
    +
    
    419
    +      -- Copy various configure-related files needed for a working
    
    420
    +      -- './configure [...] && make install' workflow
    
    421
    +      -- (see the list of files needed in the 'binary-dist' rule above, before
    
    422
    +      -- creating the archive).
    
    423
    +      forM_ bindistInstallFiles $ \file ->
    
    424
    +          root -/- bindistFolderName -/- "ghc-*" -/- file %> \dest -> do
    
    425
    +              copyFile (fixup file) dest
    
    428 426
     
    
    429 427
       where
    
    430 428
         fixup f | f `elem` ["INSTALL", "README"] = "distrib" -/- f
    
    ... ... @@ -504,7 +502,7 @@ pkgToWrappers stage pkg = do
    504 502
             -- These are the packages which we want to expose to the user and hence
    
    505 503
             -- there are wrappers installed in the bindist.
    
    506 504
           | pkg `elem` [hpcBin, haddock, hp2ps, hsc2hs, ghc, ghcPkg]
    
    507
    -                      -> (:[]) <$> (programName =<< programContext Stage1 pkg)
    
    505
    +                      -> (:[]) <$> (programName =<< programContext stage pkg)
    
    508 506
           | otherwise     -> pure []
    
    509 507
     
    
    510 508
     wrapper :: Stage -> FilePath -> Action String
    
    ... ... @@ -557,7 +555,7 @@ ghciScriptWrapper stage = do
    557 555
     -- | Create a wrapper script calls the executable given as first argument
    
    558 556
     createVersionWrapper :: Stage -> Package -> String -> FilePath -> Action ()
    
    559 557
     createVersionWrapper executable_stage pkg versioned_exe install_path = do
    
    560
    -  ghcPath <- builderPath (Ghc CompileCWithGhc (succStage executable_stage))
    
    558
    +  ghcPath <- builderPath (Ghc CompileCWithGhc executable_stage)
    
    561 559
       top <- topDirectory
    
    562 560
       let version_wrapper_dir = top -/- "hadrian" -/- "bindist" -/- "cwrappers"
    
    563 561
           wrapper_files = [ version_wrapper_dir -/- file | file <- ["version-wrapper.c", "getLocation.c", "cwrapper.c"]]
    

  • hadrian/src/Rules/Generate.hs
    ... ... @@ -9,6 +9,7 @@ import qualified Data.Set as Set
    9 9
     import Base
    
    10 10
     import qualified Context
    
    11 11
     import Expression
    
    12
    +import Hadrian.Oracles.Path (fixUnixPathsOnWindows)
    
    12 13
     import Hadrian.Oracles.TextFile (lookupStageBuildConfig)
    
    13 14
     import Oracles.Flag hiding (arSupportsAtFile, arSupportsDashL)
    
    14 15
     import Oracles.ModuleFiles
    
    ... ... @@ -251,32 +252,51 @@ generateRules = do
    251 252
         (root -/- "ghc-stage2") <~+ ghcWrapper Stage2
    
    252 253
         (root -/- "ghc-stage3") <~+ ghcWrapper Stage3
    
    253 254
     
    
    254
    -    forM_ allStages $ \stage -> do
    
    255
    -        let prefix = root -/- stageString stage -/- "lib"
    
    256
    -            -- For the finalStage, we generate settings for that stage. For
    
    257
    -            -- others we look at the next stage. Why? Because cross-compilers
    
    258
    -            -- require libs from the successor stage, otherwise they are
    
    259
    -            -- compiled for the host and not the target.
    
    260
    -            stage' = if stage /= finalStage then succStage stage else stage
    
    261
    -            go gen file = generate file (semiEmptyTarget stage') gen
    
    255
    +    forM_ allStages $ \buildStage -> do
    
    256
    +        let -- Two stages are in play per rule iteration:
    
    257
    +            --
    
    258
    +            --   * @buildStage@    — loop variable; the settings file is written
    
    259
    +            --                      into @_build/<buildStage>/lib/settings@ and
    
    260
    +            --                      describes the compiler at @compilerStage@.
    
    261
    +            --   * @compilerStage@ — the stage whose @bin/@ holds the compiler
    
    262
    +            --                      the settings file describes; also the
    
    263
    +            --                      ambient 'Expr' stage passed to
    
    264
    +            --                      'generateSettings' (via 'semiEmptyTarget'),
    
    265
    +            --                      so it is the value of @executableStage@
    
    266
    +            --                      inside that function.
    
    267
    +            --
    
    268
    +            -- For a cross-compiler the libs it links against live in the
    
    269
    +            -- /successor/ stage's lib dir; @libraryStage@ (computed in the
    
    270
    +            -- rule body below) is that successor. @compilerStage@ normally
    
    271
    +            -- equals @buildStage@, but at @finalStage@ there is no successor
    
    272
    +            -- to hold its libs, so @compilerStage@ drops to the predecessor
    
    273
    +            -- (the final stage's lib dir merely hosts the predecessor
    
    274
    +            -- cross-compiler's target-arch libs).
    
    275
    +            compilerStage = if buildStage == finalStage
    
    276
    +                              then predStage buildStage
    
    277
    +                              else buildStage
    
    278
    +            prefix = root -/- stageString buildStage -/- "lib"
    
    279
    +            go gen file = generate file (semiEmptyTarget compilerStage) gen
    
    262 280
             (prefix -/- "settings") %> \out -> do
    
    263
    -            let get_pkg_db stg = packageDbPath (PackageDbLoc stg Final)
    
    264
    -            -- For cross, LibDir points to stage' lib dir, so pkgDb must also
    
    265
    -            -- be relative to stage' lib dir.
    
    266
    -            isCross <- crossStage stage
    
    267
    -            let libStage = case stage of
    
    281
    +            -- Stage0 has no library or package DB of its own (the
    
    282
    +            -- bootstrapping compiler uses Stage1's); for any other stage the
    
    283
    +            -- package DB lives where the LibDir redirect points (this stage's
    
    284
    +            -- own lib dir, or the successor's when @buildStage@ is a cross
    
    285
    +            -- stage).
    
    286
    +            isCross <- crossStage buildStage
    
    287
    +            let libraryStage = case buildStage of
    
    268 288
                         Stage0 {} -> Stage1
    
    269
    -                    _         -> if isCross then stage' else stage
    
    270
    -            pkgDb <- get_pkg_db libStage
    
    289
    +                    _         -> if isCross then succStage buildStage else buildStage
    
    290
    +            pkgDb <- packageDbPath (PackageDbLoc libraryStage Final)
    
    271 291
                 -- addTrailingPathSeparator needed: makeRelativeNoSysLink uses
    
    272 292
                 -- splitPath where "lib" and "lib/" are distinct components.
    
    273 293
                 let libTopDir = addTrailingPathSeparator $
    
    274
    -                    if isCross
    
    275
    -                      then root -/- stageString stage' -/- "lib"
    
    276
    -                      else prefix
    
    294
    +                    if isStage0 buildStage
    
    295
    +                      then prefix
    
    296
    +                      else root -/- stageString libraryStage -/- "lib"
    
    277 297
                     relPkgDb = makeRelativeNoSysLink libTopDir pkgDb
    
    278
    -            go (generateSettings out True relPkgDb) out
    
    279
    -        (prefix -/- "targets" -/- "default.target") %> \out -> go (show <$> expr (targetStage (succStage stage))) out
    
    298
    +            go (generateSettings out True relPkgDb libraryStage) out
    
    299
    +        (prefix -/- "targets" -/- "default.target") %> \out -> go (show <$> expr (targetStage (succStage buildStage))) out
    
    280 300
     
    
    281 301
       where
    
    282 302
         file <~+ gen = file %> \out -> generate out emptyTarget gen >> makeExecutable out
    
    ... ... @@ -410,6 +430,7 @@ templateRules = do
    410 430
     
    
    411 431
     bindistRules :: Rules ()
    
    412 432
     bindistRules = do
    
    433
    +  root <- buildRootRules
    
    413 434
       templateRule ("mk" -/- "project.mk") $ mconcat
    
    414 435
         [ interpolateSetting "ProjectName" ProjectName
    
    415 436
         , interpolateSetting "ProjectVersion" ProjectVersion
    
    ... ... @@ -421,43 +442,126 @@ bindistRules = do
    421 442
     
    
    422 443
         , interpolateVar "HostOS_CPP" $ fmap cppify $ interp $ queryHost queryOS
    
    423 444
     
    
    424
    -    , interpolateVar "TargetPlatform" $ getTarget targetPlatformTriple
    
    425
    -    , interpolateVar "TargetPlatform_CPP" $ cppify <$> getTarget targetPlatformTriple
    
    426
    -    , interpolateVar "TargetArch_CPP" $ cppify <$> getTarget queryArch
    
    427
    -    , interpolateVar "TargetOS_CPP" $ cppify <$> getTarget queryOS
    
    428
    -    , interpolateVar "LLVMTarget" $ getTarget tgtLlvmTarget
    
    429
    -    ]
    
    430
    -  templateRule ("distrib" -/- "configure.ac") $ mconcat
    
    431
    -    [ interpolateSetting "ConfiguredEmsdkVersion" EmsdkVersion
    
    432
    -    , interpolateVar "CrossCompilePrefix" $ do
    
    433
    -        crossCompiling <- interp $ getFlag CrossCompiling
    
    434
    -        tpf <- setting TargetPlatformFull
    
    435
    -        pure $ if crossCompiling then tpf <> "-" else ""
    
    436
    -    , interpolateVar "LeadingUnderscore" $ yesNo <$> getTarget tgtSymbolsHaveLeadingUnderscore
    
    437
    -    , interpolateSetting "LlvmMaxVersion" LlvmMaxVersion
    
    438
    -    , interpolateSetting "LlvmMinVersion" LlvmMinVersion
    
    439
    -    , interpolateVar "LlvmTarget" $ getTarget tgtLlvmTarget
    
    440
    -    , interpolateSetting "ProjectVersion" ProjectVersion
    
    441
    -    , interpolateVar "EnableDistroToolchain" $ interp (staged (lookupStageBuildConfig "settings-use-distro-mingw"))
    
    442
    -    , interpolateVar "TablesNextToCode" $ yesNo <$> getTarget tgtTablesNextToCode
    
    443
    -    , interpolateVar "TargetHasLibm" $ yesNo <$> getTarget tgtHasLibm
    
    444
    -    , interpolateVar "TargetPlatform" $ getTarget targetPlatformTriple
    
    445
    -    , interpolateVar "BuildPlatform"  $ interp $ queryBuild targetPlatformTriple
    
    446
    -    , interpolateVar "HostPlatform"   $ interp $ queryHost targetPlatformTriple
    
    447
    -    , interpolateVar "TargetWordBigEndian" $ getTarget isBigEndian
    
    448
    -    , interpolateVar "TargetWordSize" $ getTarget wordSize
    
    449
    -    , interpolateVar "Unregisterised" $ yesNo <$> getTarget tgtUnregisterised
    
    450
    -    , interpolateVar "UseLibdw" $ fmap yesNo $ interp $ staged (fmap (isJust . tgtRTSWithLibdw) . targetStage)
    
    451
    -    , interpolateVar "UseLibffiForAdjustors" $ yesNo <$> getTarget tgtUseLibffiForAdjustors
    
    452
    -    , interpolateVar "BaseUnitId" $ pkgUnitId Stage1 base
    
    453
    -    , interpolateVar "GhcWithSMP" $ yesNo <$> targetSupportsSMP Stage2
    
    454
    -    , interpolateVar "TargetPlatformFull" (setting TargetPlatformFull)
    
    455
    -    , interpolateVar "BuildPlatformFull" (setting BuildPlatformFull)
    
    456
    -    , interpolateVar "HostPlatformFull"  (setting HostPlatformFull)
    
    445
    +    -- Stage2 always targets the final architecture. Thus, we can use a
    
    446
    +    -- constant stage here.
    
    447
    +    , interpolateVar "TargetPlatform" $ getTarget Stage2 targetPlatformTriple
    
    448
    +    , interpolateVar "TargetPlatform_CPP" $ cppify <$> getTarget Stage2 targetPlatformTriple
    
    449
    +    , interpolateVar "TargetArch_CPP" $ cppify <$> getTarget Stage2 queryArch
    
    450
    +    , interpolateVar "TargetOS_CPP" $ cppify <$> getTarget Stage2 queryOS
    
    451
    +    , interpolateVar "LLVMTarget" $ getTarget Stage2 tgtLlvmTarget
    
    457 452
         ]
    
    453
    +  forM_ [Stage1, Stage2] $ \stage ->
    
    454
    +    let crossStageInterps = Interpolations $ do
    
    455
    +          isCrossStage <- crossStage stage
    
    456
    +          targetPlatform <- setting TargetPlatformFull
    
    457
    +          -- For cross-compiled compilers we need to pretend that they were
    
    458
    +          -- build on the target. For regular commpilers we can assume that:
    
    459
    +          -- build == host == target
    
    460
    +          buildPlatform <-
    
    461
    +            if isCrossStage
    
    462
    +              then
    
    463
    +                interp $ queryBuild targetPlatformTriple
    
    464
    +              else getTarget stage targetPlatformTriple
    
    465
    +          hostPlatform <-
    
    466
    +            if isCrossStage
    
    467
    +              then
    
    468
    +                interp $ queryHost targetPlatformTriple
    
    469
    +              else getTarget stage targetPlatformTriple
    
    470
    +          baseUnitId <- pkgUnitId (if isCrossStage then succStage stage else stage) base
    
    471
    +          buildPlatformFull <- if isCrossStage then setting BuildPlatformFull else setting TargetPlatformFull
    
    472
    +          hostPlatformFull <- if isCrossStage then setting HostPlatformFull else setting TargetPlatformFull
    
    473
    +          pure
    
    474
    +            [ ("CrossCompilePrefix", if isCrossStage then targetPlatform <> "-" else "")
    
    475
    +            , ("TargetPlatformFull", targetPlatform)
    
    476
    +            , ("BuildPlatform", buildPlatform)
    
    477
    +            , ("HostPlatform", hostPlatform)
    
    478
    +            , ("BaseUnitId", baseUnitId)
    
    479
    +            , ("BuildPlatformFull", buildPlatformFull)
    
    480
    +            , ("HostPlatformFull", hostPlatformFull)
    
    481
    +            ]
    
    482
    +    in templateRuleFrom
    
    483
    +      ("distrib" -/- "configure.ac" <.> "in")
    
    484
    +      (root -/- stageString stage -/- "distrib" -/- "configure.ac")
    
    485
    +      $ mconcat
    
    486
    +      [ interpolateSetting "ConfiguredEmsdkVersion" EmsdkVersion
    
    487
    +      , interpolateVar "LeadingUnderscore" $ yesNo <$> getLibTarget stage tgtSymbolsHaveLeadingUnderscore
    
    488
    +      , interpolateSetting "LlvmMaxVersion" LlvmMaxVersion
    
    489
    +      , interpolateSetting "LlvmMinVersion" LlvmMinVersion
    
    490
    +      , interpolateVar "LlvmTarget" $ getLibTarget stage tgtLlvmTarget
    
    491
    +      , interpolateSetting "ProjectVersion" ProjectVersion
    
    492
    +      , interpolateVar "EnableDistroToolchain" $ interp (staged (lookupStageBuildConfig "settings-use-distro-mingw"))
    
    493
    +      , interpolateVar "TablesNextToCode" $ yesNo <$> getLibTarget stage tgtTablesNextToCode
    
    494
    +      , interpolateVar "TargetHasLibm" $ yesNo <$> getLibTarget stage tgtHasLibm
    
    495
    +      , interpolateVar "TargetPlatform" $ getLibTarget stage targetPlatformTriple
    
    496
    +      , interpolateVar "TargetWordBigEndian" $ getLibTarget stage isBigEndian
    
    497
    +      , interpolateVar "TargetWordSize" $ getLibTarget stage wordSize
    
    498
    +      , interpolateVar "Unregisterised" $ yesNo <$> getLibTarget stage tgtUnregisterised
    
    499
    +      , interpolateVar "UseLibdw" $ yesNo <$> getLibTarget stage (isJust . tgtRTSWithLibdw)
    
    500
    +      , interpolateVar "UseLibffiForAdjustors" $ yesNo <$> getLibTarget stage tgtUseLibffiForAdjustors
    
    501
    +      , interpolateVar "GhcWithSMP" $ yesNo <$> libStageSupportsSMP stage
    
    502
    +      , crossStageInterps
    
    503
    +      ]
    
    504
    +
    
    505
    +  -- We can build two kinds of bindists: Regular Stage2 (including
    
    506
    +  -- cross-compilers) and fully cross-compiled Stage3. To avoid
    
    507
    +  -- race-conditions, stale files, etc. build the `configure` scripts as part
    
    508
    +  -- of the stage's _build files. This requires copying several files such that
    
    509
    +  -- they are available to the autoconf run.
    
    510
    +  forM_ [Stage1, Stage2] $ \stage -> do
    
    511
    +    let distribDir = root -/- stageString stage -/- "distrib"
    
    512
    +
    
    513
    +    distribDir -/- "aclocal.m4" %> \out -> do
    
    514
    +      top <- topDirectory
    
    515
    +      copyFile (top -/- "aclocal.m4") out
    
    516
    +
    
    517
    +    forM_ ["config.sub", "config.guess", "install-sh"] $ \f ->
    
    518
    +      distribDir -/- f %> \out -> do
    
    519
    +        top <- topDirectory
    
    520
    +        copyFile (top -/- f) out
    
    521
    +
    
    522
    +    distribDir -/- "m4/*.m4" %> \out -> do
    
    523
    +      top <- topDirectory
    
    524
    +      copyFile (top -/- "m4" -/- takeFileName out) out
    
    525
    +
    
    526
    +    distribDir -/- "configure" %> \_ -> do
    
    527
    +      top    <- topDirectory
    
    528
    +      m4Files <- getDirectoryFiles (top -/- "m4") ["*.m4"]
    
    529
    +      need $ [ distribDir -/- "configure.ac"
    
    530
    +             , distribDir -/- "config.sub"
    
    531
    +             , distribDir -/- "config.guess"
    
    532
    +             , distribDir -/- "install-sh"
    
    533
    +             , distribDir -/- "aclocal.m4"
    
    534
    +             ]
    
    535
    +           ++ [ distribDir -/- "m4" -/- takeFileName f | f <- m4Files ]
    
    536
    +
    
    537
    +      -- Note [Autoreconf unix paths from ACLOCAL_PATH]
    
    538
    +      -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    539
    +      -- On Windows, autoreconf fails when the ACLOCAL_PATH env variable
    
    540
    +      -- contains Windows-style paths. MSYS2 auto-converts env vars to
    
    541
    +      -- Windows-style, so we convert ACLOCAL_PATH back to Unix style here.
    
    542
    +      win_host <- isWinHost
    
    543
    +      env <- if not win_host
    
    544
    +        then pure []
    
    545
    +        else do
    
    546
    +          aclocalPathMay <- getEnv "ACLOCAL_PATH"
    
    547
    +          case aclocalPathMay of
    
    548
    +            Nothing -> pure []
    
    549
    +            Just aclocalPath -> do
    
    550
    +              unixAclocalPath <- fixUnixPathsOnWindows aclocalPath
    
    551
    +              pure [AddEnv "ACLOCAL_PATH" unixAclocalPath]
    
    552
    +
    
    553
    +      buildWithCmdOptions env $
    
    554
    +        target (vanillaContext stage ghc) (Autoreconf distribDir) [] []
    
    458 555
       where
    
    459 556
         interp = interpretInContext (semiEmptyTarget Stage2)
    
    460
    -    getTarget = interp . queryTarget Stage2
    
    557
    +    getTarget stage = interp . queryTarget stage
    
    558
    +    getLibTarget executableStage f = do
    
    559
    +      isCross <- crossStage executableStage
    
    560
    +      getTarget (if isCross then succStage executableStage else executableStage) f
    
    561
    +    -- | 'targetSupportsSMP' lifted to the library stage (see 'getLibTarget').
    
    562
    +    libStageSupportsSMP stage = do
    
    563
    +      isCross <- crossStage stage
    
    564
    +      targetSupportsSMP (if isCross then succStage stage else stage)
    
    461 565
     
    
    462 566
     -- | Given a 'String' replace characters '.' and '-' by underscores ('_') so that
    
    463 567
     -- the resulting 'String' is a valid C preprocessor identifier.
    
    ... ... @@ -479,42 +583,40 @@ ghcWrapper stage = do
    479 583
     
    
    480 584
     -- | Generate settings file, optionally including @LibDir@.
    
    481 585
     --
    
    586
    +-- Describes the compiler whose stage is the ambient 'Expr' context
    
    587
    +-- (available here as @executableStage@ via 'getStage'). The @libraryStage@
    
    588
    +-- argument is the stage whose lib dir holds the libraries the described
    
    589
    +-- compiler links against — used both for the @base@ unit-id lookup and for
    
    590
    +-- the @LibDir@ entry. It usually equals @executableStage@ but differs when
    
    591
    +-- the compiler links against libraries from a different stage (cross
    
    592
    +-- compilers, or the Stage0 bootstrap compiler using Stage1's libraries).
    
    593
    +--
    
    482 594
     -- @rel_pkg_db@: package DB path relative to the lib dir (e.g.
    
    483 595
     -- "package.conf.d"). Callers supply the correct relative path. For bindists
    
    484
    --- the layout is known statically; for in-tree builds callers compute it. For
    
    485
    --- bindists, we omit @LibDir@ so it defaults to @topDir@ at runtime.
    
    486
    -generateSettings :: FilePath -> Bool -> FilePath -> Expr String
    
    487
    -generateSettings settingsFile includeLibDir rel_pkg_db = do
    
    596
    +-- the layout is known statically; for in-tree builds callers compute it.
    
    597
    +-- For bindists, we omit @LibDir@ so it defaults to @topDir@ at runtime.
    
    598
    +generateSettings :: FilePath -> Bool -> FilePath -> Stage -> Expr String
    
    599
    +generateSettings settingsFile includeLibDir rel_pkg_db libraryStage = do
    
    488 600
         ctx <- getContext
    
    489
    -    stage <- getStage
    
    601
    +    executableStage <- getStage
    
    602
    +
    
    603
    +    base_unit_id <- expr $ pkgUnitId libraryStage base
    
    490 604
     
    
    491
    -    -- The unit-id of the base package which is always linked against (#25382)
    
    492
    -    base_unit_id <- expr $ do
    
    493
    -      case stage of
    
    494
    -        Stage0 {} -> error "Unable to generate settings for stage0"
    
    495
    -        Stage1 -> pkgUnitId Stage1 base
    
    496
    -        Stage2 -> pkgUnitId Stage1 base
    
    497
    -        Stage3 -> pkgUnitId Stage2 base
    
    498
    -
    
    499
    -    -- For cross compilers, LibDir points to the succeeding stage's lib dir
    
    500
    -    -- (which contains the target architecture's libraries). For non-cross,
    
    501
    -    -- it points to the preceding stage's lib dir as usual.
    
    502
    -    let compilerStage = predStage stage  -- the GHC that builds packages in this stage
    
    503
    -    isCrossLibDir <- expr $ crossStage compilerStage
    
    504
    -    let stage_dir_stage = if isCrossLibDir then stage else compilerStage
    
    505
    -
    
    506
    -    -- addTrailingPathSeparator is needed because makeRelativeNoSysLink uses
    
    507
    -    -- splitPath internally, where "lib" and "lib/" are distinct components.
    
    508
    -    lib_topDir :: FilePath <- expr $ addTrailingPathSeparator <$> stageLibPath stage_dir_stage
    
    605
    +    lib_topDir :: FilePath <- expr $ addTrailingPathSeparator <$> stageLibPath libraryStage
    
    509 606
         let rel_lib_topDir = makeRelativeNoSysLink (dropFileName settingsFile) lib_topDir
    
    510 607
     
    
    511 608
         settings <- traverse sequence $
    
    512
    -          [ ("unlit command", ("$topdir/../bin/" <>) <$> expr (programName (ctx { Context.package = unlit, Context.stage = compilerStage })))
    
    513
    -          , ("Use interpreter", expr $ yesNo <$> ghcWithInterpreter compilerStage)
    
    514
    -          -- Hard-coded as Cabal queries these to determine way support and we
    
    515
    -          -- need to always advertise all ways when bootstrapping.
    
    516
    -          -- The settings file is generated at install time when installing a bindist.
    
    517
    -          , ("RTS ways", unwords . map show . Set.toList <$> getRtsWays)
    
    609
    +          [ ("unlit command", ("$topdir/../bin/" <>) <$> expr (programName (ctx { Context.package = unlit })))
    
    610
    +          , ("Use interpreter", expr $ yesNo <$> ghcWithInterpreter executableStage)
    
    611
    +          -- Advertise the RTS ways that will actually ship with the compiler
    
    612
    +          -- described by this settings file, i.e. the ways the @libraryStage@
    
    613
    +          -- RTS is built with. Cabal queries this to decide which library ways
    
    614
    +          -- the compiler supports (see
    
    615
    +          -- 'Distribution.Simple.Compiler.waySupported'); under-advertising
    
    616
    +          -- causes Cabal to silently drop flags like
    
    617
    +          -- @--enable-profiling-shared@.
    
    618
    +          -- The settings file is regenerated at install time when installing a bindist.
    
    619
    +          , ("RTS ways", unwords . map show . Set.toList <$> expr (interpretInContext (vanillaContext libraryStage rts) getRtsWays))
    
    518 620
               , ("Relative Global Package DB", pure rel_pkg_db)
    
    519 621
               , ("base unit-id", pure base_unit_id)
    
    520 622
               ]