Sven Tennie pushed to branch wip/supersven/hadrian-cross-stage3 at Glasgow Haskell Compiler / GHC
Commits:
-
d748b106
by Sven Tennie at 2026-07-26T19:42:56+02:00
-
749b92da
by Sven Tennie at 2026-07-26T19:42:56+02:00
8 changed files:
- .gitignore
- .gitlab/ci.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- distrib/configure.ac.in
- hadrian/src/BindistConfig.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/Generate.hs
Changes:
| ... | ... | @@ -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
|
| ... | ... | @@ -575,7 +575,15 @@ function build_hadrian() { |
| 575 | 575 | |
| 576 | 576 | case "${CROSS_STAGE:-2}" in
|
| 577 | 577 | 2) BINDIST_TARGET="binary-dist";;
|
| 578 | - 3) BINDIST_TARGET="binary-dist-stage3";;
|
|
| 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 "CROSS_STAGE=3 requires BIN_DIST_NAME_STAGE3 to be set"
|
|
| 585 | + fi
|
|
| 586 | + ;;
|
|
| 579 | 587 | *) fail "Unknown CROSS_STAGE, must be 2 or 3";;
|
| 580 | 588 | esac
|
| 581 | 589 | |
| ... | ... | @@ -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 [[ "${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 [[ "${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 \
|
| ... | ... | @@ -159,7 +159,7 @@ data BuildConfig |
| 159 | 159 | , withNuma :: Bool
|
| 160 | 160 | , withZstd :: Bool
|
| 161 | 161 | , crossTarget :: Maybe String
|
| 162 | - , crossStage :: Maybe Int
|
|
| 162 | + , crossStage :: Maybe FinalCrossStage
|
|
| 163 | 163 | , crossEmulator :: CrossEmulator
|
| 164 | 164 | , configureWrapper :: Maybe String
|
| 165 | 165 | , fullyStatic :: Bool
|
| ... | ... | @@ -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 distrubutions 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 | + , crossStage = Just crossStage
|
|
| 285 | 298 | , crossEmulator = emulator
|
| 286 | 299 | , configureWrapper = configure_wrapper
|
| 287 | 300 | }
|
| ... | ... | @@ -356,6 +369,17 @@ archName I386 = "i386" |
| 356 | 369 | binDistName :: Arch -> Opsys -> BuildConfig -> String
|
| 357 | 370 | binDistName arch opsys bc = "ghc-" ++ testEnv arch opsys bc
|
| 358 | 371 | |
| 372 | +-- | The bindist name for the stage3 (target) artifact produced by a combined
|
|
| 373 | +-- cross job (crossStage == Just 3). This preserves the naming convention
|
|
| 374 | +-- expected by downstream consumers.
|
|
| 375 | +binDistNameStage3 :: Arch -> Opsys -> BuildConfig -> String
|
|
| 376 | +binDistNameStage3 arch opsys bc = "ghc-" ++ intercalate "-" (concat
|
|
| 377 | + [ [ archName arch, opsysName opsys ]
|
|
| 378 | + , ["cross_"++triple | Just triple <- pure (crossTarget bc) ]
|
|
| 379 | + , ["stage3"]
|
|
| 380 | + , [flavourString (mkJobFlavour bc)]
|
|
| 381 | + ])
|
|
| 382 | + |
|
| 359 | 383 | -- | Test env should create a string which changes whenever the 'BuildConfig' changes.
|
| 360 | 384 | -- Either the change is reflected by modifying the flavourString or directly (as is
|
| 361 | 385 | -- the case for settings which affect environment variables)
|
| ... | ... | @@ -883,13 +907,16 @@ job arch opsys buildConfig = NamedJob { name = jobName, jobInfo = Job {..} } |
| 883 | 907 | [ opsysVariables arch opsys
|
| 884 | 908 | , "TEST_ENV" =: testEnv arch opsys buildConfig
|
| 885 | 909 | , "BIN_DIST_NAME" =: binDistName arch opsys buildConfig
|
| 910 | + , if crossStage buildConfig == Just Stage3
|
|
| 911 | + then "BIN_DIST_NAME_STAGE3" =: binDistNameStage3 arch opsys buildConfig
|
|
| 912 | + else mempty
|
|
| 886 | 913 | , "BUILD_FLAVOUR" =: flavourString jobFlavour
|
| 887 | 914 | , "BIGNUM_BACKEND" =: bignumString (bignumBackend buildConfig)
|
| 888 | 915 | , "CONFIGURE_ARGS" =: configureArgsStr buildConfig
|
| 889 | 916 | , "INSTALL_CONFIGURE_ARGS" =: "--enable-strict-ghc-toolchain-check"
|
| 890 | 917 | , maybe mempty ("CONFIGURE_WRAPPER" =:) (configureWrapper buildConfig)
|
| 891 | 918 | , maybe mempty ("CROSS_TARGET" =:) (crossTarget buildConfig)
|
| 892 | - , maybe mempty (("CROSS_STAGE" =:) . show) (crossStage buildConfig)
|
|
| 919 | + , maybe mempty (("CROSS_STAGE" =:) . show . crossStageToInt) (crossStage buildConfig)
|
|
| 893 | 920 | , case crossEmulator buildConfig of
|
| 894 | 921 | NoEmulator
|
| 895 | 922 | -- we need an emulator but it isn't set. Won't run the testsuite
|
| ... | ... | @@ -922,6 +949,11 @@ job arch opsys buildConfig = NamedJob { name = jobName, jobInfo = Job {..} } |
| 922 | 949 | trim :: String -> String
|
| 923 | 950 | trim = dropWhileEnd isSpace . dropWhile isSpace
|
| 924 | 951 | |
| 952 | + stage3Artifacts
|
|
| 953 | + | crossStage buildConfig == Just Stage3 =
|
|
| 954 | + [binDistNameStage3 arch opsys buildConfig ++ ".tar.xz"]
|
|
| 955 | + | otherwise = []
|
|
| 956 | + |
|
| 925 | 957 | -- Keep in sync with the exclude list in `function clean()` in
|
| 926 | 958 | -- `.gitlab/ci.sh`!
|
| 927 | 959 | jobArtifacts = Artifacts
|
| ... | ... | @@ -930,6 +962,7 @@ job arch opsys buildConfig = NamedJob { name = jobName, jobInfo = Job {..} } |
| 930 | 962 | , artifactPaths = [binDistName arch opsys buildConfig ++ ".tar.xz"
|
| 931 | 963 | ,"junit.xml"
|
| 932 | 964 | ,"unexpected-test-output.tar.gz"]
|
| 965 | + ++ stage3Artifacts
|
|
| 933 | 966 | , artifactsWhen = ArtifactsAlways
|
| 934 | 967 | }
|
| 935 | 968 | |
| ... | ... | @@ -1288,13 +1321,13 @@ alpine_aarch64 = [ |
| 1288 | 1321 | cross_jobs :: [JobGroup Job]
|
| 1289 | 1322 | cross_jobs = [
|
| 1290 | 1323 | -- x86 -> aarch64
|
| 1291 | - validateBuilds Amd64 (Linux Debian13) (crossConfig "aarch64-linux-gnu" (Emulator "qemu-aarch64 -L /usr/aarch64-linux-gnu") Nothing)
|
|
| 1324 | + validateBuilds Amd64 (Linux Debian13) (crossConfig "aarch64-linux-gnu" (Emulator "qemu-aarch64 -L /usr/aarch64-linux-gnu") Nothing Stage2)
|
|
| 1292 | 1325 | |
| 1293 | - -- x86_64 -> riscv
|
|
| 1294 | - , addValidateRule RiscV (validateBuilds Amd64 (Linux Debian13Riscv) (crossConfig "riscv64-linux-gnu" (Emulator "qemu-riscv64 -L /usr/riscv64-linux-gnu") Nothing))
|
|
| 1326 | + -- x86_64 (build) -> riscv64 (host/target)
|
|
| 1327 | + , addValidateRule RiscV (validateBuilds Amd64 (Linux Debian13Riscv) (crossConfig "riscv64-linux-gnu" (Emulator "qemu-riscv64 -L /usr/riscv64-linux-gnu") Nothing Stage3))
|
|
| 1295 | 1328 | |
| 1296 | 1329 | -- x86_64 -> loongarch64
|
| 1297 | - , addValidateRule LoongArch64 (validateBuilds Amd64 (Linux Ubuntu2404LoongArch64) (crossConfig "loongarch64-linux-gnu" (Emulator "qemu-loongarch64 -L /usr/loongarch64-linux-gnu") Nothing))
|
|
| 1330 | + , addValidateRule LoongArch64 (validateBuilds Amd64 (Linux Ubuntu2404LoongArch64) (crossConfig "loongarch64-linux-gnu" (Emulator "qemu-loongarch64 -L /usr/loongarch64-linux-gnu") Nothing Stage2))
|
|
| 1298 | 1331 | |
| 1299 | 1332 | -- Javascript
|
| 1300 | 1333 | , addValidateRule JSBackend (validateBuilds Amd64 (Linux Debian11Js) javascriptConfig)
|
| ... | ... | @@ -1315,7 +1348,7 @@ cross_jobs = [ |
| 1315 | 1348 | (validateBuilds AArch64 (Linux Debian12Wine) (winAarch64Config {llvmBootstrap = True}))
|
| 1316 | 1349 | ]
|
| 1317 | 1350 | where
|
| 1318 | - javascriptConfig = (crossConfig "javascript-unknown-ghcjs" (NoEmulatorNeeded TimeoutIncrease) (Just "emconfigure"))
|
|
| 1351 | + javascriptConfig = (crossConfig "javascript-unknown-ghcjs" (NoEmulatorNeeded TimeoutIncrease) (Just "emconfigure") Stage2)
|
|
| 1319 | 1352 | { bignumBackend = Native }
|
| 1320 | 1353 | |
| 1321 | 1354 | makeWinArmJobs = modifyJobs
|
| ... | ... | @@ -1354,7 +1387,7 @@ cross_jobs = [ |
| 1354 | 1387 | llvm_prefix = "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-"
|
| 1355 | 1388 | cflags = "-fuse-ld=" ++ llvm_prefix ++ "ld --rtlib=compiler-rt"
|
| 1356 | 1389 | |
| 1357 | - winAarch64Config = (crossConfig "aarch64-unknown-mingw32" (Emulator "/opt/wine-arm64ec-msys2-deb12/bin/wine") Nothing)
|
|
| 1390 | + winAarch64Config = (crossConfig "aarch64-unknown-mingw32" (Emulator "/opt/wine-arm64ec-msys2-deb12/bin/wine") Nothing Stage2)
|
|
| 1358 | 1391 | { bignumBackend = Native }
|
| 1359 | 1392 | |
| 1360 | 1393 | make_wasm_jobs cfg =
|
| ... | ... | @@ -1367,7 +1400,7 @@ cross_jobs = [ |
| 1367 | 1400 | $ addValidateRule WasmBackend $ validateBuilds Amd64 (Linux AlpineWasm) cfg
|
| 1368 | 1401 | |
| 1369 | 1402 | wasm_build_config =
|
| 1370 | - (crossConfig "wasm32-wasi" (NoEmulatorNeeded NoTimeoutIncrease) Nothing)
|
|
| 1403 | + (crossConfig "wasm32-wasi" (NoEmulatorNeeded NoTimeoutIncrease) Nothing Stage2)
|
|
| 1371 | 1404 | { hostFullyStatic = True
|
| 1372 | 1405 | , buildFlavour = Release -- TODO: This needs to be validate but wasm backend doesn't pass yet
|
| 1373 | 1406 | , textWithSIMDUTF = True
|
| ... | ... | @@ -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-x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-stage3-validate.tar.xz"
|
|
| 2754 | 2755 | ],
|
| 2755 | 2756 | "reports": {
|
| 2756 | 2757 | "junit": "junit.xml"
|
| ... | ... | @@ -2792,10 +2793,11 @@ |
| 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-x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-stage3-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",
|
|
| 2800 | + "CROSS_STAGE": "3",
|
|
| 2799 | 2801 | "CROSS_TARGET": "riscv64-linux-gnu",
|
| 2800 | 2802 | "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
|
| 2801 | 2803 | "RUNTEST_ARGS": "-e config.timeout=900",
|
| ... | ... | @@ -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-x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-stage3-validate.tar.xz"
|
|
| 6730 | 6733 | ],
|
| 6731 | 6734 | "reports": {
|
| 6732 | 6735 | "junit": "junit.xml"
|
| ... | ... | @@ -6768,10 +6771,11 @@ |
| 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-x86_64-linux-deb13-riscv-cross_riscv64-linux-gnu-stage3-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",
|
|
| 6778 | + "CROSS_STAGE": "3",
|
|
| 6775 | 6779 | "CROSS_TARGET": "riscv64-linux-gnu",
|
| 6776 | 6780 | "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
|
| 6777 | 6781 | "RUNTEST_ARGS": "-e config.timeout=900",
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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 | writeFile' 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,32 @@ 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 | + stg = executable_stage bindistCfg
|
|
| 410 | + -- Copy the per-stage 'configure' (produced by autoreconf in Generate.hs)
|
|
| 411 | + -- from the build distrib dir into the bindist. Generating it there keeps
|
|
| 412 | + -- the autoreconf inputs (configure.ac, aclocal.m4, m4/*.m4) next to the
|
|
| 413 | + -- configure script and lets Shake track their changes correctly.
|
|
| 414 | + root -/- bindistFolderName -/- "ghc-*" -/- "configure" %> \configurePath -> do
|
|
| 415 | + let distribConfigure = root -/- stageString stg -/- "distrib" -/- "configure"
|
|
| 416 | + need [distribConfigure]
|
|
| 417 | + copyFile distribConfigure configurePath
|
|
| 418 | + |
|
| 419 | + -- Generate the Makefile that enables the "make install" part
|
|
| 420 | + root -/- bindistFolderName -/- "ghc-*" -/- "Makefile" %> \makefilePath -> do
|
|
| 421 | + top <- topDirectory
|
|
| 422 | + copyFile (top -/- "hadrian" -/- "bindist" -/- "Makefile") makefilePath
|
|
| 423 | + |
|
| 424 | + -- Copy various configure-related files needed for a working
|
|
| 425 | + -- './configure [...] && make install' workflow
|
|
| 426 | + -- (see the list of files needed in the 'binary-dist' rule above, before
|
|
| 427 | + -- creating the archive).
|
|
| 428 | + forM_ bindistInstallFiles $ \file ->
|
|
| 429 | + root -/- bindistFolderName -/- "ghc-*" -/- file %> \dest -> do
|
|
| 430 | + copyFile (fixup file) dest
|
|
| 428 | 431 | |
| 429 | 432 | where
|
| 430 | 433 | fixup f | f `elem` ["INSTALL", "README"] = "distrib" -/- f
|
| ... | ... | @@ -504,7 +507,7 @@ pkgToWrappers stage pkg = do |
| 504 | 507 | -- These are the packages which we want to expose to the user and hence
|
| 505 | 508 | -- there are wrappers installed in the bindist.
|
| 506 | 509 | | pkg `elem` [hpcBin, haddock, hp2ps, hsc2hs, ghc, ghcPkg]
|
| 507 | - -> (:[]) <$> (programName =<< programContext Stage1 pkg)
|
|
| 510 | + -> (:[]) <$> (programName =<< programContext stage pkg)
|
|
| 508 | 511 | | otherwise -> pure []
|
| 509 | 512 | |
| 510 | 513 | wrapper :: Stage -> FilePath -> Action String
|
| ... | ... | @@ -557,7 +560,11 @@ ghciScriptWrapper stage = do |
| 557 | 560 | -- | Create a wrapper script calls the executable given as first argument
|
| 558 | 561 | createVersionWrapper :: Stage -> Package -> String -> FilePath -> Action ()
|
| 559 | 562 | createVersionWrapper executable_stage pkg versioned_exe install_path = do
|
| 560 | - ghcPath <- builderPath (Ghc CompileCWithGhc (succStage executable_stage))
|
|
| 563 | + -- The wrapper compiler must run on the build host. For the stage3 target
|
|
| 564 | + -- bindist executable_stage is Stage2, whose successor would be the
|
|
| 565 | + -- target-native Stage3 compiler; cap the wrapper stage at Stage2.
|
|
| 566 | + let wrapperGhcStage = min Stage2 (succStage executable_stage)
|
|
| 567 | + ghcPath <- builderPath (Ghc CompileCWithGhc wrapperGhcStage)
|
|
| 561 | 568 | top <- topDirectory
|
| 562 | 569 | let version_wrapper_dir = top -/- "hadrian" -/- "bindist" -/- "cwrappers"
|
| 563 | 570 | wrapper_files = [ version_wrapper_dir -/- file | file <- ["version-wrapper.c", "getLocation.c", "cwrapper.c"]]
|
| ... | ... | @@ -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,119 @@ 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
|
|
| 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
|
|
| 429 | 452 | ]
|
| 430 | - templateRule ("distrib" -/- "configure.ac") $ mconcat
|
|
| 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
|
|
| 431 | 486 | [ 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
|
|
| 487 | + , interpolateVar "LeadingUnderscore" $ yesNo <$> getTarget stage tgtSymbolsHaveLeadingUnderscore
|
|
| 437 | 488 | , interpolateSetting "LlvmMaxVersion" LlvmMaxVersion
|
| 438 | 489 | , interpolateSetting "LlvmMinVersion" LlvmMinVersion
|
| 439 | - , interpolateVar "LlvmTarget" $ getTarget tgtLlvmTarget
|
|
| 490 | + , interpolateVar "LlvmTarget" $ getTarget stage tgtLlvmTarget
|
|
| 440 | 491 | , interpolateSetting "ProjectVersion" ProjectVersion
|
| 441 | 492 | , 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
|
|
| 493 | + , interpolateVar "TablesNextToCode" $ yesNo <$> getTarget stage tgtTablesNextToCode
|
|
| 494 | + , interpolateVar "TargetHasLibm" $ yesNo <$> getTarget stage tgtHasLibm
|
|
| 495 | + , interpolateVar "TargetPlatform" $ getTarget stage targetPlatformTriple
|
|
| 496 | + , interpolateVar "TargetWordBigEndian" $ getTarget stage isBigEndian
|
|
| 497 | + , interpolateVar "TargetWordSize" $ getTarget stage wordSize
|
|
| 498 | + , interpolateVar "Unregisterised" $ yesNo <$> getTarget stage tgtUnregisterised
|
|
| 450 | 499 | , 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)
|
|
| 500 | + , interpolateVar "UseLibffiForAdjustors" $ yesNo <$> getTarget stage tgtUseLibffiForAdjustors
|
|
| 501 | + , interpolateVar "GhcWithSMP" $ yesNo <$> targetSupportsSMP stage
|
|
| 502 | + , crossStageInterps
|
|
| 457 | 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
|
|
| 461 | 558 | |
| 462 | 559 | -- | Given a 'String' replace characters '.' and '-' by underscores ('_') so that
|
| 463 | 560 | -- the resulting 'String' is a valid C preprocessor identifier.
|
| ... | ... | @@ -479,42 +576,40 @@ ghcWrapper stage = do |
| 479 | 576 | |
| 480 | 577 | -- | Generate settings file, optionally including @LibDir@.
|
| 481 | 578 | --
|
| 579 | +-- Describes the compiler whose stage is the ambient 'Expr' context
|
|
| 580 | +-- (available here as @executableStage@ via 'getStage'). The @libraryStage@
|
|
| 581 | +-- argument is the stage whose lib dir holds the libraries the described
|
|
| 582 | +-- compiler links against — used both for the @base@ unit-id lookup and for
|
|
| 583 | +-- the @LibDir@ entry. It usually equals @executableStage@ but differs when
|
|
| 584 | +-- the compiler links against libraries from a different stage (cross
|
|
| 585 | +-- compilers, or the Stage0 bootstrap compiler using Stage1's libraries).
|
|
| 586 | +--
|
|
| 482 | 587 | -- @rel_pkg_db@: package DB path relative to the lib dir (e.g.
|
| 483 | 588 | -- "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
|
|
| 589 | +-- the layout is known statically; for in-tree builds callers compute it.
|
|
| 590 | +-- For bindists, we omit @LibDir@ so it defaults to @topDir@ at runtime.
|
|
| 591 | +generateSettings :: FilePath -> Bool -> FilePath -> Stage -> Expr String
|
|
| 592 | +generateSettings settingsFile includeLibDir rel_pkg_db libraryStage = do
|
|
| 488 | 593 | ctx <- getContext
|
| 489 | - stage <- getStage
|
|
| 594 | + executableStage <- getStage
|
|
| 595 | + |
|
| 596 | + base_unit_id <- expr $ pkgUnitId libraryStage base
|
|
| 490 | 597 | |
| 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
|
|
| 598 | + lib_topDir :: FilePath <- expr $ addTrailingPathSeparator <$> stageLibPath libraryStage
|
|
| 509 | 599 | let rel_lib_topDir = makeRelativeNoSysLink (dropFileName settingsFile) lib_topDir
|
| 510 | 600 | |
| 511 | 601 | 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)
|
|
| 602 | + [ ("unlit command", ("$topdir/../bin/" <>) <$> expr (programName (ctx { Context.package = unlit })))
|
|
| 603 | + , ("Use interpreter", expr $ yesNo <$> ghcWithInterpreter executableStage)
|
|
| 604 | + -- Advertise the RTS ways that will actually ship with the compiler
|
|
| 605 | + -- described by this settings file, i.e. the ways the @libraryStage@
|
|
| 606 | + -- RTS is built with. Cabal queries this to decide which library ways
|
|
| 607 | + -- the compiler supports (see
|
|
| 608 | + -- 'Distribution.Simple.Compiler.waySupported'); under-advertising
|
|
| 609 | + -- causes Cabal to silently drop flags like
|
|
| 610 | + -- @--enable-profiling-shared@.
|
|
| 611 | + -- The settings file is regenerated at install time when installing a bindist.
|
|
| 612 | + , ("RTS ways", unwords . map show . Set.toList <$> expr (interpretInContext (vanillaContext libraryStage rts) getRtsWays))
|
|
| 518 | 613 | , ("Relative Global Package DB", pure rel_pkg_db)
|
| 519 | 614 | , ("base unit-id", pure base_unit_id)
|
| 520 | 615 | ]
|