diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c4b65f3c273..5a601b834e6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,7 @@ jobs: - name: Build the bindist shell: devx {0} - run: make CABAL=$PWD/_build/stage0/bin/cabal + run: make CABAL=$(./build-cabal.sh) - name: Upload artifacts uses: actions/upload-artifact@v4 @@ -62,7 +62,7 @@ jobs: - name: Run the testsuite shell: devx {0} - run: make test CABAL=$PWD/_build/stage0/bin/cabal + run: make test CABAL=$(./build-cabal.sh) - name: Upload test results uses: actions/upload-artifact@v4 diff --git a/.github/workflows/reusable-release.yml b/.github/workflows/reusable-release.yml index c1b33a97e73d..6a367026f848 100644 --- a/.github/workflows/reusable-release.yml +++ b/.github/workflows/reusable-release.yml @@ -16,7 +16,7 @@ on: default: "install_bin install_lib update_package_db" cabal: type: string - default: 3.14.2.0 + default: 3.17.0.1 test: type: boolean default: true @@ -28,8 +28,7 @@ env: CABAL_VERSION: ${{ inputs.cabal }} # ghcup BOOTSTRAP_HASKELL_NONINTERACTIVE: 1 - BOOTSTRAP_HASKELL_GHC_VERSION: ${{ inputs.ghc }} - BOOTSTRAP_HASKELL_CABAL_VERSION: ${{ inputs.cabal }} + BOOTSTRAP_HASKELL_MINIMAL: 1 BOOTSTRAP_HASKELL_INSTALL_NO_STACK: 1 # debian/ubuntu DEBIAN_FRONTEND: noninteractive @@ -105,6 +104,11 @@ jobs: with: cabal: ${{ env.CABAL_VERSION }} ghc: ${{ env.GHC_VERSION }} + config: &ghcup-config | + meta-cache: 0 + url-source: + - GHCupURL + - https://raw.githubusercontent.com/haskell/ghcup-metadata/refs/heads/stable-haskell-0.0.1/stable-haskell-0.0.9.yaml - uses: actions/checkout@v4 with: @@ -128,11 +132,6 @@ jobs: ln -s make /usr/local/bin/gmake echo "/usr/local/bin" >> $GITHUB_PATH - - name: Add extra-lib-dirs - run: &extra-lib-dirs | - echo "extra-lib-dirs: $HOME/.local/lib/" >> cabal.project.stage2 - echo "extra-lib-dirs: $HOME/.local/lib/" >> cabal.project.stage3 - - if: matrix.platform.image == 'rockylinux:8' name: Install emscripten run : &emscripten | @@ -166,17 +165,20 @@ jobs: cd emsdk source ./emsdk_env.sh cd .. - ${{ env.MAKE }} _build/bindist/haskell-toolchain.tar.gz _build/bindist/tests.tar.gz + ${{ env.MAKE }} _build/bindist/stage2/ghc.tar.gz _build/bindist/stage3/ghc-javascript-unknown-ghcjs.tar.gz _build/bindist/tests.tar.gz else - echo $PWD - ${{ env.MAKE }} --debug _build/bindist/ghc.tar.gz _build/bindist/cabal.tar.gz _build/bindist/tests.tar.gz + ${{ env.MAKE }} _build/bindist/stage2/ghc.tar.gz _build/bindist/tests.tar.gz fi cd _build/bindist - mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${ARTIFACT}.tar.gz - mv cabal.tar.gz cabal-$(bin/cabal --numeric-version)-${ARTIFACT}.tar.gz - if [ -e "haskell-toolchain.tar.gz" ] ; then - mv haskell-toolchain.tar.gz haskell-toolchain-${ARTIFACT}.tar.gz - mv ghc-javascript-unknown-ghcjs.tar.gz ghc-javascript-unknown-ghcjs-$(bin/ghc --numeric-version)-${ARTIFACT}.tar.gz + ( + cd stage2 + mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${ARTIFACT}.tar.gz + ) + if [ -e "ghc-javascript-unknown-ghcjs.tar.gz" ] ; then + ( + cd stage3 + mv ghc-javascript-unknown-ghcjs.tar.gz ghc-javascript-unknown-ghcjs-$(bin/ghc --numeric-version)-${ARTIFACT}.tar.gz + ) fi mv tests.tar.gz tests-${ARTIFACT}.tar.gz env: @@ -189,8 +191,10 @@ jobs: if-no-files-found: error retention-days: 2 name: artifacts-${{ matrix.platform.ARTIFACT }}-${{ matrix.branch }} - path: | + path: &upload-paths | ./_build/bindist/*.tar.gz + ./_build/bindist/stage2/*.tar.gz + ./_build/bindist/stage3/*.tar.gz build-arm: name: Build ARM binary @@ -215,13 +219,13 @@ jobs: uses: docker://arm64v8/debian:11 name: Run build (aarch64 linux) with: - args: sh -c "apt-get update && apt-get install -y curl bash git ${{ needs.tool-output.outputs.apt_tools_build }} && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && make CABAL=$PWD/_build/stage0/bin/cabal _build/bindist/ghc.tar.gz _build/bindist/cabal.tar.gz _build/bindist/tests.tar.gz && cd _build/bindist && mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${{ matrix.platform.ARTIFACT }}.tar.gz && mv cabal.tar.gz cabal-$(bin/cabal --numeric-version)-${{ matrix.platform.ARTIFACT }}.tar.gz && mv tests.tar.gz tests-${{ matrix.platform.ARTIFACT }}.tar.gz" + args: sh -c "apt-get update && apt-get install -y curl bash git ${{ needs.tool-output.outputs.apt_tools_build }} && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && ghcup config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/refs/heads/stable-haskell-0.0.1/stable-haskell-0.0.9.yaml && ghcup install ghc --set ${{ env.GHC_VERSION }} && ghcup install cabal --set ${{ env.CABAL_VERSION }} && make USE_SYSTEM_CABAL=1 _build/bindist/stage2/ghc.tar.gz _build/bindist/tests.tar.gz && cd _build/bindist/stage2 && mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${{ matrix.platform.ARTIFACT }}.tar.gz && cd .. && mv tests.tar.gz tests-${{ matrix.platform.ARTIFACT }}.tar.gz" - if: matrix.platform.ARTIFACT == 'aarch64-linux-unknown' uses: docker://arm64v8/alpine:3.20 name: Run build (aarch64 linux alpine) with: - args: sh -c "apk update && apk add curl bash git ${{ needs.tool-output.outputs.apk_tools_build }} && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && make CABAL=$PWD/_build/stage0/bin/cabal _build/bindist/ghc.tar.gz _build/bindist/cabal.tar.gz _build/bindist/tests.tar.gz && cd _build/bindist && mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${{ matrix.platform.ARTIFACT }}.tar.gz && mv cabal.tar.gz cabal-$(bin/cabal --numeric-version)-${{ matrix.platform.ARTIFACT }}.tar.gz && mv tests.tar.gz tests-${{ matrix.platform.ARTIFACT }}.tar.gz" + args: sh -c "apk update && apk add curl bash git ${{ needs.tool-output.outputs.apk_tools_build }} && export PATH=$HOME/.ghcup/bin:$PATH && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh && ghcup config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/refs/heads/stable-haskell-0.0.1/stable-haskell-0.0.9.yaml && ghcup install ghc --set ${{ env.GHC_VERSION }} && ghcup install cabal --set ${{ env.CABAL_VERSION }} && make USE_SYSTEM_CABAL=1 _build/bindist/stage2/ghc.tar.gz _build/bindist/tests.tar.gz && cd _build/bindist/stage2 && mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${{ matrix.platform.ARTIFACT }}.tar.gz && cd .. && mv tests.tar.gz tests-${{ matrix.platform.ARTIFACT }}.tar.gz" - if: always() name: Upload artifact @@ -230,8 +234,7 @@ jobs: if-no-files-found: error retention-days: 2 name: artifacts-${{ matrix.platform.ARTIFACT }}-${{ matrix.branch }} - path: | - ./_build/bindist/*.tar.gz + path: *upload-paths build-mac-x86_64: name: Build binary (Mac x86_64) @@ -255,6 +258,7 @@ jobs: with: cabal: ${{ env.CABAL_VERSION }} ghc: ${{ env.GHC_VERSION }} + config: *ghcup-config - name: Install dependencies run : | @@ -263,9 +267,6 @@ jobs: echo "/usr/local/opt/make/libexec/gnubin" >> $GITHUB_PATH echo "/usr/local/opt/libtool/libexec/gnubin" >> $GITHUB_PATH - - name: Add extra-lib-dirs - run: *extra-lib-dirs - - name: Install emscripten run : *emscripten @@ -279,8 +280,7 @@ jobs: if-no-files-found: error retention-days: 2 name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} - path: | - ./_build/bindist/*.tar.gz + path: *upload-paths build-mac-aarch64: name: Build binary (Mac aarch64) @@ -305,6 +305,7 @@ jobs: with: cabal: ${{ env.CABAL_VERSION }} ghc: ${{ env.GHC_VERSION }} + config: *ghcup-config - name: Install dependencies run : | @@ -313,9 +314,6 @@ jobs: echo "/opt/homebrew/opt/make/libexec/gnubin" >> $GITHUB_PATH echo "/opt/homebrew/opt/libtool/libexec/gnubin" >> $GITHUB_PATH - - name: Add extra-lib-dirs - run: *extra-lib-dirs - - name: Run build run: *build @@ -326,8 +324,7 @@ jobs: if-no-files-found: error retention-days: 2 name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} - path: | - ./_build/bindist/*.tar.gz + path: *upload-paths build-windows: name: Build binary (Windows) @@ -359,6 +356,7 @@ jobs: with: cabal: ${{ env.CABAL_VERSION }} ghc: ${{ env.GHC_VERSION }} + config: *ghcup-config env: GHCUP_MSYS2: 'C:/msys64' @@ -374,8 +372,7 @@ jobs: if-no-files-found: error retention-days: 2 name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} - path: | - ./_build/bindist/*.tar.gz + path: *upload-paths build-freebsd-x86_64: name: Build FreeBSD x86_64 @@ -401,6 +398,7 @@ jobs: with: cabal: ${{ env.CABAL_VERSION }} ghc: ${{ env.GHC_VERSION }} + config: *ghcup-config env: LD: ld CC: cc @@ -427,9 +425,6 @@ jobs: sudo tzsetup Etc/GMT sudo adjkerntz -a - - name: Add extra-lib-dirs - run: *extra-lib-dirs - - name: Install emscripten run : | sudo pkg install -y emscripten @@ -439,12 +434,16 @@ jobs: which ghc ghc --info cabal update - gmake CABAL=$PWD/_build/stage0/bin/cabal _build/bindist/haskell-toolchain.tar.gz _build/bindist/tests.tar.gz + gmake _build/bindist/stage2/ghc.tar.gz _build/bindist/stage3/ghc-javascript-unknown-ghcjs.tar.gz _build/bindist/tests.tar.gz cd _build/bindist - mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${{ env.ARTIFACT }}.tar.gz - mv cabal.tar.gz cabal-$(bin/cabal --numeric-version)-${{ env.ARTIFACT }}.tar.gz - mv haskell-toolchain.tar.gz haskell-toolchain-${{ env.ARTIFACT }}.tar.gz - mv ghc-javascript-unknown-ghcjs.tar.gz ghc-javascript-unknown-ghcjs-$(bin/ghc --numeric-version)-${{ env.ARTIFACT }}.tar.gz + ( + cd stage2 + mv ghc.tar.gz ghc-$(bin/ghc --numeric-version)-${{ env.ARTIFACT }}.tar.gz + ) + ( + cd stage3 + mv ghc-javascript-unknown-ghcjs.tar.gz ghc-javascript-unknown-ghcjs-$(bin/ghc --numeric-version)-${{ env.ARTIFACT }}.tar.gz + ) mv tests.tar.gz tests-${{ env.ARTIFACT }}.tar.gz env: EXTRA_LIB_DIRS: /usr/local/lib @@ -458,8 +457,7 @@ jobs: if-no-files-found: error retention-days: 2 name: artifacts-${{ env.ARTIFACT }}-${{ matrix.branch }} - path: | - ./_build/bindist/*.tar.gz + path: *upload-paths test-linux: name: Test linux binaries @@ -677,7 +675,6 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ matrix.branch }} - submodules: recursive - uses: ./.github/actions/download with: @@ -707,7 +704,6 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ matrix.branch }} - submodules: recursive - name: Install msys2 dependencies run: *msys2-install diff --git a/Makefile b/Makefile index 2fd035944c1f..7b3b4298b092 100644 --- a/Makefile +++ b/Makefile @@ -78,1020 +78,30 @@ # - [ ] All sublibs should be SRPs in the relevant cabal.project files. No more # submodules. -SHELL := bash -.SHELLFLAGS := -eu -o pipefail -c - -VERBOSE ?= 0 - -# Enable dynamic runtime/linking support when DYNAMIC=1 is passed on the make -# command line. This will build shared libraries, a dynamic RTS (defining -# -DDYNAMIC) and allow tests requiring dynamic linking (e.g. plugins-external) -# to run. The default remains static to keep rebuild cost low. -DYNAMIC ?= 0 - -# If using autoconf feature toggles you can instead run: -# ./configure --enable-dynamic --enable-profiling --enable-debug -# which generates cabal.project.stage2.settings (imported by cabal.project.stage2). -# The legacy DYNAMIC=1 path still appends flags directly; if both are used the -# configure-generated settings file (import) and these args should agree. - -ROOT_DIR := $(patsubst %/,%,$(dir $(realpath $(lastword $(MAKEFILE_LIST))))) - -GHC0 ?= ghc-9.8.4 -PYTHON ?= python3 -CABAL ?= _build/stage0/bin/cabal$(EXE_EXT) -SED ?= sed - -ifeq ($(OS),Windows_NT) -CC := x86_64-w64-mingw32-clang.exe -CXX := x86_64-w64-mingw32-clang++.exe -CC_LINK_OPT := -Wl,CRT_fp8.o -LD := ld.lld.exe -CYGPATH = cygpath --unix -f - -CYGPATH_MIXED = cygpath --mixed -f - -# Windows executables require .exe extension for native programs to find them -EXE_EXT := .exe -else -CYGPATH_MIXED = cat -CYGPATH = cat -CC_LINK_OPT ?= -LD ?= ld -EXE_EXT := -endif - -EMCC ?= emcc -EMCXX ?= em++ -EMAR ?= emar -EMRANLIB ?= emranlib - -GHC_CONFIGURE_ARGS ?= - -EXTRA_LIB_DIRS ?= -EXTRA_INCLUDE_DIRS ?= - -MUSL_EXTRA_LIB_DIRS ?= -MUSL_EXTRA_INCLUDE_DIRS ?= - -JS_EXTRA_LIB_DIRS ?= -JS_EXTRA_INCLUDE_DIRS ?= - -WASM_EXTRA_LIB_DIRS ?= -WASM_EXTRA_INCLUDE_DIRS ?= -WASM_CC_OPTS = -fno-strict-aliasing -Wno-error=int-conversion -Oz -msimd128 -mnontrapping-fptoint -msign-ext -mbulk-memory -mmutable-globals -mmultivalue -mreference-types -WASM_CXX_OPTS = -fno-exceptions -fno-strict-aliasing -Wno-error=int-conversion -Oz -msimd128 -mnontrapping-fptoint -msign-ext -mbulk-memory -mmutable-globals -mmultivalue -mreference-types - -# :exploding-head: It turns out override doesn't override the command-line -# value but it overrides Make's normal behavior of ignoring assignments to -# command-line variables. This allows the += operations to append to whatever -# was passed from the command line. - -override CABAL_ARGS += \ - --remote-repo-cache _build/packages \ - --store-dir=_build/$(STAGE)/$(TARGET_PLATFORM)/store \ - --logs-dir=_build/$(STAGE)/logs - -override CABAL_BUILD_ARGS += \ - -j -w $(GHC) --with-gcc=$(CC) --with-ld=$(LD) \ - --project-file=cabal.project.$(STAGE) \ - $(foreach lib,$(EXTRA_LIB_DIRS),--extra-lib-dirs=$(lib)) \ - $(foreach include,$(EXTRA_INCLUDE_DIRS),--extra-include-dirs=$(include)) \ - --builddir=_build/$(STAGE)/$(TARGET_PLATFORM) \ - --ghc-options="-fhide-source-paths" - -ifeq ($(DYNAMIC),1) -GHC_CONFIGURE_ARGS += --enable-dynamic +ifndef TOOLCHAIN_MK +include mk/stable-haskell/toolchain.mk endif -GHC_TOOLCHAIN_ARGS ?= --disable-ld-override - -# just some defaults -STAGE ?= stage1 -GHC ?= $(GHC0) - -CABAL_BUILD = $(CABAL) $(CABAL_ARGS) build $(CABAL_BUILD_ARGS) - -GHC1 = _build/stage1/bin/ghc$(EXE_EXT) -GHC2 = _build/stage2/bin/ghc$(EXE_EXT) - -define GHC_INFO -$(shell sh -c "$(GHC) --info | $(GHC0) -e 'getContents >>= foldMap putStrLn . lookup \"$1\" . read'") -endef - -HOST_PLATFORM = $(call GHC_INFO,Host platform) -TARGET_PLATFORM = $(call GHC_INFO,target platform string) -TARGET_ARCH = $(call GHC_INFO,target arch) -TARGET_OS = $(call GHC_INFO,target os) -TARGET_TRIPLE = $(call GHC_INFO,Target platform) -GHC_LIBDIR = $(call GHC_INFO,LibDir) -GIT_COMMIT_ID := $(shell git rev-parse HEAD) +include mk/stable-haskell/boot.mk +include mk/stable-haskell/stage1.mk -define HADRIAN_SETTINGS -[ ("hostPlatformArch", "$(TARGET_ARCH)") \ -, ("hostPlatformOS", "$(TARGET_OS)") \ -, ("cProjectGitCommitId", "$(GIT_COMMIT_ID)") \ -, ("cProjectVersion", "9.14") \ -, ("cProjectVersionInt", "914") \ -, ("cProjectPatchLevel", "0") \ -, ("cProjectPatchLevel1", "0") \ -, ("cProjectPatchLevel2", "0") \ -] -endef +# stage2 and 3 are somewhat intertwined +include mk/stable-haskell/stage2.mk +include mk/stable-haskell/stage3.mk -# Handle CPUS and THREADS -CPUS_DETECT_SCRIPT := ./mk/detect-cpu-count.sh -CPUS := $(shell if [ -x $(CPUS_DETECT_SCRIPT) ]; then $(CPUS_DETECT_SCRIPT); else echo 2; fi) -THREADS ?= $(shell echo $$(( $(CPUS) + 1 ))) - -CONFIGURE_SCRIPTS = \ - configure \ - rts/configure \ - libraries/ghc-internal/configure \ - libraries/libffi-clib/configure \ - libraries/directory/configure \ - libraries/process/configure \ - libraries/terminfo/configure \ - libraries/time/configure \ - libraries/unix/configure - -# Files that will be generated by config.status from their .in counterparts -# FIXME: This is stupid. Why do we patch versions across multiple libraries? Idiotic. -# also, why on earth do we use a non standard SnakeCase convention for substitutions -# when CAPITAL_CASE is the standard? -CONFIGURED_FILES := \ - ghc/ghc-bin.cabal \ - compiler/GHC/CmmToLlvm/Version/Bounds.hs \ - compiler/ghc.cabal \ - libraries/ghc-boot/ghc-boot.cabal \ - libraries/ghc-boot-th/ghc-boot-th.cabal \ - libraries/ghc-heap/ghc-heap.cabal \ - libraries/template-haskell/template-haskell.cabal \ - libraries/ghci/ghci.cabal \ - utils/ghc-pkg/ghc-pkg.cabal \ - utils/ghc-iserv/ghc-iserv.cabal \ - utils/runghc/runghc.cabal \ - libraries/ghc-internal/ghc-internal.cabal \ - libraries/ghc-experimental/ghc-experimental.cabal \ - libraries/base/base.cabal \ - rts/include/ghcversion.h +include mk/stable-haskell/test.mk # --- Main Targets --- -all: _build/bindist - -STAGE_UTIL_TARGETS := \ - deriveConstants:deriveConstants \ - genapply:genapply \ - genprimopcode:genprimopcode \ - ghc-pkg:ghc-pkg \ - hsc2hs:hsc2hs \ - rts-headers:rts-headers \ - unlit:unlit - -STAGE1_TARGETS := $(STAGE_UTIL_TARGETS) ghc-bin:ghc ghc-toolchain-bin:ghc-toolchain-bin - -# TODO: dedup -STAGE1_EXECUTABLES := \ - deriveConstants$(EXE_EXT) \ - genapply$(EXE_EXT) \ - genprimopcode$(EXE_EXT) \ - ghc$(EXE_EXT) \ - ghc-pkg$(EXE_EXT) \ - ghc-toolchain-bin$(EXE_EXT) \ - hsc2hs$(EXE_EXT) \ - unlit$(EXE_EXT) - -# We really want to work towards `cabal build/instsall ghc-bin:ghc`. -STAGE2_TARGETS := \ - ghc-bin:ghc - -# we need to build these before all else -STAGE2_UTIL_RTS := \ - rts:nonthreaded-debug \ - rts:nonthreaded-nodebug \ - rts:threaded-nodebug \ - rts:threaded-debug - -# rts:threaded-nodebug need it for compiling Setup.hs -STAGE2_UTIL_TARGETS := \ - $(STAGE_UTIL_TARGETS) \ - ghc-iserv:ghc-iserv \ - $(STAGE2_UTIL_RTS) \ - hp2ps:hp2ps \ - hpc-bin:hpc \ - runghc:runghc \ - ghc-bignum:ghc-bignum \ - ghc-compact:ghc-compact \ - ghc-experimental:ghc-experimental \ - ghc-toolchain:ghc-toolchain \ - integer-gmp:integer-gmp \ - system-cxx-std-lib:system-cxx-std-lib \ - xhtml:xhtml \ - haddock:haddock - -ifneq ($(OS),Windows_NT) -STAGE2_UTIL_TARGETS += terminfo:terminfo -endif - -# These things should be built on demand. -# hp2ps:hp2ps \ -# hpc-bin:hpc \ -# ghc-iserv:ghc-iserv \ -# runghc:runghc \ - -# This package is just utterly retarded -# I don't understand why this following line somehow breaks the build... -# STAGE2_TARGETS += system-cxx-std-lib:system-cxx-std-lib - -# TODO: dedup -STAGE2_EXECUTABLES := \ - ghc$(EXE_EXT) - -STAGE2_UTIL_EXECUTABLES := \ - deriveConstants$(EXE_EXT) \ - genapply$(EXE_EXT) \ - genprimopcode$(EXE_EXT) \ - hsc2hs$(EXE_EXT) \ - ghc-iserv$(EXE_EXT) \ - ghc-pkg$(EXE_EXT) \ - hp2ps$(EXE_EXT) \ - hpc$(EXE_EXT) \ - runghc$(EXE_EXT) \ - unlit$(EXE_EXT) \ - haddock$(EXE_EXT) - -BINDIST_EXECTUABLES := \ - ghc$(EXE_EXT) \ - ghc-iserv$(EXE_EXT) \ - ghc-pkg$(EXE_EXT) \ - hp2ps$(EXE_EXT) \ - hpc$(EXE_EXT) \ - hsc2hs$(EXE_EXT) \ - runghc$(EXE_EXT) \ - unlit$(EXE_EXT) \ - haddock$(EXE_EXT) - -STAGE3_LIBS := \ - rts:nonthreaded-nodebug \ - Cabal \ - Cabal-syntax \ - array \ - base \ - binary \ - bytestring \ - containers \ - deepseq \ - directory \ - exceptions \ - file-io \ - filepath \ - ghc-bignum \ - ghci \ - hpc \ - integer-gmp \ - mtl \ - os-string \ - parsec \ - pretty \ - process \ - stm \ - template-haskell \ - text \ - time \ - transformers \ - xhtml - -# --- Source headers --- -# TODO: this is a hack, because of https://github.com/haskell/cabal/issues/11172 -# -# $1 = headers -# $2 = source base dirs -# $3 = pkgname -# $4 = ghc-pkg -define copy_headers - set -e; \ - dest=`$4 field $3 include-dirs | awk '{ print $$2 ; exit }'` ;\ - for h in $1 ; do \ - mkdir -p "$$dest/`dirname $$h`" ; \ - for sdir in $2 ; do \ - if [ -e "$$sdir/$$h" ] ; then \ - cp -frp "$$sdir/$$h" "$$dest/$$h" ; \ - break ; \ - fi ; \ - done ; \ - [ -e "$$dest/$$h" ] || { echo "Copying $$dest/$$h failed... tried source dirs $2" >&2 ; exit 2 ; } ; \ - done -endef - -RTS_HEADERS_H := \ - rts/Bytecodes.h \ - rts/storage/ClosureTypes.h \ - rts/storage/FunTypes.h \ - stg/MachRegs.h \ - stg/MachRegs/arm32.h \ - stg/MachRegs/arm64.h \ - stg/MachRegs/loongarch64.h \ - stg/MachRegs/ppc.h \ - stg/MachRegs/riscv64.h \ - stg/MachRegs/s390x.h \ - stg/MachRegs/wasm32.h \ - stg/MachRegs/x86.h - -define copy_rts_headers_h - $(call copy_headers,$(RTS_HEADERS_H),rts-headers/include/,rts-headers,$1) -endef - -RTS_FS_H := \ - fs.h - -define copy_rts_fs_h - $(call copy_headers,$(RTS_FS_H),rts-fs/,rts-fs,$1) -endef - -RTS_H := \ - Cmm.h \ - HsFFI.h \ - MachDeps.h \ - Jumps.h \ - Rts.h \ - RtsAPI.h \ - RtsSymbols.h \ - Stg.h \ - ghcconfig.h \ - ghcversion.h \ - rts/ghc_ffi.h \ - rts/Adjustor.h \ - rts/ExecPage.h \ - rts/BlockSignals.h \ - rts/Config.h \ - rts/Constants.h \ - rts/EventLogFormat.h \ - rts/EventLogWriter.h \ - rts/FileLock.h \ - rts/Flags.h \ - rts/ForeignExports.h \ - rts/GetTime.h \ - rts/Globals.h \ - rts/Hpc.h \ - rts/IOInterface.h \ - rts/Libdw.h \ - rts/LibdwPool.h \ - rts/Linker.h \ - rts/Main.h \ - rts/Messages.h \ - rts/NonMoving.h \ - rts/OSThreads.h \ - rts/Parallel.h \ - rts/PrimFloat.h \ - rts/Profiling.h \ - rts/IPE.h \ - rts/PosixSource.h \ - rts/RtsToHsIface.h \ - rts/Signals.h \ - rts/SpinLock.h \ - rts/StableName.h \ - rts/StablePtr.h \ - rts/StaticPtrTable.h \ - rts/TTY.h \ - rts/Threads.h \ - rts/Ticky.h \ - rts/Time.h \ - rts/Timer.h \ - rts/TSANUtils.h \ - rts/Types.h \ - rts/Utils.h \ - rts/prof/CCS.h \ - rts/prof/Heap.h \ - rts/prof/LDV.h \ - rts/storage/Block.h \ - rts/storage/ClosureMacros.h \ - rts/storage/Closures.h \ - rts/storage/Heap.h \ - rts/storage/HeapAlloc.h \ - rts/storage/GC.h \ - rts/storage/InfoTables.h \ - rts/storage/MBlock.h \ - rts/storage/TSO.h \ - stg/DLL.h \ - stg/MiscClosures.h \ - stg/Prim.h \ - stg/Regs.h \ - stg/SMP.h \ - stg/Ticky.h \ - stg/MachRegsForHost.h \ - stg/Types.h - -RTS_H_DIRS := \ - rts/ \ - rts/include/ - -define copy_rts_h - $(call copy_headers,$(RTS_H),$(RTS_H_DIRS),rts,$1) -endef - -RTS_JS_H := \ - HsFFI.h \ - MachDeps.h \ - Rts.h \ - RtsAPI.h \ - Stg.h \ - ghcconfig.h \ - ghcversion.h \ - stg/MachRegsForHost.h \ - stg/Types.h - -define copy_rts_js_h - $(call copy_headers,$(RTS_JS_H),rts/include/,rts,$1) -endef - -HASKELINE_H := \ - win_console.h - -define copy_haskeline_h - $(call copy_headers,$(HASKELINE_H),libraries/haskeline/includes,haskeline,$1) -endef - -WIN32_H := \ - HsWin32.h \ - HsGDI.h \ - WndProc.h \ - windows_cconv.h \ - alphablend.h \ - wincon_compat.h \ - winternl_compat.h \ - winuser_compat.h \ - winreg_compat.h \ - tlhelp32_compat.h \ - winnls_compat.h \ - winnt_compat.h \ - namedpipeapi_compat.h - -define copy_win32_h - $(call copy_headers,$(WIN32_H),libraries/Win32/include/,Win32,$1) -endef - -GHC_INTERNAL_H := \ - HsBase.h \ - consUtils.h - -define copy_ghc_internal_h - $(call copy_headers,$(GHC_INTERNAL_H),libraries/ghc-internal/include/,ghc-internal,$1) -endef - -PROCESS_H := \ - runProcess.h \ - processFlags.h - -define copy_process_h - $(call copy_headers,$(PROCESS_H),libraries/process/include/,process,$1) -endef - -BYTESTRING_H := \ - fpstring.h \ - bytestring-cpp-macros.h - -define copy_bytestring_h - $(call copy_headers,$(BYTESTRING_H),libraries/bytestring/include/,bytestring,$1) -endef - -TIME_H := \ - HsTime.h - -define copy_time_h - $(call copy_headers,$(TIME_H),libraries/time/lib/include/,time,$1) -endef - -UNIX_H := \ - HsUnix.h \ - execvpe.h - -define copy_unix_h - $(call copy_headers,$(UNIX_H),libraries/unix/include/,unix,$1) -endef - -define copy_all_stage3_h - $(call copy_rts_headers_h,$1) - $(call copy_rts_fs_h,$1) - $(call copy_rts_h,$1) - if [ "$2" = "javascript-unknown-ghcjs" ] ; then $(call copy_rts_js_h,$1) ; fi - $(call copy_ghc_internal_h,$1) - $(call copy_process_h,$1) - $(call copy_bytestring_h,$1) - $(call copy_time_h,$1) - if [ "$(OS)" = "Windows_NT" ] ; then $(call copy_win32_h,$1) ; else $(call copy_unix_h,$1) ; fi -endef - -define copy_all_stage2_h - $(call copy_all_stage3_h,$1,none) - $(call copy_haskeline_h,$1) -endef - - -# --- Bootstrapping and stage 0 --- - -# export CABAL := $(shell cabal update 2>&1 >/dev/null && cabal build cabal-install -v0 --disable-tests --project-dir libraries/Cabal && cabal list-bin -v0 --project-dir libraries/Cabal cabal-install:exe:cabal) -$(abspath _build/stage0/bin/cabal$(EXE_EXT)): _build/stage0/bin/cabal$(EXE_EXT) - -# --- Stage 0 build --- - -# This just builds cabal-install, which is used to build the rest of the project. - -# We need an absolute path here otherwise cabal will consider the path relative to `the project directory -_build/stage0/bin/cabal$(EXE_EXT): BUILD_ARGS=-j -w $(GHC0) --disable-tests --project-dir libraries/Cabal --builddir=$(abspath _build/stage0) --ghc-options="-fhide-source-paths" -_build/stage0/bin/cabal$(EXE_EXT): - @echo "::group::Building Cabal..." - @mkdir -p _build/stage0/bin _build/logs - cabal build $(BUILD_ARGS) cabal-install:exe:cabal - cp -rfp $(shell cabal list-bin -v0 $(BUILD_ARGS) cabal-install:exe:cabal | $(CYGPATH)) $@ - @echo "::endgroup::" - -# --- Stage 1 build --- - -_build/stage1/%: private STAGE=stage1 -_build/stage1/%: private GHC=$(GHC0) - -.PHONY: cabal.project.stage1.local - -cabal.project.stage1.local: cabal.project.stage1 -ifeq ($(OS),Windows_NT) - echo "extra-prog-path: $(shell echo '$(GHC_LIBDIR)' | $(CYGPATH_MIXED))/../mingw/bin" > $@ -else - echo "" > $@ -endif - -.PHONY: $(addprefix _build/stage1/bin/,$(STAGE1_EXECUTABLES)) -$(addprefix _build/stage1/bin/,$(STAGE1_EXECUTABLES)) &: private TARGET_PLATFORM= -$(addprefix _build/stage1/bin/,$(STAGE1_EXECUTABLES)) &: $(CABAL) $(CONFIGURE_SCRIPTS) $(CONFIGURED_FILES) libraries/ghc-boot-th-next/ghc-boot-th-next.cabal cabal.project.stage1 cabal.project.stage1.local - @echo "::group::Building stage1 executables ($(STAGE1_EXECUTABLES))..." - # Force cabal to replan - rm -rf _build/stage1/cache - HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' $(CABAL_BUILD) $(STAGE1_TARGETS) - @echo "::endgroup::" - -_build/stage1/lib/settings: _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) - @echo "::group::Creating settings for $(TARGET_TRIPLE)..." - @mkdir -p $(@D) - _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) $(GHC_TOOLCHAIN_ARGS) --triple $(TARGET_TRIPLE) --output-settings -o $@ --cc $(CC) --cxx $(CXX) --cc-link-opt "$(CC_LINK_OPT)" - @echo "::endgroup::" - -# The somewhat strange thing is, we might not even need this at all now anymore. cabal seems to -# pass all the necessary flags correctly. Thus even with an _empty_ package-db here (and it will -# stay empty until we are done with the build), the build succeeds. -# -# For now, we are tying the knot here by making sure the stage1 compiler (stage1/bin/ghc) sees -# the packages it builds (to build stage2/bin/ghc), by symlining cabal's target package-db into -# the compilers global package-db. Another maybe even better solution might be to set the -# Global Package DB in the settings file to the absolute path where cabal will place the -# package db. This would elminate this rule outright. -_build/stage1/lib/package.conf.d/package.cache: _build/stage1/bin/ghc-pkg$(EXE_EXT) _build/stage1/lib/settings - @echo "::group::Creating stage1 package cache..." - @mkdir -p _build/stage1/lib/package.conf.d -# @mkdir -p _build/stage2/packagedb/host -# ln -s $(abspath ./_build/stage2/packagedb/host/ghc-9.14) _build/stage1/lib/package.conf.d -# _build/stage1/bin/ghc-pkg init $(abspath ./_build/stage2/packagedb/host/ghc-9.14) - @echo "::endgroup::" - -_build/stage1/lib/template-hsc.h: utils/hsc2hs/data/template-hsc.h - @mkdir -p $(@D) - cp -rfp $< $@ - -.PHONY: stage1 -stage1: $(addprefix _build/stage1/bin/,$(STAGE1_EXECUTABLES)) _build/stage1/lib/settings _build/stage1/lib/package.conf.d/package.cache _build/stage1/lib/template-hsc.h - -# --- Stage 2 build --- - -_build/stage2/%: private STAGE=stage2 -_build/stage2/%: private GHC=$(realpath _build/stage1/bin/ghc$(EXE_EXT)) - -.PHONY: $(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) -$(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) &: private TARGET_PLATFORM= -$(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) &: $(CABAL) stage1 cabal.project.stage2 stage2-rts - @echo "::group::Building stage2 executables ($(STAGE2_EXECUTABLES))..." - # Force cabal to replan - rm -rf _build/stage2/cache - GHC=$(GHC) HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ - PATH='$(PWD)/_build/stage1/bin:$(PATH)' \ - $(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) $(STAGE2_TARGETS) - @echo "::endgroup::" - -.PHONY: stage2-rts -stage2-rts: private STAGE=stage2 -stage2-rts: private GHC=$(realpath _build/stage1/bin/ghc$(EXE_EXT)) -stage2-rts: private TARGET_PLATFORM= -stage2-rts: $(CABAL) stage1 cabal.project.stage2 - @echo "::group::Building stage2 RTSes..." - # Force cabal to replan - rm -rf _build/stage2/cache - GHC=$(GHC) HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ - PATH='$(PWD)/_build/stage1/bin:$(PATH)' \ - $(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) $(STAGE2_UTIL_RTS) - @echo "::endgroup::" - - -# Do we want to build these with the stage2 GHC or the stage1 GHC? -# Traditionally we build them with the stage1 ghc, but we could just as well -# build them with the stage2 ghc; seems like a better/cleaner idea to me (moritz). -.PHONY: $(addprefix _build/stage2/bin/,$(STAGE2_UTIL_EXECUTABLES)) -$(addprefix _build/stage2/bin/,$(STAGE2_UTIL_EXECUTABLES)) &: private TARGET_PLATFORM= -$(addprefix _build/stage2/bin/,$(STAGE2_UTIL_EXECUTABLES)) &: $(CABAL) stage1 cabal.project.stage2.settings stage2-rts - @echo "::group::Building stage2 utilities ($(STAGE2_UTIL_EXECUTABLES))..." - # Force cabal to replan - rm -rf _build/stage2/cache - GHC=$(GHC) HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ - PATH='$(PWD)/_build/stage1/bin:$(PATH)' \ - $(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) $(STAGE2_UTIL_TARGETS) - @echo "::endgroup::" - -_build/stage2/lib/settings: _build/stage1/lib/settings - @mkdir -p $(@D) - cp -rfp _build/stage1/lib/settings _build/stage2/lib/settings - -_build/stage2/lib/package.conf.d/package.cache: _build/stage2/bin/ghc-pkg$(EXE_EXT) _build/stage2/lib/settings - @echo "::group::Creating stage2 package cache..." - @mkdir -p _build/stage2/lib/package.conf.d - @rm -rf _build/stage2/lib/package.conf.d/* - cp -rfp _build/stage2/packagedb/host/*/* _build/stage2/lib/package.conf.d - _build/stage2/bin/ghc-pkg$(EXE_EXT) recache - @echo "::endgroup::" - -_build/stage2/lib/template-hsc.h: utils/hsc2hs/data/template-hsc.h - @mkdir -p $(@D) - cp -rfp $< $@ - -.PHONY: stage2 -stage2: $(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) _build/stage2/lib/settings _build/stage2/lib/package.conf.d/package.cache _build/stage2/lib/template-hsc.h - -# --- Stage 3 generic --- - -_build/stage2/lib/targets/% _build/stage3/lib/targets/%: - @mkdir -p _build/stage3/lib/targets/$(@F) - @rm -f _build/stage2/lib/targets/$(@F) - @mkdir -p _build/stage2/lib/targets/ - @ln -sf ../../../stage3/lib/targets/$(@F) _build/stage2/lib/targets/$(@F) - -_build/stage3/bin/%-ghc-pkg$(EXE_EXT): _build/stage2/bin/ghc-pkg$(EXE_EXT) - @mkdir -p $(@D) - @ln -sf ../../stage2/bin/ghc-pkg$(EXE_EXT) $@ - -_build/stage3/bin/%-ghc$(EXE_EXT): _build/stage2/bin/ghc$(EXE_EXT) - @mkdir -p $(@D) - @ln -sf ../../stage2/bin/ghc$(EXE_EXT) $@ - -_build/stage3/bin/%-hsc2hs$(EXE_EXT): _build/stage2/bin/hsc2hs$(EXE_EXT) - @mkdir -p $(@D) - @ln -sf ../../stage2/bin/hsc2hs$(EXE_EXT) $@ - -_build/stage3/lib/targets/%/lib/package.conf.d: _build/stage3/lib/targets/% - @mkdir -p $@ - -# ghc-toolchain borks unlit -_build/stage3/lib/targets/%/bin/unlit$(EXE_EXT): _build/stage2/bin/unlit$(EXE_EXT) - @mkdir -p $(@D) - cp -rfp $< $@ - -_build/stage3/lib/targets/%/lib/dyld.mjs: - @mkdir -p $(@D) - @cp -f utils/jsffi/dyld.mjs $@ - @chmod +x $@ - -_build/stage3/lib/targets/%/lib/post-link.mjs: - @mkdir -p $(@D) - @cp -f utils/jsffi/post-link.mjs $@ - @chmod +x $@ - -_build/stage3/lib/targets/%/lib/prelude.mjs: - @mkdir -p $(@D) - @cp -f utils/jsffi/prelude.mjs $@ - @chmod +x $@ - -_build/stage3/lib/targets/%/lib/ghc-interp.js: - @mkdir -p $(@D) - @cp -f ghc-interp.js $@ - -# $1 = TIPLET -define build_cross - GHC=$(GHC) HADRIAN_SETTINGS='$(call HADRIAN_SETTINGS)' \ - PATH=$(PWD)/_build/stage2/bin:$(PWD)/_build/stage3/bin:$(PATH) \ - $(CABAL_BUILD) -W $(GHC2) --happy-options="--template=$(abspath _build/stage2/src/happy-lib-2.1.5/data/)" --with-hsc2hs=$1-hsc2hs --hsc2hs-options='-x' --configure-option='--host=$1' \ - $(foreach lib,$(CROSS_EXTRA_LIB_DIRS),--extra-lib-dirs=$(lib)) \ - $(foreach include,$(CROSS_EXTRA_INCLUDE_DIRS),--extra-include-dirs=$(include)) \ - $(STAGE3_LIBS) -endef - -# --- Stage 3 javascript build --- - -.PHONY: stage3-javascript-unknown-ghcjs -stage3-javascript-unknown-ghcjs: _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/settings javascript-unknown-ghcjs-libs _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/package.conf.d/package.cache _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/dyld.mjs _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/post-link.mjs _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/prelude.mjs _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/ghc-interp.js - -_build/stage3/lib/targets/javascript-unknown-ghcjs/lib/settings: _build/stage2/lib/targets/javascript-unknown-ghcjs _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) - @mkdir -p $(@D) - _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) $(GHC_TOOLCHAIN_ARGS) --triple javascript-unknown-ghcjs --output-settings -o $@ --cc $(EMCC) --cxx $(EMCXX) --ar $(EMAR) --ranlib $(EMRANLIB) - -_build/stage3/lib/targets/javascript-unknown-ghcjs/lib/package.conf.d/package.cache: _build/stage3/bin/javascript-unknown-ghcjs-ghc-pkg$(EXE_EXT) _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/settings javascript-unknown-ghcjs-libs - @mkdir -p $(@D) - @rm -rf $(@D)/* - cp -rfp _build/stage3/javascript-unknown-ghcjs/packagedb/host/*/* $(@D) - _build/stage3/bin/javascript-unknown-ghcjs-ghc-pkg$(EXE_EXT) recache - -.PHONY: javascript-unknown-ghcjs-libs -javascript-unknown-ghcjs-libs: private GHC=$(abspath _build/stage3/bin/javascript-unknown-ghcjs-ghc$(EXE_EXT)) -javascript-unknown-ghcjs-libs: private GHC2=$(abspath _build/stage2/bin/ghc$(EXE_EXT)) -javascript-unknown-ghcjs-libs: private STAGE=stage3 -javascript-unknown-ghcjs-libs: private CC=emcc -javascript-unknown-ghcjs-libs: private CROSS_EXTRA_LIB_DIRS=$(JS_EXTRA_LIB_DIRS) -javascript-unknown-ghcjs-libs: private CROSS_EXTRA_INCLUDE_DIRS=$(JS_EXTRA_INCLUDE_DIRS) -javascript-unknown-ghcjs-libs: cabal.project.stage3 _build/stage3/bin/javascript-unknown-ghcjs-ghc-pkg$(EXE_EXT) _build/stage3/bin/javascript-unknown-ghcjs-ghc$(EXE_EXT) _build/stage3/bin/javascript-unknown-ghcjs-hsc2hs$(EXE_EXT) _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/settings _build/stage3/lib/targets/javascript-unknown-ghcjs/bin/unlit$(EXE_EXT) _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/package.conf.d - $(call build_cross,javascript-unknown-ghcjs) - -# --- Stage 3 musl build --- - -.PHONY: stage3-x86_64-musl-linux -stage3-x86_64-musl-linux: x86_64-musl-linux-libs _build/stage3/lib/targets/x86_64-musl-linux/lib/package.conf.d/package.cache - -_build/stage3/lib/targets/x86_64-musl-linux/lib/settings: _build/stage2/lib/targets/x86_64-musl-linux _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) - @mkdir -p $(@D) - _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) $(GHC_TOOLCHAIN_ARGS) --triple x86_64-musl-linux --output-settings -o $@ --cc x86_64-unknown-linux-musl-cc --cxx x86_64-unknown-linux-musl-c++ --ar x86_64-unknown-linux-musl-ar --ranlib x86_64-unknown-linux-musl-ranlib --ld x86_64-unknown-linux-musl-ld - -_build/stage3/lib/targets/x86_64-musl-linux/lib/package.conf.d/package.cache: _build/stage3/bin/x86_64-musl-linux-ghc-pkg$(EXE_EXT) _build/stage3/lib/targets/x86_64-musl-linux/lib/settings x86_64-musl-linux-libs - @mkdir -p $(@D) - @rm -rf $(@D)/* - cp -rfp _build/stage3/x86_64-musl-linux/packagedb/host/*/* $(@D) - _build/stage3/bin/x86_64-musl-linux-ghc-pkg$(EXE_EXT) recache - -.PHONY: x86_64-musl-linux-libs -x86_64-musl-linux-libs: private GHC=$(abspath _build/stage3/bin/x86_64-musl-linux-ghc$(EXE_EXT)) -x86_64-musl-linux-libs: private GHC2=$(abspath _build/stage2/bin/ghc$(EXE_EXT)) -x86_64-musl-linux-libs: private STAGE=stage3 -x86_64-musl-linux-libs: private CC=x86_64-unknown-linux-musl-cc -x86_64-musl-linux-libs: private CROSS_EXTRA_LIB_DIRS=$(MUSL_EXTRA_LIB_DIRS) -x86_64-musl-linux-libs: private CROSS_EXTRA_INCLUDE_DIRS=$(MUSL_EXTRA_INCLUDE_DIRS) -x86_64-musl-linux-libs: _build/stage3/bin/x86_64-musl-linux-ghc-pkg$(EXE_EXT) _build/stage3/bin/x86_64-musl-linux-ghc$(EXE_EXT) _build/stage3/bin/x86_64-musl-linux-hsc2hs$(EXE_EXT) _build/stage3/lib/targets/x86_64-musl-linux/lib/settings _build/stage3/lib/targets/x86_64-musl-linux/bin/unlit$(EXE_EXT) _build/stage3/lib/targets/x86_64-musl-linux/lib/package.conf.d - $(call build_cross,x86_64-musl-linux) - -# --- Stage 3 wasm build --- - -.PHONY: stage3-wasm32-unknown-wasi -stage3-wasm32-unknown-wasi: wasm32-unknown-wasi-libs _build/stage3/lib/targets/wasm32-unknown-wasi/lib/package.conf.d/package.cache _build/stage3/lib/targets/wasm32-unknown-wasi/lib/dyld.mjs _build/stage3/lib/targets/wasm32-unknown-wasi/lib/post-link.mjs _build/stage3/lib/targets/wasm32-unknown-wasi/lib/prelude.mjs _build/stage3/lib/targets/wasm32-unknown-wasi/lib/ghc-interp.js - -_build/stage3/lib/targets/wasm32-unknown-wasi/lib/settings: _build/stage2/lib/targets/wasm32-unknown-wasi _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) - @mkdir -p $(@D) - PATH=/home/hasufell/.ghc-wasm/wasi-sdk/bin:$(PATH) _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) $(GHC_TOOLCHAIN_ARGS) --triple wasm32-unknown-wasi --output-settings -o $@ --cc wasm32-wasi-clang --cxx wasm32-wasi-clang++ --ar ar --ranlib ranlib --ld wasm-ld --merge-objs wasm-ld --merge-objs-opt="-r" --disable-ld-override --disable-tables-next-to-code $(foreach opt,$(WASM_CC_OPTS),--cc-opt=$(opt)) $(foreach opt,$(WASM_CXX_OPTS),--cxx-opt=$(opt)) - -_build/stage3/lib/targets/wasm32-unknown-wasi/lib/package.conf.d/package.cache: _build/stage3/bin/wasm32-unknown-wasi-ghc-pkg$(EXE_EXT) _build/stage3/lib/targets/wasm32-unknown-wasi/lib/settings wasm32-unknown-wasi-libs - @mkdir -p $(@D) - @rm -rf $(@D)/* - cp -rfp _build/stage3/wasm32-unknown-wasi/packagedb/host/*/* $(@D) - _build/stage3/bin/wasm32-unknown-wasi-ghc-pkg$(EXE_EXT) recache - -.PHONY: wasm32-unknown-wasi-libs -wasm32-unknown-wasi-libs: private GHC=$(abspath _build/stage3/bin/wasm32-unknown-wasi-ghc$(EXE_EXT)) -wasm32-unknown-wasi-libs: private GHC2=$(abspath _build/stage2/bin/ghc$(EXE_EXT)) -wasm32-unknown-wasi-libs: private STAGE=stage3 -wasm32-unknown-wasi-libs: private CC=wasm32-wasi-clang -wasm32-unknown-wasi-libs: private CROSS_EXTRA_LIB_DIRS=$(WASM_EXTRA_LIB_DIRS) -wasm32-unknown-wasi-libs: private CROSS_EXTRA_INCLUDE_DIRS=$(WASM_EXTRA_INCLUDE_DIRS) -wasm32-unknown-wasi-libs: cabal.project.stage3 _build/stage3/bin/wasm32-unknown-wasi-ghc-pkg$(EXE_EXT) _build/stage3/bin/wasm32-unknown-wasi-ghc$(EXE_EXT) _build/stage3/bin/wasm32-unknown-wasi-hsc2hs$(EXE_EXT) _build/stage3/lib/targets/wasm32-unknown-wasi/lib/settings _build/stage3/lib/targets/wasm32-unknown-wasi/bin/unlit$(EXE_EXT) _build/stage3/lib/targets/wasm32-unknown-wasi/lib/package.conf.d - $(call build_cross,wasm32-unknown-wasi) - -# --- Bindist --- - -RTS_SUBLIBS := \ - nonthreaded-nodebug \ - nonthreaded-debug \ - threaded-nodebug \ - threaded-debug - -# patchpackageconf -# -# Hacky function to patch up the paths in the package .conf files # -# $1 = package name (ex: 'bytestring') -# TODO: package name is borked for sublibs -# $2 = path to .conf file -# $3 = (relative) path from $${pkgroot} to docs directory -# $4 = host triple -# $5 = package name and version (ex: bytestring-0.13) -# -# NOTE: We must make sure we keep sub-folder structures alive. There might be -# references to $5/build/FOO, we must keep /FOO at the end. One thing not -# retaining this that will break are pubilc sublibraries. -# -# FIXME: cabal should just be able to create .conf file properly relocated. And -# allow us to install them into a pre-defined package-db, this would -# eliminate this nonsense. -define patchpackageconf - case $5 in \ - rts-*-nonthreaded-nodebug) \ - sublib="/nonthreaded-nodebug" ;; \ - rts-*-nonthreaded-debug) \ - sublib="/nonthreaded-debug" ;; \ - rts-*-threaded-nodebug) \ - sublib="/threaded-nodebug" ;; \ - rts-*-threaded-debug) \ - sublib="/threaded-debug" ;; \ - *) \ - sublib="" ;; \ - esac ; \ - $(SED) -i \ - -e "s|haddock-interfaces:.*|haddock-interfaces: \"\$${pkgroot}/$3/html/libraries/$5/$1.haddock\"|" \ - -e "s|haddock-html:.*|haddock-html: \"\$${pkgroot}/$3/html/libraries/$5\"|" \ - -e "s|import-dirs:.*|import-dirs: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ - -e "s|library-dirs:.*|library-dirs: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ - -e "s|library-dirs-static:.*|library-dirs-static: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ - -e "s|dynamic-library-dirs:.*|dynamic-library-dirs: \"\$${pkgroot}/../lib/$4\"|" \ - -e "s|data-dir:.*|data-dir: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ - -e "s|include-dirs:.*|include-dirs: \"\$${pkgroot}/../lib/$4/$5$${sublib}/include\"|" \ - -e "s|^ /.*||" \ - -e "s|^ [A-Z]:.*||" \ - $2 -endef - -# $1 = triplet -define copycrosslib - @cp -rfp _build/stage3/lib/targets/$1 _build/bindist/lib/targets/ - @ffi_incdir=`$(CURDIR)/_build/bindist/bin/$1-ghc-pkg$(EXE_EXT) field libffi-clib include-dirs | grep '/libffi-clib/src/' | sed 's|.*$(CURDIR)/||' || echo "none"` ; cd _build/bindist/lib/targets/$1/lib/package.conf.d ; \ - for pkg in *.conf ; do \ - pkgname=`echo $${pkg} | $(SED) 's/-[0-9.]*\(-[0-9a-zA-Z]*\)\?\.conf//'` ; \ - pkgnamever=`echo $${pkg} | $(SED) 's/\.conf//'` ; \ - mkdir -p $(CURDIR)/_build/bindist/lib/targets/$1/lib/$1/$${pkg%.conf} && \ - cp -rfp $(CURDIR)/_build/stage3/$1/build/host/*/ghc-*/$${pkg%.conf}/build/* $(CURDIR)/_build/bindist/lib/targets/$1/lib/$1/$${pkg%.conf}/ && \ - if [ $${pkgname} = "libffi-clib" ] ; then \ - $(call patchpackageconf,$${pkgname},$${pkg},../../..,$1,$${pkgnamever}) ; \ - else \ - $(call patchpackageconf,$${pkgname},$${pkg},../../..,$1,$${pkgnamever}) ; \ - fi ; \ - done ; \ - if [ $${ffi_incdir} != "none" ] ; then $(call copy_headers,ffitarget.h,$(CURDIR)/$${ffi_incdir},libffi-clib,$(CURDIR)/_build/bindist/bin/$1-ghc-pkg$(EXE_EXT)) ; fi -endef - -# Target for creating the final binary distribution directory -#_build/bindist: stage2 driver/ghc-usage.txt driver/ghci-usage.txt -_build/bindist: stage2 driver/ghc-usage.txt driver/ghci-usage.txt - @echo "::group::Creating binary distribution in $@" - @mkdir -p $@/bin - @mkdir -p $@/lib - # Copy executables from stage2 bin - @cp -rfp _build/stage2/bin/* $@/bin/ - # Copy libraries and settings from stage2 lib - @cp -rfp _build/stage2/lib/{package.conf.d,settings,template-hsc.h} $@/lib/ - @mkdir -p $@/lib/$(HOST_PLATFORM) - @ffi_incdir=`$(CURDIR)/$@/bin/ghc-pkg$(EXE_EXT) field libffi-clib include-dirs | grep 'libffi-clib[/\\]src/' | sed 's/^[ \t]*//' | $(CYGPATH) | sed 's|.*$(CURDIR)/||'` ; \ - cd $@/lib/package.conf.d ; \ - for pkg in *.conf ; do \ - pkgname=`echo $${pkg} | $(SED) 's/-[0-9.]*\(-[0-9a-zA-Z]*\)\?\.conf//'` ; \ - pkgnamever=`echo $${pkg} | $(SED) 's/\.conf//'` ; \ - mkdir -p $(CURDIR)/$@/lib/$(HOST_PLATFORM)/$${pkg%.conf} ; \ - cp -rfp $(CURDIR)/_build/stage2/build/host/*/ghc-*/$${pkg%.conf}/build/* $(CURDIR)/$@/lib/$(HOST_PLATFORM)/$${pkg%.conf} ; \ - if [ $${pkgname} = "libffi-clib" ] ; then \ - $(call patchpackageconf,$${pkgname},$${pkg},../../..,$(HOST_PLATFORM),$${pkgnamever}) ; \ - else \ - $(call patchpackageconf,$${pkgname},$${pkg},../../..,$(HOST_PLATFORM),$${pkgnamever}) ; \ - fi ; \ - done ; \ - $(call copy_headers,ffitarget.h,$(CURDIR)/$${ffi_incdir},libffi-clib,$(CURDIR)/$@/bin/ghc-pkg$(EXE_EXT)) - # Copy driver usage files - @cp -rfp driver/ghc-usage.txt $@/lib/ - @cp -rfp driver/ghci-usage.txt $@/lib/ - @echo "FIXME: Changing 'Support SMP' from YES to NO in settings file" - @$(SED) 's/("Support SMP","YES")/("Support SMP","NO")/' -i.bck $@/lib/settings - # Recache - $@/bin/ghc-pkg$(EXE_EXT) recache - # Copy headers - @$(call copy_all_stage2_h,$@/bin/ghc-pkg$(EXE_EXT)) - @echo "::endgroup::" - -_build/bindist/ghc.tar.gz: _build/bindist - @tar czf $@ \ - --directory=_build/bindist \ - $(foreach exe,$(BINDIST_EXECTUABLES),bin/$(exe)) \ - lib/ghc-usage.txt \ - lib/ghci-usage.txt \ - lib/package.conf.d \ - lib/settings \ - lib/template-hsc.h \ - lib/$(HOST_PLATFORM) - -_build/bindist/lib/targets/%: _build/bindist driver/ghc-usage.txt driver/ghci-usage.txt stage3-% - @echo "::group::Creating binary distribution in $@" - @mkdir -p _build/bindist/bin - @mkdir -p _build/bindist/lib/targets - # Symlinks - @cd _build/bindist/bin ; for binary in * ; do \ - test -L $$binary || ln -sf $$binary $(@F)-$$binary \ - ; done - # Copy libraries and settings - @if [ -e $(CURDIR)/_build/bindist/lib/targets/$(@F)/lib/$(@F) ] ; then find $(CURDIR)/_build/bindist/lib/targets/$(@F)/lib/$(@F)/ -mindepth 1 -type f -name "*.so" -execdir mv '{}' $(CURDIR)/_build/bindist/lib/targets/$(@F)/lib/$(@F)/'{}' \; ; fi - $(call copycrosslib,$(@F)) - # --help - @cp -rfp driver/ghc-usage.txt _build/bindist/lib/targets/$(@F)/lib/ - @cp -rfp driver/ghci-usage.txt _build/bindist/lib/targets/$(@F)/lib/ - # Recache - @_build/bindist/bin/$(@F)-ghc-pkg$(EXE_EXT) recache - # Copy headers - @$(call copy_all_stage3_h,_build/bindist/bin/$(@F)-ghc-pkg$(EXE_EXT),$(@F)) - @echo "::endgroup::" - -_build/bindist/ghc-%.tar.gz: _build/bindist/lib/targets/% _build/bindist/ghc.tar.gz - @triple=`basename $<` ; \ - tar czf $@ \ - --directory=_build/bindist \ - $(foreach exe,$(BINDIST_EXECTUABLES),bin/$${triple}-$(exe)) \ - lib/targets/$${triple} - -_build/bindist/cabal.tar.gz: _build/stage0/bin/cabal$(EXE_EXT) - @mkdir -p _build/bindist/bin - @cp $^ _build/bindist/bin/cabal$(EXE_EXT) - @tar czf $@ \ - --directory=_build/bindist \ - bin/cabal$(EXE_EXT) - -_build/bindist/haskell-toolchain.tar.gz: _build/bindist/cabal.tar.gz _build/bindist/ghc.tar.gz _build/bindist/ghc-javascript-unknown-ghcjs.tar.gz - @tar czf $@ \ - --directory=_build/bindist \ - $(foreach exe,$(BINDIST_EXECTUABLES),bin/$(exe)$(EXE_EXT)) \ - lib/ghc-usage.txt \ - lib/ghci-usage.txt \ - lib/package.conf.d \ - lib/settings \ - lib/template-hsc.h \ - lib/$(HOST_PLATFORM) \ - $(foreach exe,$(BINDIST_EXECTUABLES),bin/javascript-unknown-ghcjs-$(exe)) \ - lib/targets/javascript-unknown-ghcjs \ - bin/cabal$(EXE_EXT) - -_build/bindist/tests.tar.gz: - @tar czf $@ \ - testsuite - -# --- Hackage --- - -$(GHC1) $(GHC2): | hackage -hackage: _build/packages/hackage.haskell.org/01-index.tar.gz - -# Always run cabal update. This makes sure that the index file won't go stale, -# whatever index-state we set in the project file. Reproducibility is left to -# index-state. -.PHONY: _build/packages/hackage.haskell.org/01-index.tar.gz -_build/packages/hackage.haskell.org/01-index.tar.gz: | $(CABAL) - @mkdir -p $(@D) - $(CABAL) $(CABAL_ARGS) update - -# --- Configure and source preparation --- - -$(CONFIGURE_SCRIPTS) : % : %.ac - @echo ">>> Running autoreconf $(@D)" - autoreconf $(@D) - @echo "::endgroup::" - -# Top level configure script. -# -# NOTE: other configure scripts are run by Cabal -# -# We use --no-create to avoid regenerating files if not needed. -# Each configured file is tracked independently below. -config.status: configure - @echo ">>> Running $(@D)/configure" - $(@D)/configure --no-create $(GHC_CONFIGURE_ARGS) - @echo "::endgroup::" +all: _build/bindist/stage2 -# Configured files are obtained from their .in counterparts via config.status -$(CONFIGURED_FILES) : % : ./config.status %.in - ./config.status $@ - -# Create ghc-boot-th-next from ghc-boot-th -libraries/ghc-boot-th-next/ghc-boot-th-next.cabal: libraries/ghc-boot-th/ghc-boot-th.cabal - @echo "::group::Synthesizing ghc-boot-th-next (copy & sed from ghc-boot-th)..." - @mkdir -p libraries/ghc-boot-th-next - sed -e 's/^name:[[:space:]]*ghc-boot-th$$/name: ghc-boot-th-next/' $< > $@ - @echo "::endgroup::" # --- Clean Targets --- -clean-cabal: clean-stage0 - -clean-stage0: - @echo "::group::Cleaning build artifacts..." - rm -rf _build/stage0 +# +clean: clean-stage1 clean-stage2 clean-stage3 rm -f libraries/ghc-boot-th-next/ghc-boot-th-next.cabal rm -f libraries/ghc-boot-th-next/ghc-boot-th-next.cabal.in rm -f libraries/ghc-boot-th-next/.synth-stamp - @echo "::endgroup::" - -clean: clean-stage1 clean-stage2 clean-stage3 - @echo "Not removing stage0 (cabal), use clean-stage0 to remove cabal too." - -clean-stage1: - @echo "::group::Cleaning stage1 build artifacts..." - rm -rf _build/stage1 - @echo "::endgroup::" - -clean-stage2: - @echo "::group::Cleaning stage2 build artifacts..." - rm -rf _build/stage2 - @echo "::endgroup::" - -clean-stage3: - @echo "::group::Cleaning stage3 build artifacts..." - rm -rf _build/stage3 - rm -rf _build/stage2/lib/targets - @echo "::endgroup::" distclean: clean @echo "::group::Cleaning all generated files (distclean)..." @@ -1101,53 +111,5 @@ distclean: clean rm -rf libraries/ghc-boot-th-next @echo "::endgroup::" -# Default: skip performance tests (can override with SKIP_PERF_TESTS=NO) -SKIP_PERF_TESTS ?= YES -export SKIP_PERF_TESTS - -# --- Test Suite Helper Tool Paths & Flags (Hadrian parity light) --- -# We approximate Hadrian's test invocation without depending on Hadrian. -# Bindist places test tools in _build/bindist/bin (created by the bindist target). -TEST_TOOLS_DIR := _build/bindist/bin -TEST_GHC := $(abspath $(TEST_TOOLS_DIR)/ghc$(EXE_EXT)) -TEST_GHC_PKG := $(abspath $(TEST_TOOLS_DIR)/ghc-pkg$(EXE_EXT)) -TEST_HP2PS := $(abspath $(TEST_TOOLS_DIR)/hp2ps$(EXE_EXT)) -TEST_HPC := $(abspath $(TEST_TOOLS_DIR)/hpc$(EXE_EXT)) -TEST_RUN_GHC := $(abspath $(TEST_TOOLS_DIR)/runghc$(EXE_EXT)) - -# Canonical GHC flags used by the testsuite (mirrors testsuite/mk/test.mk & Hadrian runTestGhcFlags) -CANONICAL_TEST_HC_OPTS = \ - -dcore-lint -dstg-lint -dcmm-lint -no-user-package-db -fno-dump-with-ways \ - -fprint-error-index-links=never -rtsopts -fno-warn-missed-specialisations \ - -fshow-warning-groups -fdiagnostics-color=never -fno-diagnostics-show-caret \ - -Werror=compat -dno-debug-output - -# Build timeout utility (needed for some tests) if not already built. -.PHONY: testsuite-timeout -testsuite-timeout: - $(MAKE) -C testsuite/timeout - -# --- Test Target --- - -test: _build/bindist testsuite-timeout - @echo "::group::Running tests with THREADS=$(THREADS)" >&2 - # If any required tool is missing, testsuite logic will skip related tests. - TEST_HC='$(TEST_GHC)' \ - GHC_PKG='$(TEST_GHC_PKG)' \ - HP2PS_ABS='$(TEST_HP2PS)' \ - HPC='$(TEST_HPC)' \ - RUNGHC='$(TEST_RUN_GHC)' \ - TEST_CC='$(CC)' \ - TEST_CXX='$(CXX)' \ - TEST_HC_OPTS='$(CANONICAL_TEST_HC_OPTS)' \ - METRICS_FILE='$(CURDIR)/_build/test-perf.csv' \ - SUMMARY_FILE='$(CURDIR)/_build/test-summary.txt' \ - JUNIT_FILE='$(CURDIR)/_build/test-junit.xml' \ - SKIP_PERF_TESTS='$(SKIP_PERF_TESTS)' \ - THREADS='$(THREADS)' \ - $(MAKE) -C testsuite/tests test - @echo "::endgroup::" - -# Inform Make that these are not actual files if they get deleted by other means -.PHONY: clean clean-stage1 clean-stage2 clean-stage3 distclean test all +.PHONY: clean distclean all diff --git a/build-cabal.sh b/build-cabal.sh new file mode 100755 index 000000000000..81ae6540a09c --- /dev/null +++ b/build-cabal.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -e + +cabal build \ + ${CABAL0_ARGS} \ + -j \ + --disable-tests \ + --project-dir libraries/Cabal \ + --builddir=$(pwd)/build/stage0 \ + --ghc-options="-fhide-source-paths" \ + cabal-install:exe:cabal 1>&2 + +exec cabal list-bin \ + ${CABAL0_ARGS} \ + -v0 \ + -j \ + --disable-tests \ + --project-dir libraries/Cabal \ + --builddir=$(pwd)/build/stage0 \ + --ghc-options="-fhide-source-paths" \ + cabal-install:exe:cabal diff --git a/libraries/Cabal b/libraries/Cabal index 2309d2ca2d27..8e9a1e3e7503 160000 --- a/libraries/Cabal +++ b/libraries/Cabal @@ -1 +1 @@ -Subproject commit 2309d2ca2d276fe9fa2c971a8e4912602461c991 +Subproject commit 8e9a1e3e7503f26360356b4a4563427ca5579972 diff --git a/mk/stable-haskell/boot.mk b/mk/stable-haskell/boot.mk new file mode 100644 index 000000000000..c3587fc3ecb4 --- /dev/null +++ b/mk/stable-haskell/boot.mk @@ -0,0 +1,73 @@ +CONFIGURE_SCRIPTS = \ + configure \ + rts/configure \ + libraries/ghc-internal/configure \ + libraries/libffi-clib/configure \ + libraries/directory/configure \ + libraries/process/configure \ + libraries/terminfo/configure \ + libraries/time/configure \ + libraries/unix/configure + +# Files that will be generated by config.status from their .in counterparts +# FIXME: This is stupid. Why do we patch versions across multiple libraries? Idiotic. +# also, why on earth do we use a non standard SnakeCase convention for substitutions +# when CAPITAL_CASE is the standard? +CONFIGURED_FILES := \ + ghc/ghc-bin.cabal \ + compiler/GHC/CmmToLlvm/Version/Bounds.hs \ + compiler/ghc.cabal \ + libraries/ghc-boot/ghc-boot.cabal \ + libraries/ghc-boot-th/ghc-boot-th.cabal \ + libraries/ghc-heap/ghc-heap.cabal \ + libraries/template-haskell/template-haskell.cabal \ + libraries/ghci/ghci.cabal \ + utils/ghc-pkg/ghc-pkg.cabal \ + utils/ghc-iserv/ghc-iserv.cabal \ + utils/runghc/runghc.cabal \ + libraries/ghc-internal/ghc-internal.cabal \ + libraries/ghc-experimental/ghc-experimental.cabal \ + libraries/base/base.cabal \ + rts/include/ghcversion.h + +# --- Hackage --- + +$(GHC1) $(GHC2): | hackage +hackage: _build/packages/hackage.haskell.org/01-index.tar.gz + +# Always run cabal update. This makes sure that the index file won't go stale, +# whatever index-state we set in the project file. Reproducibility is left to +# index-state. +.PHONY: _build/packages/hackage.haskell.org/01-index.tar.gz +_build/packages/hackage.haskell.org/01-index.tar.gz: + @mkdir -p $(@D) + $(CABAL) $(CABAL_ARGS) update + +# --- Configure and source preparation --- + +$(CONFIGURE_SCRIPTS) : % : %.ac + @echo ">>> Running autoreconf $(@D)" + autoreconf $(@D) + @echo "::endgroup::" + +# Top level configure script. +# +# NOTE: other configure scripts are run by Cabal +# +# We use --no-create to avoid regenerating files if not needed. +# Each configured file is tracked independently below. +config.status: configure + @echo ">>> Running $(@D)/configure" + $(@D)/configure --no-create $(GHC_CONFIGURE_ARGS) + @echo "::endgroup::" + +# Configured files are obtained from their .in counterparts via config.status +$(CONFIGURED_FILES) : % : ./config.status %.in + ./config.status $@ + +# Create ghc-boot-th-next from ghc-boot-th +libraries/ghc-boot-th-next/ghc-boot-th-next.cabal: libraries/ghc-boot-th/ghc-boot-th.cabal + @echo "::group::Synthesizing ghc-boot-th-next (copy & sed from ghc-boot-th)..." + @mkdir -p libraries/ghc-boot-th-next + sed -e 's/^name:[[:space:]]*ghc-boot-th$$/name: ghc-boot-th-next/' $< > $@ + @echo "::endgroup::" diff --git a/mk/stable-haskell/headers.mk b/mk/stable-haskell/headers.mk new file mode 100644 index 000000000000..2833113bf01e --- /dev/null +++ b/mk/stable-haskell/headers.mk @@ -0,0 +1,226 @@ +MK_COPY_HEADERS := 1 + +# --- Source headers --- +# TODO: this is a hack, because of https://github.com/haskell/cabal/issues/11172 +# +# $1 = headers +# $2 = source base dirs +# $3 = pkgname +# $4 = ghc-pkg +define copy_headers + set -e; \ + dest=`$4 field $3 include-dirs | awk '{ print $$2 ; exit }'` ;\ + for h in $1 ; do \ + mkdir -p "$$dest/`dirname $$h`" ; \ + for sdir in $2 ; do \ + if [ -e "$$sdir/$$h" ] ; then \ + cp -frp "$$sdir/$$h" "$$dest/$$h" ; \ + break ; \ + fi ; \ + done ; \ + [ -e "$$dest/$$h" ] || { echo "Copying $$dest/$$h failed... tried source dirs $2" >&2 ; exit 2 ; } ; \ + done +endef + +RTS_HEADERS_H := \ + rts/Bytecodes.h \ + rts/storage/ClosureTypes.h \ + rts/storage/FunTypes.h \ + stg/MachRegs.h \ + stg/MachRegs/arm32.h \ + stg/MachRegs/arm64.h \ + stg/MachRegs/loongarch64.h \ + stg/MachRegs/ppc.h \ + stg/MachRegs/riscv64.h \ + stg/MachRegs/s390x.h \ + stg/MachRegs/wasm32.h \ + stg/MachRegs/x86.h + +define copy_rts_headers_h + $(call copy_headers,$(RTS_HEADERS_H),rts-headers/include/,rts-headers,$1) +endef + +RTS_FS_H := \ + fs.h + +define copy_rts_fs_h + $(call copy_headers,$(RTS_FS_H),rts-fs/,rts-fs,$1) +endef + +RTS_H := \ + Cmm.h \ + HsFFI.h \ + MachDeps.h \ + Jumps.h \ + Rts.h \ + RtsAPI.h \ + RtsSymbols.h \ + Stg.h \ + ghcconfig.h \ + ghcversion.h \ + rts/ghc_ffi.h \ + rts/Adjustor.h \ + rts/ExecPage.h \ + rts/BlockSignals.h \ + rts/Config.h \ + rts/Constants.h \ + rts/EventLogFormat.h \ + rts/EventLogWriter.h \ + rts/FileLock.h \ + rts/Flags.h \ + rts/ForeignExports.h \ + rts/GetTime.h \ + rts/Globals.h \ + rts/Hpc.h \ + rts/IOInterface.h \ + rts/Libdw.h \ + rts/LibdwPool.h \ + rts/Linker.h \ + rts/Main.h \ + rts/Messages.h \ + rts/NonMoving.h \ + rts/OSThreads.h \ + rts/Parallel.h \ + rts/PrimFloat.h \ + rts/Profiling.h \ + rts/IPE.h \ + rts/PosixSource.h \ + rts/RtsToHsIface.h \ + rts/Signals.h \ + rts/SpinLock.h \ + rts/StableName.h \ + rts/StablePtr.h \ + rts/StaticPtrTable.h \ + rts/TTY.h \ + rts/Threads.h \ + rts/Ticky.h \ + rts/Time.h \ + rts/Timer.h \ + rts/TSANUtils.h \ + rts/Types.h \ + rts/Utils.h \ + rts/prof/CCS.h \ + rts/prof/Heap.h \ + rts/prof/LDV.h \ + rts/storage/Block.h \ + rts/storage/ClosureMacros.h \ + rts/storage/Closures.h \ + rts/storage/Heap.h \ + rts/storage/HeapAlloc.h \ + rts/storage/GC.h \ + rts/storage/InfoTables.h \ + rts/storage/MBlock.h \ + rts/storage/TSO.h \ + stg/DLL.h \ + stg/MiscClosures.h \ + stg/Prim.h \ + stg/Regs.h \ + stg/SMP.h \ + stg/Ticky.h \ + stg/MachRegsForHost.h \ + stg/Types.h + +RTS_H_DIRS := \ + rts/ \ + rts/include/ + +define copy_rts_h + $(call copy_headers,$(RTS_H),$(RTS_H_DIRS),rts,$1) +endef + +RTS_JS_H := \ + HsFFI.h \ + MachDeps.h \ + Rts.h \ + RtsAPI.h \ + Stg.h \ + ghcconfig.h \ + ghcversion.h \ + stg/MachRegsForHost.h \ + stg/Types.h + +define copy_rts_js_h + $(call copy_headers,$(RTS_JS_H),rts/include/,rts,$1) +endef + +HASKELINE_H := \ + win_console.h + +define copy_haskeline_h + $(call copy_headers,$(HASKELINE_H),libraries/haskeline/includes,haskeline,$1) +endef + +WIN32_H := \ + HsWin32.h \ + HsGDI.h \ + WndProc.h \ + windows_cconv.h \ + alphablend.h \ + wincon_compat.h \ + winternl_compat.h \ + winuser_compat.h \ + winreg_compat.h \ + tlhelp32_compat.h \ + winnls_compat.h \ + winnt_compat.h \ + namedpipeapi_compat.h + +define copy_win32_h + $(call copy_headers,$(WIN32_H),libraries/Win32/include/,Win32,$1) +endef + +GHC_INTERNAL_H := \ + HsBase.h \ + consUtils.h + +define copy_ghc_internal_h + $(call copy_headers,$(GHC_INTERNAL_H),libraries/ghc-internal/include/,ghc-internal,$1) +endef + +PROCESS_H := \ + runProcess.h \ + processFlags.h + +define copy_process_h + $(call copy_headers,$(PROCESS_H),libraries/process/include/,process,$1) +endef + +BYTESTRING_H := \ + fpstring.h \ + bytestring-cpp-macros.h + +define copy_bytestring_h + $(call copy_headers,$(BYTESTRING_H),libraries/bytestring/include/,bytestring,$1) +endef + +TIME_H := \ + HsTime.h + +define copy_time_h + $(call copy_headers,$(TIME_H),libraries/time/lib/include/,time,$1) +endef + +UNIX_H := \ + HsUnix.h \ + execvpe.h + +define copy_unix_h + $(call copy_headers,$(UNIX_H),libraries/unix/include/,unix,$1) +endef + +define copy_all_stage3_h + $(call copy_rts_headers_h,$1) + $(call copy_rts_fs_h,$1) + $(call copy_rts_h,$1) + if [ "$2" = "javascript-unknown-ghcjs" ] ; then $(call copy_rts_js_h,$1) ; fi + $(call copy_ghc_internal_h,$1) + $(call copy_process_h,$1) + $(call copy_bytestring_h,$1) + $(call copy_time_h,$1) + if [ "$(OS)" = "Windows_NT" ] ; then $(call copy_win32_h,$1) ; else $(call copy_unix_h,$1) ; fi +endef + +define copy_all_stage2_h + $(call copy_all_stage3_h,$1,none) + $(call copy_haskeline_h,$1) +endef diff --git a/mk/stable-haskell/pkg-conf.mk b/mk/stable-haskell/pkg-conf.mk new file mode 100644 index 000000000000..ef7b27548452 --- /dev/null +++ b/mk/stable-haskell/pkg-conf.mk @@ -0,0 +1,46 @@ +MK_PKG_CONF := 1 + +# patchpackageconf +# +# Hacky function to patch up the paths in the package .conf files +# +# $1 = package name (ex: 'bytestring') +# TODO: package name is borked for sublibs +# $2 = path to .conf file +# $3 = (relative) path from $${pkgroot} to docs directory +# $4 = host triple +# $5 = package name and version (ex: bytestring-0.13) +# +# NOTE: We must make sure we keep sub-folder structures alive. There might be +# references to $5/build/FOO, we must keep /FOO at the end. One thing not +# retaining this that will break are pubilc sublibraries. +# +# FIXME: cabal should just be able to create .conf file properly relocated. And +# allow us to install them into a pre-defined package-db, this would +# eliminate this nonsense. +define patchpackageconf + case $5 in \ + rts-*-nonthreaded-nodebug) \ + sublib="/nonthreaded-nodebug" ;; \ + rts-*-nonthreaded-debug) \ + sublib="/nonthreaded-debug" ;; \ + rts-*-threaded-nodebug) \ + sublib="/threaded-nodebug" ;; \ + rts-*-threaded-debug) \ + sublib="/threaded-debug" ;; \ + *) \ + sublib="" ;; \ + esac ; \ + $(SED) -i \ + -e "s|haddock-interfaces:.*|haddock-interfaces: \"\$${pkgroot}/$3/html/libraries/$5/$1.haddock\"|" \ + -e "s|haddock-html:.*|haddock-html: \"\$${pkgroot}/$3/html/libraries/$5\"|" \ + -e "s|import-dirs:.*|import-dirs: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ + -e "s|library-dirs:.*|library-dirs: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ + -e "s|library-dirs-static:.*|library-dirs-static: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ + -e "s|dynamic-library-dirs:.*|dynamic-library-dirs: \"\$${pkgroot}/../lib/$4\"|" \ + -e "s|data-dir:.*|data-dir: \"\$${pkgroot}/../lib/$4/$5$${sublib}\"|" \ + -e "s|include-dirs:.*|include-dirs: \"\$${pkgroot}/../lib/$4/$5$${sublib}/include\"|" \ + -e "s|^ /.*||" \ + -e "s|^ [A-Z]:.*||" \ + $2 +endef diff --git a/mk/stable-haskell/stage1.mk b/mk/stable-haskell/stage1.mk new file mode 100644 index 000000000000..baf8f94d9500 --- /dev/null +++ b/mk/stable-haskell/stage1.mk @@ -0,0 +1,121 @@ +ifndef MK_TOOLCHAIN +include mk/stable-haskell/toolchain.mk +endif + +STAGE1_UTIL_TARGETS := \ + deriveConstants:deriveConstants \ + genapply:genapply \ + genprimopcode:genprimopcode \ + ghc-pkg:ghc-pkg \ + hsc2hs:hsc2hs \ + rts-headers:rts-headers \ + unlit:unlit + +STAGE1_TARGETS := $(STAGE1_UTIL_TARGETS) ghc-bin:ghc ghc-toolchain-bin:ghc-toolchain-bin + +BINDIST1_EXECTUABLES := \ + ghc$(EXE_EXT) \ + ghc-pkg$(EXE_EXT) \ + ghc-toolchain-bin$(EXE_EXT) \ + hsc2hs$(EXE_EXT) \ + unlit$(EXE_EXT) + +# TODO: dedup +STAGE1_EXECUTABLES := \ + deriveConstants$(EXE_EXT) \ + genapply$(EXE_EXT) \ + genprimopcode$(EXE_EXT) \ + ghc$(EXE_EXT) \ + ghc-pkg$(EXE_EXT) \ + ghc-toolchain-bin$(EXE_EXT) \ + hsc2hs$(EXE_EXT) \ + unlit$(EXE_EXT) + +# --- Stage 1 build --- + +_build/stage1/%: private STAGE=stage1 +_build/stage1/%: private GHC=$(GHC0) + +.PHONY: cabal.project.stage1.local + +cabal.project.stage1.local: cabal.project.stage1 +ifeq ($(OS),Windows_NT) + echo "extra-prog-path: $(shell echo '$(GHC_LIBDIR)' | $(CYGPATH_MIXED))/../mingw/bin" > $@ +else + echo "" > $@ +endif + +_build/stage1/bin: stage1 + @mkdir -p $@ + +.PHONY: $(addprefix _build/stage1/bin/,$(STAGE1_EXECUTABLES)) +$(addprefix _build/stage1/bin/,$(STAGE1_EXECUTABLES)) &: private TARGET_PLATFORM= +$(addprefix _build/stage1/bin/,$(STAGE1_EXECUTABLES)) &: $(CONFIGURE_SCRIPTS) $(CONFIGURED_FILES) libraries/ghc-boot-th-next/ghc-boot-th-next.cabal cabal.project.stage1 cabal.project.stage1.local + @echo "::group::Building stage1 executables ($(STAGE1_EXECUTABLES))..." + # Force cabal to replan + rm -rf _build/stage1/cache + HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' $(CABAL_BUILD) $(STAGE1_TARGETS) + @echo "::endgroup::" + +_build/stage1/lib/settings: _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) + @echo "::group::Creating settings for $(TARGET_TRIPLE)..." + @mkdir -p $(@D) + _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) $(GHC_TOOLCHAIN_ARGS) --triple $(TARGET_TRIPLE) --output-settings -o $@ --cc $(CC) --cxx $(CXX) --cc-link-opt "$(CC_LINK_OPT)" + @echo "::endgroup::" + +# The somewhat strange thing is, we might not even need this at all now anymore. cabal seems to +# pass all the necessary flags correctly. Thus even with an _empty_ package-db here (and it will +# stay empty until we are done with the build), the build succeeds. +# +# For now, we are tying the knot here by making sure the stage1 compiler (stage1/bin/ghc) sees +# the packages it builds (to build stage2/bin/ghc), by symlining cabal's target package-db into +# the compilers global package-db. Another maybe even better solution might be to set the +# Global Package DB in the settings file to the absolute path where cabal will place the +# package db. This would elminate this rule outright. +_build/stage1/lib/package.conf.d/package.cache: _build/stage1/bin/ghc-pkg$(EXE_EXT) _build/stage1/lib/settings + @echo "::group::Creating stage1 package cache..." + @mkdir -p _build/stage1/lib/package.conf.d +# @mkdir -p _build/stage2/packagedb/host +# ln -s $(abspath ./_build/stage2/packagedb/host/ghc-9.14) _build/stage1/lib/package.conf.d +# _build/stage1/bin/ghc-pkg init $(abspath ./_build/stage2/packagedb/host/ghc-9.14) + @echo "::endgroup::" + +_build/stage1/lib/template-hsc.h: utils/hsc2hs/data/template-hsc.h + @mkdir -p $(@D) + cp -rfp $< $@ + +.PHONY: stage1 +stage1: $(addprefix _build/stage1/bin/,$(STAGE1_EXECUTABLES)) _build/stage1/lib/settings _build/stage1/lib/package.conf.d/package.cache _build/stage1/lib/template-hsc.h + +_build/bindist/stage1: stage1 driver/ghc-usage.txt driver/ghci-usage.txt + @echo "::group::Creating binary distribution in $@" + @mkdir -p $@/bin + @mkdir -p $@/lib + # Copy executables from stage bin + @cp -rfp _build/$(@F)/bin/* $@/bin/ + # Copy libraries and settings from stage lib + @cp -rfp _build/$(@F)/lib/{package.conf.d,settings,template-hsc.h} $@/lib/ + @mkdir -p $@/lib/$(HOST_PLATFORM) + # Copy driver usage files + @cp -rfp driver/ghc-usage.txt $@/lib/ + @cp -rfp driver/ghci-usage.txt $@/lib/ + @echo "FIXME: Changing 'Support SMP' from YES to NO in settings file" + @$(SED) 's/("Support SMP","YES")/("Support SMP","NO")/' -i.bck $@/lib/settings + @echo "::endgroup::" + +_build/bindist/stage1/ghc.tar.gz: _build/bindist/stage1 + @tar czf $@ \ + --directory=_build/bindist/stage1 \ + $(foreach exe,$(BINDIST1_EXECTUABLES),bin/$(exe)) \ + lib/ghc-usage.txt \ + lib/ghci-usage.txt \ + lib/package.conf.d \ + lib/settings \ + lib/template-hsc.h \ + lib/$(HOST_PLATFORM) + +.PHONY: clean-stage1 +clean-stage1: + @echo "::group::Cleaning stage1 build artifacts..." + rm -rf _build/stage1 + @echo "::endgroup::" diff --git a/mk/stable-haskell/stage2.mk b/mk/stable-haskell/stage2.mk new file mode 100644 index 000000000000..8486196c60d1 --- /dev/null +++ b/mk/stable-haskell/stage2.mk @@ -0,0 +1,208 @@ +ifndef MK_TOOLCHAIN +include mk/stable-haskell/toolchain.mk +endif + +ifndef MK_COPY_HEADERS +include mk/stable-haskell/headers.mk +endif + +ifndef MK_PKG_CONF +include mk/stable-haskell/pkg-conf.mk +endif + +STAGE2_UTIL_TARGETS := \ + deriveConstants:deriveConstants \ + genapply:genapply \ + genprimopcode:genprimopcode \ + ghc-pkg:ghc-pkg \ + hsc2hs:hsc2hs \ + rts-headers:rts-headers \ + unlit:unlit + +# We really want to work towards `cabal build/instsall ghc-bin:ghc`. +STAGE2_TARGETS := \ + ghc-bin:ghc + +# we need to build these before all else +STAGE2_UTIL_RTS := \ + rts:nonthreaded-debug \ + rts:nonthreaded-nodebug \ + rts:threaded-nodebug \ + rts:threaded-debug + +# rts:threaded-nodebug need it for compiling Setup.hs +STAGE2_UTIL_TARGETS := \ + $(STAGE2_UTIL_TARGETS) \ + ghc-iserv:ghc-iserv \ + $(STAGE2_UTIL_RTS) \ + hp2ps:hp2ps \ + hpc-bin:hpc \ + runghc:runghc \ + ghc-bignum:ghc-bignum \ + ghc-compact:ghc-compact \ + ghc-experimental:ghc-experimental \ + ghc-toolchain:ghc-toolchain \ + integer-gmp:integer-gmp \ + system-cxx-std-lib:system-cxx-std-lib \ + xhtml:xhtml \ + haddock:haddock + +ifneq ($(OS),Windows_NT) +STAGE2_UTIL_TARGETS += terminfo:terminfo +endif + +# These things should be built on demand. +# hp2ps:hp2ps \ +# hpc-bin:hpc \ +# ghc-iserv:ghc-iserv \ +# runghc:runghc \ + +# This package is just utterly retarded +# I don't understand why this following line somehow breaks the build... +# STAGE2_TARGETS += system-cxx-std-lib:system-cxx-std-lib + +BINDIST2_EXECTUABLES := \ + ghc$(EXE_EXT) \ + ghc-iserv$(EXE_EXT) \ + ghc-pkg$(EXE_EXT) \ + hp2ps$(EXE_EXT) \ + hpc$(EXE_EXT) \ + hsc2hs$(EXE_EXT) \ + runghc$(EXE_EXT) \ + unlit$(EXE_EXT) \ + haddock$(EXE_EXT) + +# TODO: dedup +STAGE2_EXECUTABLES := \ + ghc$(EXE_EXT) + +STAGE2_UTIL_EXECUTABLES := \ + deriveConstants$(EXE_EXT) \ + genapply$(EXE_EXT) \ + genprimopcode$(EXE_EXT) \ + hsc2hs$(EXE_EXT) \ + ghc-iserv$(EXE_EXT) \ + ghc-pkg$(EXE_EXT) \ + hp2ps$(EXE_EXT) \ + hpc$(EXE_EXT) \ + runghc$(EXE_EXT) \ + unlit$(EXE_EXT) \ + haddock$(EXE_EXT) + +# --- Stage 2 build --- + +_build/stage2/%: private STAGE=stage2 +_build/stage2/%: private GHC=$(realpath $(GHC1)) + +.PHONY: $(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) +$(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) &: private TARGET_PLATFORM= +$(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) &: $(GHC_BIN1) $(GHC1) $(GHC_PKG1) $(GHC_TOOLCHAIN1) cabal.project.stage2 stage2-rts + @echo "::group::Building stage2 executables ($(STAGE2_EXECUTABLES))..." + # Force cabal to replan + rm -rf _build/stage2/cache + GHC=$(GHC) HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ + PATH='$(realpath $(GHC_BIN1)):$(PATH)' \ + $(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) $(STAGE2_TARGETS) + @echo "::endgroup::" + +.PHONY: stage2-rts +stage2-rts: private STAGE=stage2 +stage2-rts: private GHC=$(realpath $(GHC1)) +stage2-rts: private TARGET_PLATFORM= +stage2-rts: $(GHC_BIN1) $(GHC1) $(GHC_PKG1) $(GHC_TOOLCHAIN1) cabal.project.stage2 + @echo "::group::Building stage2 RTSes..." + # Force cabal to replan + rm -rf _build/stage2/cache + GHC=$(GHC) HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ + PATH='$(realpath $(GHC_BIN1)):$(PATH)' \ + $(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) $(STAGE2_UTIL_RTS) + @echo "::endgroup::" + + +# Do we want to build these with the stage2 GHC or the stage1 GHC? +# Traditionally we build them with the stage1 ghc, but we could just as well +# build them with the stage2 ghc; seems like a better/cleaner idea to me (moritz). +.PHONY: $(addprefix _build/stage2/bin/,$(STAGE2_UTIL_EXECUTABLES)) +$(addprefix _build/stage2/bin/,$(STAGE2_UTIL_EXECUTABLES)) &: private TARGET_PLATFORM= +$(addprefix _build/stage2/bin/,$(STAGE2_UTIL_EXECUTABLES)) &: $(GHC_BIN1) $(GHC1) $(GHC_PKG1) $(GHC_TOOLCHAIN1) cabal.project.stage2.settings stage2-rts + @echo "::group::Building stage2 utilities ($(STAGE2_UTIL_EXECUTABLES))..." + # Force cabal to replan + rm -rf _build/stage2/cache + GHC=$(GHC) HADRIAN_SETTINGS='$(HADRIAN_SETTINGS)' \ + PATH='$(realpath $(GHC_BIN1)):$(PATH)' \ + $(CABAL_BUILD) --ghc-options="-ghcversion-file=$(abspath ./rts/include/ghcversion.h)" -W $(GHC0) $(STAGE2_UTIL_TARGETS) + @echo "::endgroup::" + +_build/stage2/lib/settings: $(GHC_TOOLCHAIN1) + @echo "::group::Creating settings for $(TARGET_TRIPLE)..." + @mkdir -p $(@D) + $(GHC_TOOLCHAIN1) $(GHC_TOOLCHAIN_ARGS) --triple $(TARGET_TRIPLE) --output-settings -o $@ --cc $(CC) --cxx $(CXX) --cc-link-opt "$(CC_LINK_OPT)" + @echo "::endgroup::" + +_build/stage2/lib/package.conf.d/package.cache: _build/stage2/bin/ghc-pkg$(EXE_EXT) _build/stage2/lib/settings + @echo "::group::Creating stage2 package cache..." + @mkdir -p _build/stage2/lib/package.conf.d + @rm -rf _build/stage2/lib/package.conf.d/* + cp -rfp _build/stage2/packagedb/host/*/* _build/stage2/lib/package.conf.d + _build/stage2/bin/ghc-pkg$(EXE_EXT) recache + @echo "::endgroup::" + +_build/stage2/lib/template-hsc.h: utils/hsc2hs/data/template-hsc.h + @mkdir -p $(@D) + cp -rfp $< $@ + +.PHONY: stage2 +stage2: $(addprefix _build/stage2/bin/,$(STAGE2_EXECUTABLES)) _build/stage2/lib/settings _build/stage2/lib/package.conf.d/package.cache _build/stage2/lib/template-hsc.h + +# Target for creating the final binary distribution directory +#_build/bindist: stage2 driver/ghc-usage.txt driver/ghci-usage.txt +_build/bindist/stage2: stage2 driver/ghc-usage.txt driver/ghci-usage.txt + @echo "::group::Creating binary distribution in $@" + @mkdir -p $@/bin + @mkdir -p $@/lib + # Copy executables from stage bin + @cp -rfp _build/$(@F)/bin/* $@/bin/ + # Copy libraries and settings from stage lib + @cp -rfp _build/$(@F)/lib/{package.conf.d,settings,template-hsc.h} $@/lib/ + @mkdir -p $@/lib/$(HOST_PLATFORM) + @ffi_incdir=`$(CURDIR)/$@/bin/ghc-pkg$(EXE_EXT) field libffi-clib include-dirs | grep 'libffi-clib[/\\]src/' | sed 's/^[ \t]*//' | $(CYGPATH) | sed 's|.*$(CURDIR)/||'` ; \ + cd $@/lib/package.conf.d ; \ + for pkg in *.conf ; do \ + pkgname=`echo $${pkg} | $(SED) 's/-[0-9.]*\(-[0-9a-zA-Z]*\)\?\.conf//'` ; \ + pkgnamever=`echo $${pkg} | $(SED) 's/\.conf//'` ; \ + mkdir -p $(CURDIR)/$@/lib/$(HOST_PLATFORM)/$${pkg%.conf} ; \ + cp -rfp $(CURDIR)/_build/$(@F)/build/host/*/ghc-*/$${pkg%.conf}/build/* $(CURDIR)/$@/lib/$(HOST_PLATFORM)/$${pkg%.conf} ; \ + if [ $${pkgname} = "libffi-clib" ] ; then \ + $(call patchpackageconf,$${pkgname},$${pkg},../../..,$(HOST_PLATFORM),$${pkgnamever}) ; \ + else \ + $(call patchpackageconf,$${pkgname},$${pkg},../../..,$(HOST_PLATFORM),$${pkgnamever}) ; \ + fi ; \ + done ; \ + $(call copy_headers,ffitarget.h,$(CURDIR)/$${ffi_incdir},libffi-clib,$(CURDIR)/$@/bin/ghc-pkg$(EXE_EXT)) + # Copy driver usage files + @cp -rfp driver/ghc-usage.txt $@/lib/ + @cp -rfp driver/ghci-usage.txt $@/lib/ + @echo "FIXME: Changing 'Support SMP' from YES to NO in settings file" + @$(SED) 's/("Support SMP","YES")/("Support SMP","NO")/' -i.bck $@/lib/settings + # Recache + $@/bin/ghc-pkg$(EXE_EXT) recache + # Copy headers + @$(call copy_all_stage2_h,$@/bin/ghc-pkg$(EXE_EXT)) + @echo "::endgroup::" + +_build/bindist/stage2/ghc.tar.gz: _build/bindist/stage2 + @tar czf $@ \ + --directory=_build/bindist/stage2 \ + $(foreach exe,$(BINDIST2_EXECTUABLES),bin/$(exe)) \ + lib/ghc-usage.txt \ + lib/ghci-usage.txt \ + lib/package.conf.d \ + lib/settings \ + lib/template-hsc.h \ + lib/$(HOST_PLATFORM) + +.PHONY: clean-stage2 +clean-stage2: + @echo "::group::Cleaning stage2 build artifacts..." + rm -rf _build/stage2 + @echo "::endgroup::" diff --git a/mk/stable-haskell/stage3.mk b/mk/stable-haskell/stage3.mk new file mode 100644 index 000000000000..3cb16de08f86 --- /dev/null +++ b/mk/stable-haskell/stage3.mk @@ -0,0 +1,248 @@ +ifndef MK_TOOLCHAIN +include mk/stable-haskell/toolchain.mk +endif + +ifndef MK_COPY_HEADERS +include mk/stable-haskell/headers.mk +endif + +ifndef MK_PKG_CONF +include mk/stable-haskell/pkg-conf.mk +endif + +# $1 = triplet +define copycrosslib + @cp -rfp _build/stage3/lib/targets/$1 _build/bindist/stage3/lib/targets/ + @ffi_incdir=`$(CURDIR)/_build/bindist/stage3/bin/$1-ghc-pkg$(EXE_EXT) field libffi-clib include-dirs | grep '/libffi-clib/src/' | sed 's|.*$(CURDIR)/||' || echo "none"` ; cd _build/bindist/stage3/lib/targets/$1/lib/package.conf.d ; \ + for pkg in *.conf ; do \ + pkgname=`echo $${pkg} | $(SED) 's/-[0-9.]*\(-[0-9a-zA-Z]*\)\?\.conf//'` ; \ + pkgnamever=`echo $${pkg} | $(SED) 's/\.conf//'` ; \ + mkdir -p $(CURDIR)/_build/bindist/stage3/lib/targets/$1/lib/$1/$${pkg%.conf} && \ + cp -rfp $(CURDIR)/_build/stage3/$1/build/host/*/ghc-*/$${pkg%.conf}/build/* $(CURDIR)/_build/bindist/stage3/lib/targets/$1/lib/$1/$${pkg%.conf}/ && \ + if [ $${pkgname} = "libffi-clib" ] ; then \ + $(call patchpackageconf,$${pkgname},$${pkg},../../..,$1,$${pkgnamever}) ; \ + else \ + $(call patchpackageconf,$${pkgname},$${pkg},../../..,$1,$${pkgnamever}) ; \ + fi ; \ + done ; \ + if [ $${ffi_incdir} != "none" ] ; then $(call copy_headers,ffitarget.h,$(CURDIR)/$${ffi_incdir},libffi-clib,$(CURDIR)/_build/bindist/stage3/bin/$1-ghc-pkg$(EXE_EXT)) ; fi +endef + +BINDIST3_EXECTUABLES := \ + ghc$(EXE_EXT) \ + ghc-iserv$(EXE_EXT) \ + ghc-pkg$(EXE_EXT) \ + hp2ps$(EXE_EXT) \ + hpc$(EXE_EXT) \ + hsc2hs$(EXE_EXT) \ + runghc$(EXE_EXT) \ + unlit$(EXE_EXT) \ + haddock$(EXE_EXT) + +STAGE3_LIBS := \ + rts:nonthreaded-nodebug \ + Cabal \ + Cabal-syntax \ + array \ + base \ + binary \ + bytestring \ + containers \ + deepseq \ + directory \ + exceptions \ + file-io \ + filepath \ + ghc-bignum \ + ghci \ + hpc \ + integer-gmp \ + mtl \ + os-string \ + parsec \ + pretty \ + process \ + stm \ + template-haskell \ + text \ + time \ + transformers \ + xhtml + + +# --- Stage 3 generic --- + +_build/stage2/lib/targets/% _build/stage3/lib/targets/%: + @mkdir -p _build/stage3/lib/targets/$(@F) + @rm -f _build/stage2/lib/targets/$(@F) + @mkdir -p _build/stage2/lib/targets/ + @ln -sf ../../../stage3/lib/targets/$(@F) _build/stage2/lib/targets/$(@F) + +_build/stage3/bin/%-ghc-pkg$(EXE_EXT): _build/stage2/bin/ghc-pkg$(EXE_EXT) + @mkdir -p $(@D) + @ln -sf ../../stage2/bin/ghc-pkg$(EXE_EXT) $@ + +_build/stage3/bin/%-ghc$(EXE_EXT): _build/stage2/bin/ghc$(EXE_EXT) + @mkdir -p $(@D) + @ln -sf ../../stage2/bin/ghc$(EXE_EXT) $@ + +_build/stage3/bin/%-hsc2hs$(EXE_EXT): _build/stage2/bin/hsc2hs$(EXE_EXT) + @mkdir -p $(@D) + @ln -sf ../../stage2/bin/hsc2hs$(EXE_EXT) $@ + +_build/stage3/lib/targets/%/lib/package.conf.d: _build/stage3/lib/targets/% + @mkdir -p $@ + +# ghc-toolchain borks unlit +_build/stage3/lib/targets/%/bin/unlit$(EXE_EXT): _build/stage2/bin/unlit$(EXE_EXT) + @mkdir -p $(@D) + cp -rfp $< $@ + +_build/stage3/lib/targets/%/lib/dyld.mjs: + @mkdir -p $(@D) + @cp -f utils/jsffi/dyld.mjs $@ + @chmod +x $@ + +_build/stage3/lib/targets/%/lib/post-link.mjs: + @mkdir -p $(@D) + @cp -f utils/jsffi/post-link.mjs $@ + @chmod +x $@ + +_build/stage3/lib/targets/%/lib/prelude.mjs: + @mkdir -p $(@D) + @cp -f utils/jsffi/prelude.mjs $@ + @chmod +x $@ + +_build/stage3/lib/targets/%/lib/ghc-interp.js: + @mkdir -p $(@D) + @cp -f ghc-interp.js $@ + +# $1 = TIPLET +define build_cross + GHC=$(GHC) HADRIAN_SETTINGS='$(call HADRIAN_SETTINGS)' \ + PATH=$(PWD)/_build/stage2/bin:$(PWD)/_build/stage3/bin:$(PATH) \ + $(CABAL_BUILD) -W $(GHC2) --happy-options="--template=$(abspath _build/stage2/src/happy-lib-2.1.5/data/)" --with-hsc2hs=$1-hsc2hs --hsc2hs-options='-x' --configure-option='--host=$1' \ + $(foreach lib,$(CROSS_EXTRA_LIB_DIRS),--extra-lib-dirs=$(lib)) \ + $(foreach include,$(CROSS_EXTRA_INCLUDE_DIRS),--extra-include-dirs=$(include)) \ + $(STAGE3_LIBS) +endef + +# --- Stage 3 javascript build --- + +.PHONY: stage3-javascript-unknown-ghcjs +stage3-javascript-unknown-ghcjs: _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/settings javascript-unknown-ghcjs-libs _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/package.conf.d/package.cache _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/dyld.mjs _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/post-link.mjs _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/prelude.mjs _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/ghc-interp.js + +_build/stage3/lib/targets/javascript-unknown-ghcjs/lib/settings: _build/stage2/lib/targets/javascript-unknown-ghcjs _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) + @mkdir -p $(@D) + _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) $(GHC_TOOLCHAIN_ARGS) --triple javascript-unknown-ghcjs --output-settings -o $@ --cc $(EMCC) --cxx $(EMCXX) --ar $(EMAR) --ranlib $(EMRANLIB) + +_build/stage3/lib/targets/javascript-unknown-ghcjs/lib/package.conf.d/package.cache: _build/stage3/bin/javascript-unknown-ghcjs-ghc-pkg$(EXE_EXT) _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/settings javascript-unknown-ghcjs-libs + @mkdir -p $(@D) + @rm -rf $(@D)/* + cp -rfp _build/stage3/javascript-unknown-ghcjs/packagedb/host/*/* $(@D) + _build/stage3/bin/javascript-unknown-ghcjs-ghc-pkg$(EXE_EXT) recache + +.PHONY: javascript-unknown-ghcjs-libs +javascript-unknown-ghcjs-libs: private GHC=$(abspath _build/stage3/bin/javascript-unknown-ghcjs-ghc$(EXE_EXT)) +javascript-unknown-ghcjs-libs: private GHC2=$(abspath _build/stage2/bin/ghc$(EXE_EXT)) +javascript-unknown-ghcjs-libs: private STAGE=stage3 +javascript-unknown-ghcjs-libs: private CC=emcc +javascript-unknown-ghcjs-libs: private CROSS_EXTRA_LIB_DIRS=$(JS_EXTRA_LIB_DIRS) +javascript-unknown-ghcjs-libs: private CROSS_EXTRA_INCLUDE_DIRS=$(JS_EXTRA_INCLUDE_DIRS) +javascript-unknown-ghcjs-libs: cabal.project.stage3 _build/stage3/bin/javascript-unknown-ghcjs-ghc-pkg$(EXE_EXT) _build/stage3/bin/javascript-unknown-ghcjs-ghc$(EXE_EXT) _build/stage3/bin/javascript-unknown-ghcjs-hsc2hs$(EXE_EXT) _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/settings _build/stage3/lib/targets/javascript-unknown-ghcjs/bin/unlit$(EXE_EXT) _build/stage3/lib/targets/javascript-unknown-ghcjs/lib/package.conf.d + $(call build_cross,javascript-unknown-ghcjs) + +# --- Stage 3 musl build --- + +.PHONY: stage3-x86_64-musl-linux +stage3-x86_64-musl-linux: x86_64-musl-linux-libs _build/stage3/lib/targets/x86_64-musl-linux/lib/package.conf.d/package.cache + +_build/stage3/lib/targets/x86_64-musl-linux/lib/settings: _build/stage2/lib/targets/x86_64-musl-linux _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) + @mkdir -p $(@D) + _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) $(GHC_TOOLCHAIN_ARGS) --triple x86_64-musl-linux --output-settings -o $@ --cc x86_64-unknown-linux-musl-cc --cxx x86_64-unknown-linux-musl-c++ --ar x86_64-unknown-linux-musl-ar --ranlib x86_64-unknown-linux-musl-ranlib --ld x86_64-unknown-linux-musl-ld + +_build/stage3/lib/targets/x86_64-musl-linux/lib/package.conf.d/package.cache: _build/stage3/bin/x86_64-musl-linux-ghc-pkg$(EXE_EXT) _build/stage3/lib/targets/x86_64-musl-linux/lib/settings x86_64-musl-linux-libs + @mkdir -p $(@D) + @rm -rf $(@D)/* + cp -rfp _build/stage3/x86_64-musl-linux/packagedb/host/*/* $(@D) + _build/stage3/bin/x86_64-musl-linux-ghc-pkg$(EXE_EXT) recache + +.PHONY: x86_64-musl-linux-libs +x86_64-musl-linux-libs: private GHC=$(abspath _build/stage3/bin/x86_64-musl-linux-ghc$(EXE_EXT)) +x86_64-musl-linux-libs: private GHC2=$(abspath _build/stage2/bin/ghc$(EXE_EXT)) +x86_64-musl-linux-libs: private STAGE=stage3 +x86_64-musl-linux-libs: private CC=x86_64-unknown-linux-musl-cc +x86_64-musl-linux-libs: private CROSS_EXTRA_LIB_DIRS=$(MUSL_EXTRA_LIB_DIRS) +x86_64-musl-linux-libs: private CROSS_EXTRA_INCLUDE_DIRS=$(MUSL_EXTRA_INCLUDE_DIRS) +x86_64-musl-linux-libs: _build/stage3/bin/x86_64-musl-linux-ghc-pkg$(EXE_EXT) _build/stage3/bin/x86_64-musl-linux-ghc$(EXE_EXT) _build/stage3/bin/x86_64-musl-linux-hsc2hs$(EXE_EXT) _build/stage3/lib/targets/x86_64-musl-linux/lib/settings _build/stage3/lib/targets/x86_64-musl-linux/bin/unlit$(EXE_EXT) _build/stage3/lib/targets/x86_64-musl-linux/lib/package.conf.d + $(call build_cross,x86_64-musl-linux) + +# --- Stage 3 wasm build --- + +.PHONY: stage3-wasm32-unknown-wasi +stage3-wasm32-unknown-wasi: wasm32-unknown-wasi-libs _build/stage3/lib/targets/wasm32-unknown-wasi/lib/package.conf.d/package.cache _build/stage3/lib/targets/wasm32-unknown-wasi/lib/dyld.mjs _build/stage3/lib/targets/wasm32-unknown-wasi/lib/post-link.mjs _build/stage3/lib/targets/wasm32-unknown-wasi/lib/prelude.mjs _build/stage3/lib/targets/wasm32-unknown-wasi/lib/ghc-interp.js + +_build/stage3/lib/targets/wasm32-unknown-wasi/lib/settings: _build/stage2/lib/targets/wasm32-unknown-wasi _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) + @mkdir -p $(@D) + PATH=/home/hasufell/.ghc-wasm/wasi-sdk/bin:$(PATH) _build/stage1/bin/ghc-toolchain-bin$(EXE_EXT) $(GHC_TOOLCHAIN_ARGS) --triple wasm32-unknown-wasi --output-settings -o $@ --cc wasm32-wasi-clang --cxx wasm32-wasi-clang++ --ar ar --ranlib ranlib --ld wasm-ld --merge-objs wasm-ld --merge-objs-opt="-r" --disable-ld-override --disable-tables-next-to-code $(foreach opt,$(WASM_CC_OPTS),--cc-opt=$(opt)) $(foreach opt,$(WASM_CXX_OPTS),--cxx-opt=$(opt)) + +_build/stage3/lib/targets/wasm32-unknown-wasi/lib/package.conf.d/package.cache: _build/stage3/bin/wasm32-unknown-wasi-ghc-pkg$(EXE_EXT) _build/stage3/lib/targets/wasm32-unknown-wasi/lib/settings wasm32-unknown-wasi-libs + @mkdir -p $(@D) + @rm -rf $(@D)/* + cp -rfp _build/stage3/wasm32-unknown-wasi/packagedb/host/*/* $(@D) + _build/stage3/bin/wasm32-unknown-wasi-ghc-pkg$(EXE_EXT) recache + +.PHONY: wasm32-unknown-wasi-libs +wasm32-unknown-wasi-libs: private GHC=$(abspath _build/stage3/bin/wasm32-unknown-wasi-ghc$(EXE_EXT)) +wasm32-unknown-wasi-libs: private GHC2=$(abspath _build/stage2/bin/ghc$(EXE_EXT)) +wasm32-unknown-wasi-libs: private STAGE=stage3 +wasm32-unknown-wasi-libs: private CC=wasm32-wasi-clang +wasm32-unknown-wasi-libs: private CROSS_EXTRA_LIB_DIRS=$(WASM_EXTRA_LIB_DIRS) +wasm32-unknown-wasi-libs: private CROSS_EXTRA_INCLUDE_DIRS=$(WASM_EXTRA_INCLUDE_DIRS) +wasm32-unknown-wasi-libs: cabal.project.stage3 _build/stage3/bin/wasm32-unknown-wasi-ghc-pkg$(EXE_EXT) _build/stage3/bin/wasm32-unknown-wasi-ghc$(EXE_EXT) _build/stage3/bin/wasm32-unknown-wasi-hsc2hs$(EXE_EXT) _build/stage3/lib/targets/wasm32-unknown-wasi/lib/settings _build/stage3/lib/targets/wasm32-unknown-wasi/bin/unlit$(EXE_EXT) _build/stage3/lib/targets/wasm32-unknown-wasi/lib/package.conf.d + $(call build_cross,wasm32-unknown-wasi) + + +_build/bindist/stage3/lib/targets/%: _build/bindist/stage2 driver/ghc-usage.txt driver/ghci-usage.txt stage3-% + @echo "::group::Creating binary distribution in $@" + @mkdir -p _build/bindist/stage2/bin + @mkdir -p _build/bindist/stage3/bin + @mkdir -p _build/bindist/stage3/lib/targets + # Symlinks + @cd _build/bindist/stage2/bin ; for binary in * ; do \ + test -L $$binary || { cp -rfp $$binary $(CURDIR)/_build/bindist/stage3/bin/$$binary && ln -sf $$binary $(CURDIR)/_build/bindist/stage3/bin/$(@F)-$$binary ; } \ + ; done + # Copy libraries and settings + @if [ -e $(CURDIR)/_build/bindist/stage2/lib/targets/$(@F)/lib/$(@F) ] ; then find $(CURDIR)/_build/bindist/stage3/lib/targets/$(@F)/lib/$(@F)/ -mindepth 1 -type f -name "*.so" -execdir mv '{}' $(CURDIR)/_build/bindist/stage3/lib/targets/$(@F)/lib/$(@F)/'{}' \; ; fi + $(call copycrosslib,$(@F)) + # --help + @cp -rfp driver/ghc-usage.txt _build/bindist/stage3/lib/targets/$(@F)/lib/ + @cp -rfp driver/ghci-usage.txt _build/bindist/stage3/lib/targets/$(@F)/lib/ + # Recache + @_build/bindist/stage3/bin/$(@F)-ghc-pkg$(EXE_EXT) recache + # Copy headers + @$(call copy_all_stage3_h,_build/bindist/stage3/bin/$(@F)-ghc-pkg$(EXE_EXT),$(@F)) + # remove temporary binaries (the tarball should just contain symlinks to binaries... + # the binaries are provided by stage2) + @cd _build/bindist/stage2/bin ; for binary in * ; do \ + test -L $$binary || rm $(CURDIR)/_build/bindist/stage3/bin/$$binary \ + ; done + @echo "::endgroup::" + +_build/bindist/stage3/ghc-%.tar.gz: _build/bindist/stage3/lib/targets/% _build/bindist/stage2/ghc.tar.gz + @triple=`basename $<` ; \ + tar czf $@ \ + --directory=_build/bindist/stage3 \ + $(foreach exe,$(BINDIST3_EXECTUABLES),bin/$${triple}-$(exe)) \ + lib/targets/$${triple} + +_build/bindist/tests.tar.gz: + @tar czf $@ \ + testsuite + +.PHONY: clean-stage3 +clean-stage3: + @echo "::group::Cleaning stage3 build artifacts..." + rm -rf _build/stage3 + rm -rf _build/stage2/lib/targets + @echo "::endgroup::" diff --git a/mk/stable-haskell/test.mk b/mk/stable-haskell/test.mk new file mode 100644 index 000000000000..17349bc1e3f0 --- /dev/null +++ b/mk/stable-haskell/test.mk @@ -0,0 +1,48 @@ +# Default: skip performance tests (can override with SKIP_PERF_TESTS=NO) +SKIP_PERF_TESTS ?= YES +export SKIP_PERF_TESTS + +# --- Test Suite Helper Tool Paths & Flags (Hadrian parity light) --- +# We approximate Hadrian's test invocation without depending on Hadrian. +# Bindist places test tools in _build/bindist/bin (created by the bindist target). +TEST_TOOLS_DIR := _build/bindist/stage2/bin +TEST_GHC := $(abspath $(TEST_TOOLS_DIR)/ghc$(EXE_EXT)) +TEST_GHC_PKG := $(abspath $(TEST_TOOLS_DIR)/ghc-pkg$(EXE_EXT)) +TEST_HP2PS := $(abspath $(TEST_TOOLS_DIR)/hp2ps$(EXE_EXT)) +TEST_HPC := $(abspath $(TEST_TOOLS_DIR)/hpc$(EXE_EXT)) +TEST_RUN_GHC := $(abspath $(TEST_TOOLS_DIR)/runghc$(EXE_EXT)) + +# Canonical GHC flags used by the testsuite (mirrors testsuite/mk/test.mk & Hadrian runTestGhcFlags) +CANONICAL_TEST_HC_OPTS = \ + -dcore-lint -dstg-lint -dcmm-lint -no-user-package-db -fno-dump-with-ways \ + -fprint-error-index-links=never -rtsopts -fno-warn-missed-specialisations \ + -fshow-warning-groups -fdiagnostics-color=never -fno-diagnostics-show-caret \ + -Werror=compat -dno-debug-output + +# Build timeout utility (needed for some tests) if not already built. +.PHONY: testsuite-timeout +testsuite-timeout: + $(MAKE) -C testsuite/timeout + +# --- Test Target --- + +test: _build/bindist/stage2 testsuite-timeout + @echo "::group::Running tests with THREADS=$(THREADS)" >&2 + # If any required tool is missing, testsuite logic will skip related tests. + TEST_HC='$(TEST_GHC)' \ + GHC_PKG='$(TEST_GHC_PKG)' \ + HP2PS_ABS='$(TEST_HP2PS)' \ + HPC='$(TEST_HPC)' \ + RUNGHC='$(TEST_RUN_GHC)' \ + TEST_CC='$(CC)' \ + TEST_CXX='$(CXX)' \ + TEST_HC_OPTS='$(CANONICAL_TEST_HC_OPTS)' \ + METRICS_FILE='$(CURDIR)/_build/test-perf.csv' \ + SUMMARY_FILE='$(CURDIR)/_build/test-summary.txt' \ + JUNIT_FILE='$(CURDIR)/_build/test-junit.xml' \ + SKIP_PERF_TESTS='$(SKIP_PERF_TESTS)' \ + THREADS='$(THREADS)' \ + $(MAKE) -C testsuite/tests test + @echo "::endgroup::" + +.PHONY: test diff --git a/mk/stable-haskell/toolchain.mk b/mk/stable-haskell/toolchain.mk new file mode 100644 index 000000000000..e3e4ceecb28c --- /dev/null +++ b/mk/stable-haskell/toolchain.mk @@ -0,0 +1,132 @@ +MK_TOOLCHAIN := 1 + +SHELL := bash +.SHELLFLAGS := -eu -o pipefail -c + +VERBOSE ?= 0 + +# Enable dynamic runtime/linking support when DYNAMIC=1 is passed on the make +# command line. This will build shared libraries, a dynamic RTS (defining +# -DDYNAMIC) and allow tests requiring dynamic linking (e.g. plugins-external) +# to run. The default remains static to keep rebuild cost low. +DYNAMIC ?= 0 + +# If using autoconf feature toggles you can instead run: +# ./configure --enable-dynamic --enable-profiling --enable-debug +# which generates cabal.project.stage2.settings (imported by cabal.project.stage2). +# The legacy DYNAMIC=1 path still appends flags directly; if both are used the +# configure-generated settings file (import) and these args should agree. + +GHC0 ?= ghc-9.8.4 +PYTHON ?= python3 +CABAL ?= cabal +SED ?= sed + +ifeq ($(OS),Windows_NT) +CC := x86_64-w64-mingw32-clang.exe +CXX := x86_64-w64-mingw32-clang++.exe +CC_LINK_OPT := -Wl,CRT_fp8.o +LD := ld.lld.exe +CYGPATH = cygpath --unix -f - +CYGPATH_MIXED = cygpath --mixed -f - +# Windows executables require .exe extension for native programs to find them +EXE_EXT := .exe +else +CYGPATH_MIXED = cat +CYGPATH = cat +CC_LINK_OPT ?= +LD ?= ld +EXE_EXT := +endif + +EMCC ?= emcc +EMCXX ?= em++ +EMAR ?= emar +EMRANLIB ?= emranlib + +GHC_CONFIGURE_ARGS ?= + +EXTRA_LIB_DIRS ?= +EXTRA_INCLUDE_DIRS ?= + +MUSL_EXTRA_LIB_DIRS ?= +MUSL_EXTRA_INCLUDE_DIRS ?= + +JS_EXTRA_LIB_DIRS ?= +JS_EXTRA_INCLUDE_DIRS ?= + +WASM_EXTRA_LIB_DIRS ?= +WASM_EXTRA_INCLUDE_DIRS ?= +WASM_CC_OPTS = -fno-strict-aliasing -Wno-error=int-conversion -Oz -msimd128 -mnontrapping-fptoint -msign-ext -mbulk-memory -mmutable-globals -mmultivalue -mreference-types +WASM_CXX_OPTS = -fno-exceptions -fno-strict-aliasing -Wno-error=int-conversion -Oz -msimd128 -mnontrapping-fptoint -msign-ext -mbulk-memory -mmutable-globals -mmultivalue -mreference-types + +# :exploding-head: It turns out override doesn't override the command-line +# value but it overrides Make's normal behavior of ignoring assignments to +# command-line variables. This allows the += operations to append to whatever +# was passed from the command line. + +override CABAL_ARGS += \ + --remote-repo-cache _build/packages \ + --store-dir=_build/$(STAGE)/$(TARGET_PLATFORM)/store \ + --logs-dir=_build/$(STAGE)/logs + +override CABAL_BUILD_ARGS += \ + -j -w $(GHC) --with-gcc=$(CC) --with-ld=$(LD) \ + --project-file=cabal.project.$(STAGE) \ + $(foreach lib,$(EXTRA_LIB_DIRS),--extra-lib-dirs=$(lib)) \ + $(foreach include,$(EXTRA_INCLUDE_DIRS),--extra-include-dirs=$(include)) \ + --builddir=_build/$(STAGE)/$(TARGET_PLATFORM) \ + --ghc-options="-fhide-source-paths" + +ifeq ($(DYNAMIC),1) +GHC_CONFIGURE_ARGS += --enable-dynamic +endif + +GHC_TOOLCHAIN_ARGS ?= --disable-ld-override + +# just some defaults +STAGE ?= stage1 +GHC ?= $(GHC0) + +CABAL_BUILD = $(CABAL) $(CABAL_ARGS) build $(CABAL_BUILD_ARGS) + +GHC_BIN1 ?= _build/stage1/bin +GHC1 = $(GHC_BIN1)/ghc$(EXE_EXT) +GHC_PKG1 = $(GHC_BIN1)/ghc$(EXE_EXT) +GHC_TOOLCHAIN1 = $(GHC_BIN1)/ghc-toolchain-bin$(EXE_EXT) + +GHC_BIN2 ?= _build/stage2/bin +GHC2 = $(GHC_BIN2)/ghc$(EXE_EXT) +GHC_PKG2 = $(GHC_BIN2)/ghc-pkg$(EXE_EXT) +GHC_HSC2HS2 = $(GHC_BIN2)/hsc2hs$(EXE_EXT) +GHC_UNLIT2 = $(GHC_BIN2)/unlit$(EXE_EXT) + +define GHC_INFO +$(shell sh -c "$(GHC) --info | $(GHC0) -e 'getContents >>= foldMap putStrLn . lookup \"$1\" . read'") +endef + +HOST_PLATFORM = $(call GHC_INFO,Host platform) +TARGET_PLATFORM = $(call GHC_INFO,target platform string) +TARGET_ARCH = $(call GHC_INFO,target arch) +TARGET_OS = $(call GHC_INFO,target os) +TARGET_TRIPLE = $(call GHC_INFO,Target platform) +GHC_LIBDIR = $(call GHC_INFO,LibDir) +GIT_COMMIT_ID := $(shell git rev-parse HEAD) + +define HADRIAN_SETTINGS +[ ("hostPlatformArch", "$(TARGET_ARCH)") \ +, ("hostPlatformOS", "$(TARGET_OS)") \ +, ("cProjectGitCommitId", "$(GIT_COMMIT_ID)") \ +, ("cProjectVersion", "9.14") \ +, ("cProjectVersionInt", "914") \ +, ("cProjectPatchLevel", "0") \ +, ("cProjectPatchLevel1", "0") \ +, ("cProjectPatchLevel2", "0") \ +] +endef + +# Handle CPUS and THREADS +CPUS_DETECT_SCRIPT := ./mk/detect-cpu-count.sh +CPUS := $(shell if [ -x $(CPUS_DETECT_SCRIPT) ]; then $(CPUS_DETECT_SCRIPT); else echo 2; fi) +THREADS ?= $(shell echo $$(( $(CPUS) + 1 ))) +