Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ghc/ci-images
  • phadej/ci-images
  • cgohla/ci-images
  • samuela/ci-images
  • arrowd/ci-images
  • trommler/ci-images
  • bjaress/ci-images
  • WJWH/ci-images
  • Kleidukos/ci-images
  • maerwald/ci-images
  • adamse/ci-images
  • supersven/ci-images
  • blackgnezdo/ci-images
  • doyougnu/ci-images
  • fp/ci-images
  • lrzlin/ci-images
  • Bodigrim/ci-images
17 results
Show changes
Commits on Source (127)
Showing with 1097 additions and 244 deletions
dockerfiles
.vscode
variables:
# Always start with a fresh clone to avoid non-hermetic builds
GIT_STRATEGY: clone
stages:
- prepare
- build
......
--| A description of a Docker image
--| A description of a Docker image
let
CF = ./deps/Containerfile.dhall
......@@ -7,10 +7,22 @@ let
--| The name a of a Docker image
ImageName = Text
-- Note [Specifying custom platform]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- For reasons that aren't entirely clear, Kaniko at some point started refusing
-- to use base images that don't match the builder's platform. This affects ARMv7
-- and i386 images as they are built on AArch64 and x86-64 machiners, respectively.
-- To work around this we pass the `--custom-platform` flag to kaniko, forcing it
-- to accept the upstream base images, despite the platform mis-match.
--
-- See https://github.com/GoogleContainerTools/kaniko/issues/1995
let
type: Type =
{ name: ImageName
, runnerTags: List Text
-- See Note [Specifying custom platform]
, customPlatform: Optional Text
, jobStage: Text
, needs: List ImageName
, image: CF.Type
......@@ -18,8 +30,9 @@ let
in
{ Type = type
, default =
{ needs = [] : List ImageName
{ customPlatform = None Text
, needs = [] : List ImageName
, jobStage = "build"
}
, ImageName = ImageName
}
\ No newline at end of file
}
DHALL ?= dhall
all : gitlab-pipeline.yaml dockerfiles
gitlab-pipeline.yaml: gitlab-pipeline.dhall
${DHALL} text --file=$< > $@
dockerfiles: dockerfiles.dhall
mkdir -p dockerfiles
${DHALL} to-directory-tree --file=$< --output=$@
clean:
rm gitlab-pipeline.yaml || echo "Skipping"
rm -r dockerfiles || echo "Skipping"
let bootGhcVersion : Text = "9.10.1"
in bootGhcVersion
#!/usr/bin/env bash
set -e
commit="$(git rev-parse HEAD)"
images="$@"
dhall to-directory-tree --output dockerfiles < dockerfiles.dhall
cd dockerfiles
if [ -z "$images" ]; then
images="$(ls)"
fi
for d in $images; do
tag="registry.gitlab.haskell.org/ghc/ci-images/$(basename $d):$commit"
docker build -t "$tag" "$d"
docker push "$tag"
done
......@@ -13,8 +13,11 @@ let
path: Text = "/usr/local/bin/cabal"
in
CF.run "install cabal"
[ "curl -L ${bindistUrl} | tar -Jx"
, "mv cabal ${path}"
[ "curl -L -O ${bindistUrl}"
, "mkdir -p cabal-unpack"
, "tar xf cabal-*.tar.* -C cabal-unpack/"
, "mv cabal-unpack/cabal ${path}"
, "rm -rf cabal-unpack"
, "${path} --version"
]
# setEnv path
......@@ -23,13 +26,16 @@ let
installFromSource: Text -> CF.Type =
\(version: Text) ->
let
path: Text = "/usr/local/bin/cabal"
path: Text = "/usr/local/bin"
let
storeDir: Text = "/opt/cabal/store"
in
CF.run "install cabal"
[ "cabal update"
, "cabal install cabal-install==${version}"
, "mv $HOME/.cabal/bin/cabal ${path}"
, "mkdir -p ${storeDir}"
, "cabal install --store-dir=${storeDir}/store --enable-static --install-method=copy --installdir=${path} cabal-install==${version}"
, "${path} --version"
, "rm -rf ${storeDir}"
]
# setEnv path
......@@ -57,4 +63,4 @@ in
{ Type = type
, install = install
, fromUpstreamBindist = fromUpstreamBindist
}
\ No newline at end of file
}
let
CF = ../deps/Containerfile.dhall
let
Llvm = ./Llvm.dhall
let
BinariesSpec: Type =
{ version : Text
}
let
installArm64ECToWine: Text -> BinariesSpec -> CF.Type =
\(wineDest: Text) -> \(binSpec: BinariesSpec) ->
let
package: Text = "fex-emu-wine_${binSpec.version}_arm64.deb"
let
url: Text = "https://gitlab.haskell.org/api/v4/projects/3815/packages/generic/fex-emu-wine/${binSpec.version}_arm64/fex-emu-wine_${binSpec.version}_arm64.deb"
in
CF.run "install FEX"
[ "mkdir /tmp/fex"
, "pushd /tmp/fex"
, "wget ${url}"
, "ar xv ./${package}"
, "tar --zstd -xvf ./data.tar.zst"
, "cp ./usr/lib/wine/aarch64-windows/* ${wineDest}/lib/wine/aarch64-windows/"
, "popd"
, "rm -Rf /tmp/fex"
]
in
{ BinariesSpec = BinariesSpec
, install = installArm64ECToWine
}
......@@ -9,14 +9,16 @@ let
, triple : Text
}
let Bindist = < BindistSpec : BindistSpec | BindistURL : Text >
let
Options =
{ Type =
{ bindist : BindistSpec
{ Type =
{ bindist : Bindist
, destDir : Text
, configureOpts : List Text
}
, default =
, default =
{ configureOpts = [] : List Text
}
}
......@@ -25,21 +27,20 @@ let
install: Options.Type -> CF.Type =
\(opts: Options.Type) ->
let
version = opts.bindist.version
let
bindistUrl: Text = "https://downloads.haskell.org/~ghc/${version}/ghc-${version}-${opts.bindist.triple}.tar.xz"
bindistUrl: Text = merge { BindistSpec = \(bindistSpec : BindistSpec) -> "https://downloads.haskell.org/~ghc/${bindistSpec.version}/ghc-${bindistSpec.version}-${bindistSpec.triple}.tar.xz", BindistURL = \(bindistURL : Text) -> bindistURL } opts.bindist
in
CF.run "fetch GHC" [ "curl -L ${bindistUrl} | tar -Jx -C /tmp" ]
# CF.run "configure bindist"
[ "cd /tmp/ghc-${version}*"
CF.run "install GHC bindist"
[ "curl -L ${bindistUrl} | tar -Jx -C /tmp"
, "cd /tmp/ghc-*"
, "./configure ${Prelude.Text.concatSep " " opts.configureOpts} --prefix=${opts.destDir}"
, "make install"
, "rm -Rf /tmp/ghc-*"
, "${opts.destDir}/bin/ghc --version"
]
# CF.run "remove temporary directory" [ "rm -Rf /tmp/ghc-${version}-*" ]
# CF.run "test GHC" [ "${opts.destDir}/bin/ghc --version" ]
in
{ Options = Options
, BindistSpec = BindistSpec
, Bindist = Bindist
, install = install
}
\ No newline at end of file
}
let
Prelude = ../deps/Prelude.dhall
let
CF = ../deps/Containerfile.dhall
......@@ -5,36 +7,47 @@ let
outDir: Text = "/opt/toolchain"
let
binDir: Text = "${outDir}/bin"
let
hackageIndexState: Text = "2023-09-18T18:43:12Z"
let
cabalInstall: List Text -> CF.Type = \(args : List Text) ->
CF.run "build haskell tools"
[ "mkdir -p ${outDir}/store"
, "$CABAL user-config update"
-- We must override store-dir lest data files end up in
-- /root/.cabal, which isn't accessible to the build user
, ''
$CABAL \
--store-dir=${outDir}/store \
v2-install \
--constraint='alex ^>= 3.2.7.3' \
--constraint='happy ^>= 1.20' \
--with-compiler=$GHC \
--install-method=copy \
--installdir=${binDir} \
--index-state=${hackageIndexState} \
'' ++ Prelude.Text.concatSep " " args
]
let
build: CF.Type =
CF.run "build haskell tools"
[ "mkdir -p ${outDir}/store"
, "$CABAL user-config update"
, "$CABAL v2-update"
-- We must override store-dir lest data files end up in
-- /root/.cabal, which isn't accessible to the build user
, ''
$CABAL \
--store-dir=${outDir}/store \
v2-install \
--constraint='alex ^>= 3.2.6' \
--constraint='happy ^>= 1.20' \
--with-compiler=$GHC \
--enable-static \
--install-method=copy \
--installdir=${binDir} \
hscolour happy alex hlint-3.2
''
]
installGhcBuildDeps: CF.Type =
cabalInstall [ "hscolour", "happy", "alex" ]
# CF.env (toMap
{ HAPPY = "${binDir}/happy"
, ALEX = "${binDir}/alex"
, HSCOLOUR = "${binDir}/HsColour"
, HLINT = "${binDir}/hlint"
})
let
installHLint: CF.Type =
cabalInstall [ "hlint-3.5" ]
# CF.env (toMap
{ HLINT = "${binDir}/hlint"
})
in
{
build = build
installGhcBuildDeps = installGhcBuildDeps,
installHLint = installHLint
}
......@@ -8,66 +8,74 @@ let
{ version : Text
, triple : Text
}
let Source: Type =
< FromBindist : BindistSpec
| FromDistro : List Text
-- Commands to run to install
>
let
Options =
{ Type =
{ source : Source
, destDir : Text
}
Output =
{ Type = { action : CF.Type
, out_llc : Text
, out_opt : Text
, out_clang : Text
, out_clang_cpp : Text
}
, default = {}
}
let Config = Output.Type
let
installFromBindistTo: Text -> BindistSpec -> CF.Type =
installFromBindistTo: Text -> BindistSpec -> Output.Type =
\(destDir: Text) -> \(bindist: BindistSpec) ->
let
url: Text = "https://github.com/llvm/llvm-project/releases/download/llvmorg-${bindist.version}/clang+llvm-${bindist.version}-${bindist.triple}.tar.xz"
in
CF.run "install LLVM"
[ "curl -L ${url} | tar -xJC ."
, "mkdir ${destDir}"
, "cp -R clang+llvm*/* ${destDir}"
, "rm -R clang+llvm*"
, "${destDir}/bin/llc --version"
]
{ action = CF.run "install LLVM"
[ "curl -L ${url} | tar -xJC ."
, "mkdir ${destDir}"
, "cp -R clang+llvm*/* ${destDir}"
, "rm -R clang+llvm*"
, "${destDir}/bin/llc --version"
]
, out_llc = "${destDir}/bin/llc"
, out_opt = "${destDir}/bin/opt"
, out_clang="${destDir}/bin/clang"
, out_clang_cpp="${destDir}/bin/clang++" }
let
install: Options.Type -> CF.Type =
\(opts: Options.Type) ->
merge
{ FromBindist = installFromBindistTo opts.destDir
, FromDistro = \(cmds: List Text) -> CF.run "install LLVM" cmds
} opts.source
llvmInstall: Optional Output.Type -> CF.Type =
\(output : Optional Output.Type) ->
merge { Some = \(llvm_out : Output.Type) -> llvm_out.action
, None = [] : CF.Type
} output
let
maybeInstallTo: Text -> Optional Source -> CF.Type =
\(destDir: Text) -> \(source: Optional Source) ->
merge
{ Some = \(src: Source) -> install { source = src, destDir = destDir }
, None = [] : CF.Type
} source
let
setEnv: Text -> CF.Type =
\(destDir: Text) ->
llvmSetEnv: Output.Type -> CF.Type =
\(output : Output.Type) ->
CF.env (toMap
{ LLC = "${destDir}/bin/llc"
, OPT = "${destDir}/bin/opt"
{ LLC = output.out_llc
, OPT = output.out_opt
, LLVMAS = output.out_clang
})
let setEnv =
\(output : Optional Output.Type) ->
merge { Some = \(llvm_out : Output.Type) -> llvmSetEnv llvm_out
, None = [] : CF.Type
} output
let
-- llvmConfigureArgs : Optional Output.Type -> List Text
llvmConfigureArgs = \(output: Optional Output.Type) ->
merge { Some = \(out: Output.Type) -> [ "LLC=${out.out_llc}"
, "OPT=${out.out_opt}"
, "LLVMAS=${out.out_clang}" ]
, None = [] : List Text
} output
in
{ Options = Options
, Source = Source
{ Config = Config
, BindistSpec = BindistSpec
, install = install
, maybeInstallTo = maybeInstallTo
, installFromBindistTo = installFromBindistTo
, setEnv = setEnv
, install = llvmInstall
, configureArgs = llvmConfigureArgs
}
let
CF = ../deps/Containerfile.dhall
let
Archive: Type = <TAR_XZ | ZIP>
let
BindistSpec: Type =
{ -- there are two sources of such toolchain:
-- https://github.com/mstorsjo/llvm-mingw (it has msvcrt but no arm64ec)
-- https://github.com/bylaws/llvm-mingw (it has arm64ec but no msvcrt)
-- for all our purposes we need ucrt (not msvscrt) and arm64ec, so, `bylaws` is more suitable
source : Text
, version : Text
, crt : Text
, os : Text
, archive : Archive
}
let
installFromBindistTo: Text -> BindistSpec -> CF.Type =
\(destDir: Text) -> \(bindist: BindistSpec) ->
let
url: Text = "https://github.com/${bindist.source}/llvm-mingw/releases/download/${bindist.version}/llvm-mingw-${bindist.version}-${bindist.crt}-${bindist.os}."
++ merge { TAR_XZ = "tar.xz", ZIP = "zip" } bindist.archive
let
unpack : List Text = merge
{ TAR_XZ = [ "curl -L ${url} | tar -xJC ."
]
, ZIP = [ "wget -q -O llvm-mingw-tmp.zip '${url}'"
, "unzip llvm-mingw-tmp.zip -d ."
, "rm llvm-mingw-tmp.zip"
]
} bindist.archive
in
CF.run "install LLVM MinGW for ${bindist.os}"
(unpack # [ "mkdir ${destDir}"
, "cp -R llvm-mingw-*/* ${destDir}"
, "rm -R llvm-mingw-*"
])
in
{ BindistSpec = BindistSpec
, Archive = Archive
, installFromBindistTo = installFromBindistTo
}
let
Prelude = ../deps/Prelude.dhall
let
CF = ../deps/Containerfile.dhall
let
BindistSpec: Type =
{ version_year : Text
, version_month : Text
, version_day : Text
, wine_version : Text
, build_date : Text
, build_time : Text
}
let
installFromBindistTo: Text -> BindistSpec -> Text -> CF.Type =
\(userHome: Text) -> \(bindist: BindistSpec) -> \(winePrefix: Text) ->
let
url: Text = "https://gitlab.haskell.org/api/v4/projects/3815/packages/generic/wine-msys2-env/${bindist.wine_version}-${bindist.version_year}_${bindist.version_month}_${bindist.version_day}-${bindist.build_date}_${bindist.build_time}/wine-msys2-env-deb12.tar.xz"
let
drive_c: Text = "${userHome}/.wine/drive_c"
let
runMSYS: Text = "${winePrefix}/bin/wine c:/msys64/usr/bin/bash.exe -l -c" -- option `-l` is strictly important
in
CF.env (toMap { MSYSTEM = "CLANGARM64" })
# CF.run "download & install MSYS2"
[ "curl -L ${url} | tar -Jx -C ${drive_c}"
-- Test MSYS2 works
, "${runMSYS} ' '"
]
in
{ BindistSpec = BindistSpec
, install = installFromBindistTo
}
let
CF = ../deps/Containerfile.dhall
let
BindistSpec: Type =
{ version : Text
}
let
installForArm64EC: BindistSpec -> CF.Type =
\(spec: BindistSpec) ->
let
url: Text = "https://gitlab.haskell.org/api/v4/projects/3815/packages/generic/wine-arm64ec-msys2/${spec.version}/wine-arm64ec-msys2-deb12.tar.xz"
in
CF.run "install Wine"
[ "curl -L ${url} | tar -xJC /"
]
in
{ BindistSpec = BindistSpec
, installForArm64EC = installForArm64EC
, installedPath = "/opt/wine-arm64ec-msys2-deb12"
}
https://raw.githubusercontent.com/bgamari/dhall-gitlab-ci/d990e6abb3af94aaf5eb6c7d10bcc26090c6e21f/package.dhall
https://raw.githubusercontent.com/bgamari/dhall-gitlab-ci/eaa32660c024b3205dc3a32da3d1990243d61870/package.dhall
......@@ -21,11 +21,20 @@ let
let
toJob: Image.Type -> Prelude.Map.Entry Text GitLab.Job.Type =
\(image: Image.Type) ->
let
let
docker_base_url: Text = "registry.gitlab.haskell.org/$CI_PROJECT_PATH"
let
imageName: Text = "${docker_base_url}/${image.name}"
let
customPlatform: Text =
Prelude.Optional.fold
Text
image.customPlatform
Text
(\(plat: Text) -> "--custom-platform ${plat}")
""
-- N.B. https://docs.gitlab.com/ee/ci/docker/using_kaniko.html
let job: GitLab.Job.Type =
GitLab.Job::
......@@ -34,12 +43,15 @@ let
, entrypoint = Some [""]
})
, stage = Some image.jobStage
, tags = Some image.runnerTags
, tags = Some (image.runnerTags # ["docker"])
, variables = toMap
{ DOCKER_DRIVER = "overlay2"
, DOCKER_TLS_CERTDIR = "/certs"
-- See https://gitlab.haskell.org/ghc/ci-images/-/issues/3
, container = "docker"
-- HTTP2 is extremely slow, so it is disabled.
-- https://gitlab.haskell.org/ghc/ci-images/-/issues/7
, GODEBUG = "http2client=0"
}
, needs = image.needs # [ "generate-dockerfiles" ]
, dependencies = [ "generate-dockerfiles" ]
......@@ -53,7 +65,8 @@ let
--context $CI_PROJECT_DIR \
--dockerfile $CI_PROJECT_DIR/dockerfiles/${image.name}/Dockerfile \
--destination $CI_REGISTRY_IMAGE/${image.name}:$CI_COMMIT_SHA \
--destination $CI_REGISTRY_IMAGE/${image.name}:latest
--destination $CI_REGISTRY_IMAGE/${image.name}:latest \
${customPlatform}
''
]
}
......@@ -85,7 +98,7 @@ let
{ stage = Some "lint"
, image = Some (GitLab.Image :: { name = "hadolint/hadolint:latest-debian" })
, tags = Some [ "x86_64-linux" ]
, script =
, script =
[ "find dockerfiles -name Dockerfile -print0 | xargs -0 -n1 hadolint" ]
}
......@@ -98,7 +111,7 @@ let top: GitLab.Top.Type =
-- N.B. Jobs sadly can only depend upon jobs in previous stages. Hence the
-- `build-derived` stage, which exists only for the `linter` job.
{ stages = Some [ "prepare", "lint", "build", "build-derived" ]
, jobs = jobs # toMap
, jobs = jobs # toMap
{ generate-dockerfiles = dockerfilesJob
-- , lint = lintJob
}
......
......@@ -10,5 +10,6 @@ let
, ./images/debian.dhall
, ./images/centos.dhall
, ./images/fedora.dhall
, ./images/rocky.dhall
]
in all-images
......@@ -13,31 +13,44 @@ let
let
Image = ../Image.dhall
let
docker_base_url: Text = "registry.gitlab.haskell.org/ghc/ci-images"
let
coreBuildDepends: List Text =
[ "autoconf"
[ "alpine-sdk"
, "autoconf"
, "automake"
, "bash"
, "binutils-gold"
, "build-base"
, "coreutils"
, "cpio"
, "curl"
, "gcc"
, "git"
, "gmp"
, "gmp-dev"
, "grep"
, "libffi"
, "linux-headers"
, "gzip"
, "jq"
, "libffi-dev"
, "lld"
, "musl-dev"
, "musl-locales"
, "ncurses-dev"
, "ncurses-libs"
, "ncurses-static"
, "perl"
, "python3"
, "zlib-dev"
, "xz"
, "bash"
, "git"
, "wget"
, "sudo"
, "grep"
, "curl"
, "gmp-dev"
, "cabal"
, "ghc"
, "unzip"
, "wget"
, "xz"
, "zlib-dev"
, "zstd"
]
let
......@@ -50,26 +63,43 @@ let
]
let
buildDepends: List Text = coreBuildDepends # docsBuildDepends
docsBuildDepends320: List Text =
[ "texmf-dist-lang"
, "texmf-dist-fontsrecommended"
, "texinfo"
]
let installDepsStep: CF.Type =
CF.run "Installing GHC build dependencies"
[ "apk add --no-cache ${Prelude.Text.concatSep " " buildDepends}" ]
let installPkgs: List Text -> CF.Type = \(pkgs: List Text) ->
CF.run "Installing packages: ${Prelude.Text.concatSep " " pkgs}"
[ "apk add --no-cache ${Prelude.Text.concatSep " " pkgs}" ]
let installGhcDepsStep: CF.Type =
installPkgs (coreBuildDepends # docsBuildDepends)
let installWasmDepsStep: CF.Type =
CF.run "Installing wasm backend dependencies"
[ "curl -f -L --retry 5 https://gitlab.haskell.org/haskell-wasm/ghc-wasm-meta/-/archive/45f73c3e075fa38efe84055b0dba87996948101d/ghc-wasm-meta-45f73c3e075fa38efe84055b0dba87996948101d.tar.gz | tar xz"
, "cd ghc-wasm-meta-*"
, "SKIP_GHC=1 ./setup.sh"
, "cd .."
, "rm -r ghc-wasm-meta-*"
, "sudo apk add --no-cache chromium firefox" ]
let
ghcVersion: Text = "8.10.4"
bootGhcVersion: Text = ../boot_ghc_version.dhall
let
fetchGhcStep: CF.Type =
let
destDir: Text = "/opt/ghc/${ghcVersion}"
in
Ghc.install
{ bindist = { version = ghcVersion, triple = "x86_64-alpine3.10-linux-integer-simple" }
, destDir = destDir
, configureOpts = [ "--disable-ld-override" ] : List Text
}
# CF.env (toMap { GHC = "${destDir}/bin/ghc" })
fetchGhcStep: Ghc.Bindist -> CF.Type =
\(ghcBindist: Ghc.Bindist) ->
let
destDir: Text = "/opt/ghc"
in
Ghc.install
{ bindist = ghcBindist
, destDir = destDir
, configureOpts = ["--disable-ld-override"] : List Text
}
# CF.env (toMap { GHC = "${destDir}/bin/ghc" })
-- Create a normal user
let
......@@ -80,21 +110,154 @@ let
]
# [CF.Statement.User "ghc"]
# CF.workdir "/home/ghc/"
# CF.run "update cabal index" [ "$CABAL update"]
let
images: List Image.Type =
[ Image::
[ Image ::
{ name = "x86_64-linux-alpine3_12"
, runnerTags = [ "x86_64-linux" ]
, image =
CF.from "alpine:3.12.0"
, image =
CF.from "alpine:3.12.12"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installGhcDepsStep
# fetchGhcStep (Ghc.Bindist.BindistSpec { version = bootGhcVersion, triple = "x86_64-alpine3_12-linux" })
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-alpine3_12" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
, Image ::
{ name = "x86_64-linux-alpine3_20-wasm"
, runnerTags = [ "x86_64-linux" ]
, needs = [ "x86_64-linux-alpine3_20" ]
, image =
CF.from "${docker_base_url}/x86_64-linux-alpine3_20:latest"
# [ CF.Statement.User "root" ]
# [ CF.Statement.User "ghc"
, CF.Statement.Cmd ["bash"]
]
# installWasmDepsStep
}
, Image ::
{ name = "i386-linux-alpine3_12"
, runnerTags = [ "x86_64-linux" ]
, image =
CF.from "i386/alpine:3.12.12"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installDepsStep
# fetchGhcStep
# Cabal.install (Cabal.Type.FromDistribution "/usr/bin/cabal")
# HaskellTools.build
# installGhcDepsStep
# fetchGhcStep (Ghc.Bindist.BindistURL "https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/9.0.1/ghc-9.0.1-i386-alpine-linux.tar.xz")
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "i386-linux-alpine3_12" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
, Image ::
{ name = "x86_64-linux-alpine3_15"
, runnerTags = [ "x86_64-linux" ]
, image =
CF.from "alpine:3.15.8"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installGhcDepsStep
# fetchGhcStep (Ghc.Bindist.BindistSpec { version = bootGhcVersion, triple = "x86_64-alpine3_12-linux" })
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-alpine3_12" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
, Image ::
{ name = "i386-linux-alpine3_15"
, runnerTags = [ "x86_64-linux" ]
, image =
CF.from "i386/alpine:3.15.8"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installGhcDepsStep
# fetchGhcStep (Ghc.Bindist.BindistURL "https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/9.0.1/ghc-9.0.1-i386-alpine-linux.tar.xz")
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "i386-linux-alpine3_12" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
, Image ::
{ name = "i386-linux-alpine3_17"
, runnerTags = [ "x86_64-linux" ]
, image =
CF.from "i386/alpine:3.17.3"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installGhcDepsStep
# installPkgs ["llvm15"]
# fetchGhcStep (Ghc.Bindist.BindistURL "https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/9.0.1/ghc-9.0.1-i386-alpine-linux.tar.xz")
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "i386-linux-alpine3_12" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
, Image ::
{ name = "i386-linux-alpine3_20"
, runnerTags = [ "x86_64-linux" ]
, image =
CF.from "i386/alpine:3.20.1"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installGhcDepsStep
# installPkgs (["llvm17", "clang17"] # docsBuildDepends320)
# fetchGhcStep (Ghc.Bindist.BindistURL "https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/9.10.1/ghc-9.10.1-i386-linux-alpine-3.17.7.tar.xz")
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "i386-linux-alpine3_12" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
, Image ::
{ name = "x86_64-linux-alpine3_18"
, runnerTags = [ "x86_64-linux" ]
, image =
CF.from "alpine:3.18.6"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installGhcDepsStep
# installPkgs ["llvm15", "clang15"]
# fetchGhcStep (Ghc.Bindist.BindistSpec { version = bootGhcVersion, triple = "x86_64-alpine3_12-linux" })
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-alpine3_12" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
, Image ::
{ name = "x86_64-linux-alpine3_20"
, runnerTags = [ "x86_64-linux" ]
, image =
CF.from "alpine:3.20.1"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installGhcDepsStep
# installPkgs (["llvm17", "clang17"] # docsBuildDepends320)
# fetchGhcStep (Ghc.Bindist.BindistSpec { version = bootGhcVersion, triple = "x86_64-alpine3_12-linux" })
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-alpine3_12" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
, Image ::
{ name = "aarch64-linux-alpine3_18"
, runnerTags = [ "aarch64-linux" ]
, image =
CF.from "arm64v8/alpine:3.18.0"
# [ CF.Statement.Shell ["/bin/ash", "-eo", "pipefail", "-c"] ]
# installGhcDepsStep
# fetchGhcStep (Ghc.Bindist.BindistSpec { version = bootGhcVersion, triple = "aarch64-alpine3_18-linux" })
# installPkgs ["cabal", "llvm15", "clang15"]
# CF.env (toMap { CABAL = "/usr/bin/cabal" })
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# [ CF.Statement.Cmd ["bash"] ]
}
]
......
......@@ -3,8 +3,6 @@ let
Prelude = ../deps/Prelude.dhall
let
CF = ../deps/Containerfile.dhall
let
Llvm = ../components/Llvm.dhall
let
Ghc = ../components/Ghc.dhall
let
......@@ -77,6 +75,13 @@ let
CF.run "apply nsswitch workaround"
[ "sed -i -e 's/systemd//g' /etc/nsswitch.conf" ]
let
centosEOLWorkaroundStep: CF.Type =
CF.run "patch .repo files"
[ "sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo"
, "sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo"
, "sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo" ]
let
installDepsStep: CF.Type =
CF.run "install build dependencies"
......@@ -91,6 +96,20 @@ let
]
# [CF.Statement.User "ghc"]
# CF.workdir "/home/ghc/"
# CF.run "update cabal index" [ "$CABAL update"]
let
installLatestPython: CF.Type =
CF.run "install latest python for testsuite"
[
"unset LLC OPT"
, "cd $(mktemp -d)"
, "curl -f -L --retry 5 https://www.python.org/ftp/python/3.11.2/Python-3.11.2.tar.xz | tar xJ --strip-components=1"
, "./configure --prefix=/home/ghc/.local"
, "make install -j$(curl -f -L --retry 5 https://gitlab.haskell.org/ghc/ghc/-/raw/master/mk/detect-cpu-count.sh | sh)"
, "sudo rm -rf /tmp/*"
]
# CF.env (toMap { PYTHON = "/home/ghc/.local/bin/python3" })
let
CentosImage =
......@@ -100,44 +119,40 @@ let
, fromImage : Text
, runnerTags : List Text
, bootstrapGhc : Ghc.BindistSpec
, llvm : Optional Llvm.Source
}
let
toDocker: type -> Image.Type = \(opts : type) ->
let
ghcDir: Text = "/opt/ghc/${opts.bootstrapGhc.version}"
let
llvmDir: Text = "/opt/llvm"
let
image: CF.Type =
CF.from opts.fromImage
# CF.env (toMap { LANG = "C.UTF-8" })
# [ CF.Statement.Shell ["/bin/bash", "-o", "pipefail", "-c"] ]
# centosEOLWorkaroundStep
# installDepsStep
# nsswitchWorkaroundStep
-- install GHC
# Ghc.install
{ bindist = opts.bootstrapGhc
{ bindist = Ghc.Bindist.BindistSpec opts.bootstrapGhc
, destDir = ghcDir
, configureOpts = [] : List Text
}
# CF.env (toMap { GHC = "${ghcDir}/bin/ghc" })
-- install LLVM to be used by built compiler
# Llvm.maybeInstallTo llvmDir opts.llvm
-- install cabal-install
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.2.0.0", triple = "x86_64-unknown-linux" })
# Cabal.install (Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-centos7" })
-- install hscolour, alex, and happy
# HaskellTools.build
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# nsswitchWorkaround
# createUserStep
# CF.run "update cabal index" [ "$CABAL update"]
# installLatestPython
# [ CF.Statement.Cmd ["bash"] ]
in
......@@ -151,13 +166,14 @@ let
, toDocker = toDocker
}
let bootGhcVersion = ../boot_ghc_version.dhall
let images: List Image.Type =
[ CentosImage.toDocker
{ name = "x86_64-linux-centos7"
, fromImage = "centos:7"
, runnerTags = [ "x86_64-linux" ]
, bootstrapGhc = { version = "8.10.4", triple = "x86_64-centos7-linux" }
, llvm = None Llvm.Source
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-centos7-linux" }
}
]
in images
......@@ -14,8 +14,16 @@ let
Cabal = ../components/Cabal.dhall
let
Image = ../Image.dhall
let
LlvmMinGW = ../components/LlvmMingw.dhall
let
Wine = ../components/Wine.dhall
let
FEX = ../components/FEX.dhall
let
MSYS2 = ../components/MSYS2.dhall
let
let
docker_base_url: Text = "registry.gitlab.haskell.org/ghc/ci-images"
let
......@@ -25,6 +33,7 @@ let
, "libsqlite3-0"
, "libsqlite3-dev"
, "libgmp-dev"
, "libncurses-dev"
, "ca-certificates"
, "g++"
, "git"
......@@ -46,8 +55,6 @@ let
, "wget"
, "curl"
, "locales"
-- For LLVM
, "libtinfo5"
-- DWARF libraries
, "libdw1", "libdw-dev"
-- For nofib
......@@ -56,6 +63,10 @@ let
, "systemtap-sdt-dev"
-- For lndir
, "xutils-dev"
-- For wasm CI jobs
, "unzip"
-- For python
, "pkg-config"
]
let
......@@ -66,17 +77,45 @@ let
, "texlive-binaries"
, "texlive-fonts-recommended"
, "lmodern"
, "tex-gyre"
]
let debianBuildDepends: List Text =
[ "texlive-generic-extra" ]
[ "texlive-generic-extra"
]
let debian11OrHigherBuildDepends: List Text =
[ "texlive-plain-generic"
]
let debian12LinuxPerfDepends: List Text =
[ "linux-perf"
]
let ubuntuBuildDepends: List Text =
[ "texlive-plain-generic" ]
[ "texlive-plain-generic"
]
let
buildDepends: List Text = coreBuildDepends # docsBuildDepends
let
RepoType = < Standard | Archive >
let
updateRepositories: RepoType -> CF.Type =
\(repo : RepoType) ->
let useArchives : CF.Type =
[ CF.Statement.Comment "Use archive repos"
, CF.Statement.Exec [ "sed", "-i", "s/deb.debian.org/archive.debian.org/g", "/etc/apt/sources.list" ]
, CF.Statement.Exec [ "sed", "-i", "s|security.debian.org|archive.debian.org/|g", "/etc/apt/sources.list" ]
, CF.Statement.Exec [ "sed", "-i", "/-updates/d", "/etc/apt/sources.list" ]
, CF.Statement.Empty
]
in merge { Standard = [] : CF.Type, Archive = useArchives } repo
let
installPackages: List Text -> CF.Type =
\(pkgs: List Text) ->
......@@ -102,6 +141,7 @@ let
]
# [CF.Statement.User "ghc"]
# CF.workdir "/home/ghc/"
# CF.run "update cabal index" [ "$CABAL update"]
-- Install stack for testing hadrian
let
......@@ -110,6 +150,138 @@ let
[ "curl -sSL https://get.haskellstack.org/ | sh"
]
let
installLlvmFromAptStrict : Text -> Llvm.Config =
\(ver : Text) ->
{ action = CF.run "install llvm" [ "apt-get install -qy wget software-properties-common gnupg lsb-release"
, "wget https://apt.llvm.org/llvm.sh"
, "chmod +x llvm.sh"
, "./llvm.sh ${ver}"
]
, out_llc = "/usr/bin/llc-${ver}"
, out_opt = "/usr/bin/opt-${ver}"
, out_clang = "/usr/bin/clang-${ver}"
, out_clang_cpp = "/usr/bin/clang++-${ver}"
}
let
installLlvmFromApt : Text -> Optional Llvm.Config =
\(ver : Text) -> Some (installLlvmFromAptStrict ver)
-- Workaround for https://github.com/llvm/llvm-project/issues/62475
let
installLlvmFromAptBookworm : Text -> Optional Llvm.Config =
\(ver : Text) -> Some
{ action = CF.run "install llvm" [ "apt-get install -qy wget software-properties-common gnupg lsb-release"
, "echo \"deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${ver} main\" > /etc/apt/sources.list.d/apt.llvm.org.list"
, "wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc"
, "apt update"
, "apt-get install -y clang-${ver} lldb-${ver} lld-${ver} clangd-${ver}"
]
, out_llc = "/usr/bin/llc-${ver}"
, out_opt = "/usr/bin/opt-${ver}"
, out_clang = "/usr/bin/clang-${ver}"
, out_clang_cpp = "/usr/bin/clang++-${ver}"
}
let
installEMSDK: CF.Type =
CF.run "install emsdk"
[ "sudo mkdir /emsdk"
, "sudo chown ghc:ghc /emsdk"
, "curl -f -L --retry 5 https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.40.tar.gz | tar xz --strip-components=1 -C /emsdk"
, "/emsdk/emsdk install latest"
, "/emsdk/emsdk activate latest"
]
# CF.env (toMap { EMSDK = "/emsdk" })
let
installNodeJS: CF.Type =
CF.run "install nodejs"
[ "curl -fsSL https://deb.nodesource.com/setup_21.x | sudo -E bash - && sudo apt-get install -y nodejs"
]
let
installGoogleClosureCompiler: CF.Type =
CF.run "install Google Closure Compiler"
[ "sudo npm i -g google-closure-compiler@20240317.0.0"
-- By some reason "linux native" version ends with segmentation fault on deb11.
-- But we can use java version w/o issues.
-- To run Google Closure Compiler in "java"-platform mode needed call:
-- $ google-closure-compiler --platform=java
-- For example:
-- $ google-closure-compiler --platform=java --help
, "sudo apt install -y default-jre"
]
let
installLatestPython: CF.Type =
CF.run "install latest python for testsuite"
[
"unset LLC OPT"
, "cd $(mktemp -d)"
, "curl -f -L --retry 5 https://www.python.org/ftp/python/3.11.2/Python-3.11.2.tar.xz | tar xJ --strip-components=1"
, "./configure --build=$(dpkg --print-architecture)-linux --prefix=/home/ghc/.local"
, "make install -j$(curl -f -L --retry 5 https://gitlab.haskell.org/ghc/ghc/-/raw/master/mk/detect-cpu-count.sh | sh)"
, "sudo rm -rf /tmp/*"
]
# CF.env (toMap { PYTHON = "/home/ghc/.local/bin/python3" })
let
installLibzstd: CF.Type =
CF.run "install libzstd >= 1.4.0, required for IPE data compression"
[ "sudo mkdir /libzstd"
, "sudo chown ghc:ghc /libzstd"
, "curl -f -L --retry 5 https://github.com/facebook/zstd/releases/download/v1.5.5/zstd-1.5.5.tar.gz | tar xz --strip-components=1 -C /libzstd"
, "cd /libzstd/lib"
, "sudo make prefix=/usr install -j$(curl -f -L --retry 5 https://gitlab.haskell.org/ghc/ghc/-/raw/master/mk/detect-cpu-count.sh | sh)"
]
let
-- See https://wiki.debian.org/RISC-V#Cross_compilation
installRiscv64: CF.Type =
CF.run "install RISCV64 cross-compilation toolchain"
[ "sudo apt-get update"
, "sudo dpkg --add-architecture riscv64"
, "sudo apt-get install -yq gcc-riscv64-linux-gnu g++-riscv64-linux-gnu"
, "sudo ln -s /usr/riscv64-linux-gnu/lib/ld-linux-riscv64-lp64d.so.1 /lib"
, ''
sudo tee /etc/ld.so.conf.d/riscv64-linux-gnu.conf > /dev/null <<EOF
/usr/local/lib/riscv64-linux-gnu
/lib/riscv64-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/riscv64-linux-gnu/lib/
EOF
''
]
let
installLoongArch64: CF.Type =
CF.run "install LoongArch64 cross-compilation toolchain"
[ "sudo apt update"
, "sudo apt install -yq gcc-14-loongarch64-linux-gnu g++-14-loongarch64-linux-gnu rename"
, "sudo rename 's/-14$//' /usr/bin/loongarch64-linux-gnu-*-14"
, "sudo ln -s /usr/loongarch64-linux-gnu/lib/ld-linux-loongarch-lp64d.so.1 /lib"
, ''
sudo tee /etc/ld.so.conf.d/loongarch64-linux-gnu.conf > /dev/null <<EOF
/usr/local/lib/loongarch64-linux-gnu
/lib/loongarch64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/loongarch64-linux-gnu/lib/
EOF
''
]
let
bootLlvmDir: Text = "/opt/llvm-bootstrap"
let
bootLlvmConfig = \(bd : Llvm.BindistSpec) -> Some (Llvm.installFromBindistTo bootLlvmDir bd)
let
llvmDir: Text = "/opt/llvm"
let
llvmConfig = \(bd : Llvm.BindistSpec) -> Some (Llvm.installFromBindistTo llvmDir bd)
let
DebianImage =
let
......@@ -117,13 +289,23 @@ let
{ name: Text
, fromImage : Text
, runnerTags : List Text
, bootstrapLlvm : Optional Llvm.Source
-- See Note [Specifying custom platform]
, customPlatform : Optional Text
, bootstrapLlvm : Optional Llvm.Config
, bootstrapGhc : Ghc.BindistSpec
, llvm : Optional Llvm.Source
, llvm : Optional Llvm.Config
, cabalSource : Cabal.Type
, extraPackages: List Text
-- N.B. Optional as Stack's installer does not support all platforms
, withStack : Bool
, withEMSDK : Bool
, withClosure : Bool
-- deb9/ubuntu18 python too old for testsuite driver, needs at least 3.7
, withLatestPython : Bool
, withLibzstd : Bool
, repoType : RepoType
, withRiscv64 : Bool
, withLoongArch64 : Bool
}
let
......@@ -131,180 +313,429 @@ let
let
ghcDir: Text = "/opt/ghc/${opts.bootstrapGhc.version}"
let
bootLlvmDir: Text = "/opt/llvm-bootstrap"
let
llvmDir: Text = "/opt/llvm"
let
bootstrapLlvmConfigureOptions =
merge { Some = \(_: Llvm.Source) -> [ "LLC=${bootLlvmDir}/bin/llc", "OPT=${bootLlvmDir}/bin/opt" ]
, None = [] : List Text
} opts.bootstrapLlvm
bootstrapLlvmConfigureOptions = Llvm.configureArgs opts.bootstrapLlvm
let
image =
CF.from opts.fromImage
# CF.env (toMap { LANG = "C.UTF-8" })
# [ CF.Statement.Shell ["/bin/bash", "-o", "pipefail", "-c"] ]
# updateRepositories opts.repoType
# installPackages (buildDepends # opts.extraPackages)
# (if opts.withStack then installStack else [] : CF.Type)
# cleanApt
-- install LLVM for bootstrap GHC
# Llvm.maybeInstallTo bootLlvmDir opts.bootstrapLlvm
# Llvm.install opts.bootstrapLlvm
-- install GHC
# Ghc.install
{ bindist = opts.bootstrapGhc
{ bindist = Ghc.Bindist.BindistSpec opts.bootstrapGhc
, destDir = ghcDir
, configureOpts = bootstrapLlvmConfigureOptions
}
# CF.env (toMap { GHC = "${ghcDir}/bin/ghc" })
-- install LLVM to be used by built compiler
# Llvm.maybeInstallTo llvmDir opts.llvm
# Llvm.setEnv llvmDir
# Llvm.install opts.llvm
# Llvm.setEnv opts.llvm
# cleanApt
-- install cabal-install
# Cabal.install opts.cabalSource
-- install hscolour, alex, and happy
# HaskellTools.build
# CF.run "update cabal index" [ "$CABAL update"]
# HaskellTools.installGhcBuildDeps
# createUserStep
# CF.run "update cabal index" [ "$CABAL update"]
# (if opts.withEMSDK || opts.withClosure then installNodeJS else [] : CF.Type)
# (if opts.withEMSDK then installEMSDK else [] : CF.Type)
# (if opts.withClosure then installGoogleClosureCompiler else [] : CF.Type)
# (if opts.withLatestPython then installLatestPython else [] : CF.Type)
# (if opts.withLibzstd then installLibzstd else [] : CF.Type)
# [ CF.Statement.Cmd ["bash"] ]
# (if opts.withRiscv64 then installRiscv64 else [] : CF.Type)
# (if opts.withLoongArch64 then installLoongArch64 else [] : CF.Type)
in Image::{ name = opts.name, runnerTags = opts.runnerTags, image = image }
in Image::{ name = opts.name
, runnerTags = opts.runnerTags
, customPlatform = opts.customPlatform
, image = image
}
in
{ Type = type
, default =
{ withStack = True
{ customPlatform = None Text
, withStack = False
, withEMSDK = False
, withClosure = False
, withLatestPython = False
, withLibzstd = False
, repoType = RepoType.Standard
, bootstrapLlvm = None Llvm.Config
, llvm = None Llvm.Config
, withRiscv64 = False
, withLoongArch64 = False
}
, toDocker = toDocker
}
let images: List Image.Type =
let bootGhcVersion = ../boot_ghc_version.dhall
let debian11Images: List Image.Type =
[ DebianImage.toDocker DebianImage::
{ name = "aarch64-linux-deb10"
, fromImage = "arm64v8/debian:buster"
{ name = "x86_64-linux-deb11"
, fromImage = "amd64/debian:bullseye"
, runnerTags = [ "x86_64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb10-linux" }
, llvm = installLlvmFromApt "15"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-deb10" }
, extraPackages =
debian11OrHigherBuildDepends
-- For cross-compilation testing
# [ "crossbuild-essential-arm64", "crossbuild-essential-s390x", "qemu-user" ]
, withEMSDK = False
}
, DebianImage.toDocker DebianImage::
{ name = "x86_64-linux-deb11-emsdk-closure"
, fromImage = "amd64/debian:bullseye"
, runnerTags = [ "x86_64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb10-linux" }
, llvm = installLlvmFromApt "15"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-deb10" }
, extraPackages = [] : List Text
, withEMSDK = True
, withClosure = True
}
, DebianImage.toDocker DebianImage::
{ name = "aarch64-linux-deb11"
, fromImage = "arm64v8/debian:bullseye"
, runnerTags = [ "aarch64-linux" ]
, bootstrapLlvm = Some (Llvm.Source.FromBindist { version = "9.0.1" , triple = "aarch64-linux-gnu" })
, bootstrapGhc = { version = "8.10.4", triple = "aarch64-deb10-linux" }
, llvm = Some (Llvm.Source.FromBindist { version = "11.0.1" , triple = "aarch64-linux-gnu" })
, cabalSource = Cabal.Type.FromBindist "http://home.smart-cactus.org/~ben/ghc/cabal-install-3.4.0.0-rc4-aarch64-linux.tar.xz"
, extraPackages = [ "libnuma-dev" ] : List Text
, withStack = False
, bootstrapGhc = { version = bootGhcVersion, triple = "aarch64-deb10-linux" }
, llvm = installLlvmFromApt "15"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "aarch64-linux-deb10" }
, extraPackages = [ ] : List Text
}
, DebianImage.toDocker DebianImage::
{ name = "i386-linux-deb11"
, fromImage = "i386/debian:bullseye"
, runnerTags = [ "x86_64-linux" ]
, customPlatform = Some "linux/386"
, bootstrapGhc = { version = bootGhcVersion, triple = "i386-deb10-linux" }
, llvm = None Llvm.Config
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "i386-linux-deb9" }
, extraPackages = debian11OrHigherBuildDepends
}
]
let x86_deb12_base : DebianImage.Type =
DebianImage::
{ name = "x86_64-linux-deb12"
, fromImage = "amd64/debian:bookworm"
, runnerTags = [ "x86_64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb10-linux" }
, llvm = installLlvmFromAptBookworm "19"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-deb11" }
, extraPackages =
debian11OrHigherBuildDepends
-- Add support for perf test suite runs
# debian12LinuxPerfDepends
, withEMSDK = False
, withClosure = False
}
let debian12Images: List Image.Type =
[ DebianImage.toDocker
(x86_deb12_base with extraPackages = x86_deb12_base.extraPackages # debian12LinuxPerfDepends # ["libnuma-dev"]
with withLibzstd = True
with withStack = True )
, DebianImage.toDocker
(x86_deb12_base with name = "x86_64-linux-deb12-riscv"
with extraPackages = x86_deb12_base.extraPackages # ["qemu-user"]
with withRiscv64 = True )
, DebianImage.toDocker DebianImage::
{ name = "armv7-linux-deb10"
, fromImage = "arm32v7/debian:buster"
, runnerTags = [ "armv7-linux" ]
, bootstrapLlvm = Some (Llvm.Source.FromBindist { version = "9.0.1", triple = "armv7a-linux-gnueabihf" })
, bootstrapGhc = { version = "8.10.4", triple = "armv7-deb10-linux" }
, llvm = Some (Llvm.Source.FromBindist { version = "11.0.1" , triple = "armv7a-linux-gnueabihf" })
, cabalSource = Cabal.Type.FromBindist "http://home.smart-cactus.org/~ben/ghc/cabal-install-3.4.0.0-rc4-armv7l-deb10.tar.xz"
, extraPackages = [ "libnuma-dev" ] # debianBuildDepends
, withStack = False
{ name = "aarch64-linux-deb12"
, fromImage = "arm64v8/debian:bookworm"
, runnerTags = [ "aarch64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "aarch64-deb10-linux" }
, llvm = installLlvmFromApt "19"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "aarch64-linux-deb11" }
, extraPackages = [ ] : List Text
}
, ( let
home_dir = "/home/ghc"
let
cabal_index_state = "2025-03-20T17:30:02Z"
let
msys_cabal_version = "3.14.1.1"
let deb = DebianImage.toDocker DebianImage::
{ name = "aarch64-linux-deb12-wine"
, fromImage = "arm64v8/debian:bookworm"
, runnerTags = [ "aarch64-linux" ]
, bootstrapGhc = { version = "9.12.2", triple = "aarch64-deb12-linux" }
, llvm = installLlvmFromApt "19"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.14.1.1", triple = "aarch64-linux-deb12" }
, extraPackages = [
, "zstd" -- uncompress debs for FEX dlls
] : List Text
}
in deb with image = deb.image
# [CF.Statement.User "root"]
# CF.workdir "/root/"
-- Its purpose is to test the building of cross-compiled GHC for Aarch64 Windows from Linux
-- At the moment GHC supports LLVM =< 19, where 20250114@mstorsjo is 19.1.7
# LlvmMinGW.installFromBindistTo "/opt/llvm-mingw-linux"
{ source = "mstorsjo", version = "20250114", crt = "ucrt"
, os = "ubuntu-20.04-aarch64", archive = LlvmMinGW.Archive.TAR_XZ
}
# Wine.installForArm64EC { version = "10.7" }
# FEX.install Wine.installedPath { version = "2505_j" }
# [CF.Statement.User "ghc"]
# CF.workdir "${home_dir}/"
# CF.env (toMap { WINEPREFIX = "${home_dir}/.wine", WINEDEBUG = "-all" })
# CF.run "init Wine drives for selected user with FEX registry preinstall"
[ "${Wine.installedPath}/bin/wine reg.exe ADD 'HKLM\\Software\\Microsoft\\Wow64\\amd64' /ve /t REG_SZ /d 'libarm64ecfex.dll' /f"
-- Forcely keep all registry changes are persistent
, "${Wine.installedPath}/bin/wineserver -k 15"
]
# MSYS2.install home_dir { wine_version = "10.7", version_year = "2025", version_month = "02", version_day = "21", build_date = "20250512", build_time = "1031" } Wine.installedPath
# CF.run "install GHC"
[ "mkdir ${home_dir}/.wine/drive_c/msys64/opt/ghc-bootstrap"
, "curl -L https://downloads.haskell.org/~ghc/9.12.2/ghc-9.12.2-x86_64-unknown-mingw32.tar.xz | tar -Jx -C ${home_dir}/.wine/drive_c/msys64/opt/ghc-bootstrap --strip-components=1"
, "echo 'export PATH=/opt/ghc-bootstrap/bin:$PATH' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
, "echo 'export GHC=/opt/ghc-bootstrap/bin/ghc' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
, "${Wine.installedPath}/bin/wine c:/msys64/usr/bin/bash.exe -l -c 'ghc --version'"
]
# CF.run "install Cabal"
[ "mkdir -p ${home_dir}/.wine/drive_c/msys64/opt/cabal/{bin,dir}"
, "wget -q -O tmp.zip https://downloads.haskell.org/cabal/cabal-install-${msys_cabal_version}/cabal-install-${msys_cabal_version}-x86_64-windows.zip"
, "unzip tmp.zip -d Cabal-msys2"
, "cp ./Cabal-msys2/cabal.exe ${home_dir}/.wine/drive_c/msys64/opt/cabal/bin/"
, "rm tmp.zip"
, "rm -r ./Cabal-msys2"
, "echo 'export PATH=/opt/cabal/dir/bin:/opt/cabal/bin:$PATH' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
, "echo 'export CABAL=/opt/cabal/bin/cabal' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
-- Double escaping: one for Dhall, second for Bash
, "echo 'export CABAL_CONFIG=C:\\\\msys64\\\\opt\\\\cabal\\\\cabal.conf' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
, "echo 'export CABAL_DIR=C:\\\\msys64\\\\opt\\\\cabal\\\\dir' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
, "${Wine.installedPath}/bin/wine c:/msys64/usr/bin/bash.exe -l -c 'cabal user-config init'"
-- The install method should be COPY because MSYS2 does not support symlinking under Wine
, "sed -i 's/-- install-method:/install-method: copy/g' ${home_dir}/.wine/drive_c/msys64/opt/cabal/cabal.conf"
-- Set Cabal registry to specific revision, yep, we need pass same index state reference twice.
, "sed -i 's/-- index-state:/index-state: ${cabal_index_state}/g' ${home_dir}/.wine/drive_c/msys64/opt/cabal/cabal.conf"
, "${Wine.installedPath}/bin/wine c:/msys64/usr/bin/bash.exe -l -c 'cabal update \"hackage.haskell.org,${cabal_index_state}\"'"
]
-- We are going to replace GHC's prepacked mingw toolchain with new one.
-- At the moment GHC supports LLVM =< 19, where 20250114@mstorsjo is 19.1.7
# CF.run "Remove prepared MinGW toolchain"
[ "rm -rf ${home_dir}/.wine/drive_c/msys64/opt/ghc-bootstrap/mingw"
]
# LlvmMinGW.installFromBindistTo "${home_dir}/.wine/drive_c/msys64/opt/ghc-bootstrap/mingw"
{ source = "mstorsjo", version = "20250114", crt = "ucrt"
, os = "aarch64", archive = LlvmMinGW.Archive.ZIP
}
# CF.run "Setup Clang"
[ -- We should pass the full path to the linker. Also be warn:
-- > lld is a generic driver.
-- > Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld (WebAssembly) instead
-- So, let's use ld.lld because we are in msys2 environment. lld-link will not work.
''
sed -i 's#-fuse-ld=lld#-fuse-ld=$topdir/../mingw/bin/ld.lld#g' \
${home_dir}/.wine/drive_c/msys64/opt/ghc-bootstrap/lib/settings \
''
-- msys2's environment has different location for libs
, ''
sed -i 's#clang64/opt/llvm-16/x86_64-w64-mingw32/lib#clang64/lib#g' \
${home_dir}/.wine/drive_c/msys64/opt/ghc-bootstrap/lib/settings \
''
-- windress is platform-dependent
, ''
sed -i 's#/llvm-windres.exe#/x86_64-w64-mingw32-windres.exe#g' \
${home_dir}/.wine/drive_c/msys64/opt/ghc-bootstrap/lib/settings
''
]
# CF.run "install GHC build deps"
[ ''
${Wine.installedPath}/bin/wine c:/msys64/usr/bin/bash.exe -l -c 'cabal v2-install \
--constraint="alex ^>= 3.5.2.0" \
--constraint="happy ^>= 2.1.5" \
--constraint="hscolour ^>= 1.25" \
'' ++ Prelude.Text.concatSep " " [ "hscolour", "happy", "alex" ] ++ "'"
, "echo 'export ALEX=/opt/cabal/dir/bin/alex' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
, "echo 'export HAPPY=/opt/cabal/dir/bin/happy' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
, "echo 'export HSCOLOUR=/opt/cabal/dir/bin/HsColour' >> ${home_dir}/.wine/drive_c/msys64/home/ghc/.bash_profile"
]
)
, DebianImage.toDocker DebianImage::
{ name = "i386-linux-deb9"
, fromImage = "i386/debian:stretch"
{ name = "i386-linux-deb12"
, fromImage = "i386/debian:bookworm"
, runnerTags = [ "x86_64-linux" ]
, bootstrapLlvm = None Llvm.Source
, bootstrapGhc = { version = "8.10.4", triple = "i386-deb9-linux" }
, llvm = None Llvm.Source
, cabalSource = Cabal.Type.FromBindist "https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-unknown-linux.tar.xz"
, extraPackages = debianBuildDepends # [ "cabal-install" ] : List Text
, withStack = False
, customPlatform = Some "linux/386"
, bootstrapGhc = { version = bootGhcVersion, triple = "i386-deb10-linux" }
, llvm = None Llvm.Config
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "i386-linux-deb9" }
, extraPackages =
debian11OrHigherBuildDepends
}
]
-- N.B. Need bindist for deb10 i386
--, DebianImage.toDocker DebianImage::
-- { name = "i386-linux-deb10"
-- , fromImage = "i386/debian:buster"
-- , runnerTags = [ "x86_64-linux" ]
-- , bootstrapLlvm = None Llvm.Source
-- , bootstrapGhc = { version = "8.10.4", triple = "i386-deb10-linux" }
-- , llvm = None Llvm.Source
-- , cabalSource = Cabal.Type.FromSource "3.2.0.0"
-- , extraPackages =
-- debianBuildDepends
-- # [ "libnuma-dev" ]
-- # [ "cabal-install" ]
-- , withStack = False
-- }
let debian10Images: List Image.Type =
[ DebianImage.toDocker DebianImage::
{ name = "aarch64-linux-deb10"
, fromImage = "arm64v8/debian:buster"
, runnerTags = [ "aarch64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "aarch64-deb10-linux" }
, llvm = installLlvmFromApt "15"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "aarch64-linux-deb10" }
, extraPackages = [] : List Text
}
, DebianImage.toDocker DebianImage::
{ name = "i386-linux-deb10"
, fromImage = "i386/debian:buster"
, runnerTags = [ "x86_64-linux" ]
, customPlatform = Some "linux/386"
, bootstrapGhc = { version = bootGhcVersion, triple = "i386-deb10-linux" }
, llvm = None Llvm.Config
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "i386-linux-deb9" }
, extraPackages =
debianBuildDepends
# [ "libnuma-dev", "libtinfo5" ]
# [ "cabal-install" ]
}
, DebianImage.toDocker DebianImage::
{ name = "x86_64-linux-deb10"
, fromImage = "amd64/debian:buster"
, runnerTags = [ "x86_64-linux" ]
, bootstrapLlvm = Some (Llvm.Source.FromBindist { version = "9.0.1", triple = "x86_64-linux-gnu-ubuntu-16.04" })
, bootstrapGhc = { version = "8.10.4", triple = "x86_64-deb10-linux" }
, llvm = Some (Llvm.Source.FromBindist { version = "11.0.1" , triple = "x86_64-linux-gnu-ubuntu-16.04" })
, cabalSource = Cabal.fromUpstreamBindist { version = "3.2.0.0", triple = "x86_64-unknown-linux" }
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb10-linux" }
, llvm = installLlvmFromApt "15"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-deb10" }
, extraPackages =
debianBuildDepends
-- For cross-compilation testing
# ["crossbuild-essential-arm64"]
# [ "libnuma-dev" ]
}
]
, DebianImage.toDocker DebianImage::
let debian9Images: List Image.Type =
[ DebianImage.toDocker DebianImage::
{ name = "x86_64-linux-deb9"
, fromImage = "amd64/debian:stretch"
, runnerTags = [ "x86_64-linux" ]
, bootstrapLlvm = None Llvm.Source
, bootstrapGhc = { version = "8.10.4", triple = "x86_64-deb9-linux" }
, llvm = Some (Llvm.Source.FromBindist { version = "10.0.1" , triple = "x86_64-linux-gnu-ubuntu-16.04" })
, cabalSource = Cabal.fromUpstreamBindist { version = "3.2.0.0", triple = "x86_64-unknown-linux" }
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb9-linux" }
-- No debian 9 build for cabal 3.10.1.0
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.1.0", triple = "x86_64-linux-deb9" }
, extraPackages = debianBuildDepends : List Text
, withLatestPython = True
, repoType = RepoType.Archive
}
]
, DebianImage.toDocker DebianImage::
let ubuntuImages: List Image.Type =
[
DebianImage.toDocker DebianImage::
{ name = "x86_64-linux-ubuntu24_04-loongarch"
, fromImage = "amd64/ubuntu:24.04"
, runnerTags = [ "x86_64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb11-linux" }
, llvm = installLlvmFromApt "19"
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-deb11" }
, extraPackages = ubuntuBuildDepends # [ "qemu-user" ]
, withLoongArch64 = True
}
, DebianImage.toDocker DebianImage::
{ name = "x86_64-linux-ubuntu24_04"
, fromImage = "amd64/ubuntu:24.04"
, runnerTags = [ "x86_64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb11-linux" }
, llvm = llvmConfig { version = "15.0.6" , triple = "x86_64-linux-gnu-ubuntu-18.04" }
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-deb11" }
, extraPackages = ubuntuBuildDepends
}
, DebianImage.toDocker DebianImage::
{ name = "x86_64-linux-ubuntu22_04"
, fromImage = "amd64/ubuntu:22.04"
, runnerTags = [ "x86_64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb10-linux" }
, llvm = llvmConfig { version = "15.0.6" , triple = "x86_64-linux-gnu-ubuntu-18.04" }
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-deb10" }
, extraPackages = ubuntuBuildDepends
}
, DebianImage.toDocker DebianImage::
{ name = "x86_64-linux-ubuntu20_04"
, fromImage = "amd64/ubuntu:20.04"
, runnerTags = [ "x86_64-linux" ]
, bootstrapLlvm = None Llvm.Source
, bootstrapGhc = { version = "8.10.4", triple = "x86_64-deb9-linux" }
, llvm = Some (Llvm.Source.FromBindist { version = "11.0.1" , triple = "x86_64-linux-gnu-ubuntu-16.04" })
, cabalSource = Cabal.fromUpstreamBindist { version = "3.2.0.0", triple = "x86_64-unknown-linux" }
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb10-linux" }
, llvm = llvmConfig { version = "15.0.6" , triple = "x86_64-linux-gnu-ubuntu-18.04" }
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-ubuntu20_04" }
, extraPackages = ubuntuBuildDepends
}
, DebianImage.toDocker DebianImage::
{ name = "x86_64-linux-ubuntu18_04"
, fromImage = "amd64/ubuntu:18.04"
, runnerTags = [ "x86_64-linux" ]
, bootstrapGhc = { version = bootGhcVersion, triple = "x86_64-deb9-linux" }
, cabalSource = Cabal.fromUpstreamBindist { version = "3.10.2.0", triple = "x86_64-linux-ubuntu18_04" }
, extraPackages = [ "libtinfo5" ] # ubuntuBuildDepends
, withLatestPython = True
}
]
, Image::
let linterImages: List Image.Type =
[ Image::
{ name = "linters"
, runnerTags = [ "x86_64-linux" ]
, jobStage = "build-derived"
, needs = [ "x86_64-linux-deb10" ]
, needs = [ "x86_64-linux-deb12" ]
, image =
let installMypy: CF.Type =
[ CF.Statement.User "root" ]
# installPackages [ "python3-pip" ]
# CF.run "installing mypy" [ "pip3 install mypy==0.701" ]
let lintersCommit: Text = "38aa8be4374692e3b2442ca24e6c497761f5bead"
let installLinters: CF.Type =
[ CF.Statement.User "ghc" ]
# CF.run "cloning linter repository"
[ "git clone https://gitlab.haskell.org/ghc/git-haskell-org-hooks"
, "git -C git-haskell-org-hooks checkout ${lintersCommit}"
]
# CF.run "building linters"
[ "cd git-haskell-org-hooks"
, "$CABAL update"
, "$CABAL install -w $GHC"
]
# CF.env (toMap { PATH = "/home/ghc/.cabal/bin:$PATH" })
installPackages [ "pipx", "python3-setuptools", "python3-pip", "python3-dev", "python3-wheel" ]
-- Need version 1.5.0.0 of pipx which isn't available on deb10
# CF.run "installing mypy" [ "pipx install pipx" ]
# CF.run "installing mypy" [ "/root/.local/bin/pipx install --global mypy==1.0" ]
let lintersCommit: Text = "b376b0c20e033e71751fe2059daba1ba40b886be"
let installShellcheck: CF.Type =
installPackages [ "shellcheck" ]
in
CF.from "${docker_base_url}/x86_64-linux-deb10:latest"
CF.from "${docker_base_url}/x86_64-linux-deb12:latest"
# [ CF.Statement.User "root" ]
# installMypy
# installShellcheck
# installLinters
# [CF.Statement.User "ghc"]
}
]
in images
let bootstrapImages: List Image.Type =
[ DebianImage.toDocker (x86_deb12_base
with name = "x86_64-linux-deb12-ghc9_8"
with bootstrapGhc = { version = "9.8.1", triple = "x86_64-deb10-linux" } )
, DebianImage.toDocker (x86_deb12_base
with name = "x86_64-linux-deb12-ghc9_10"
with bootstrapGhc = { version = "9.10.1", triple = "x86_64-deb10-linux" } )
]
let allImages: List Image.Type =
linterImages # debian12Images # debian11Images # debian10Images # debian9Images # ubuntuImages # bootstrapImages
in allImages