Skip to content

Commit 8981eea

Browse files
committed
Adds tooling image builder
1 parent 421318b commit 8981eea

1 file changed

Lines changed: 244 additions & 0 deletions

File tree

tooling/builder.sh

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
#!/usr/bin/env sh
2+
set -eu
3+
4+
################################################################################
5+
# Pre-flight checks.
6+
################################################################################
7+
8+
command -v git >/dev/null 2>&1 || { echo >&2 "git is not installed, aborting."; exit 1; }
9+
command -v buildah >/dev/null 2>&1 || { echo >&2 "buildah is not installed, aborting."; exit 1; }
10+
11+
# Start the script in the top-level repository directory no matter what.
12+
cd "$( git rev-parse --show-toplevel )"
13+
14+
################################################################################
15+
# Argument parsing and related values.
16+
#
17+
# cf. https://sookocheff.com/post/bash/parsing-bash-script-arguments-with-shopts/
18+
################################################################################
19+
20+
alpine_ver="3.14"
21+
container="ghc-with-tooling"
22+
image="ghc-with-tooling"
23+
ghc_version="8.10.7"
24+
25+
# NOTE: The logic associated with this will have to change for GHC 9.x and up to
26+
# support the changes introduced with the switch to `ghc-bignum`.
27+
numeric="gmp"
28+
29+
cabal_version="3.6.0.0"
30+
31+
stack_version="2.7.3"
32+
stack_expected_checksum="c5bce24defa2b2b86f1bbb14bed4f1ee83bec14c6ed9fcc81174d5473fbf3450"
33+
34+
hls_version="1.4.0"
35+
36+
usage="USAGE: $0
37+
-h show this help text
38+
-a ALPINE_VER override the default Alpine version
39+
default: ${alpine_ver}
40+
-c CONTAINER override the default container name
41+
default: ${container}
42+
-g GHC_VER override the numeric library GHC is built against; either 'gmp' or 'simple'
43+
default: ${ghc_version}
44+
-i IMAGE override the default image base name
45+
default: ${image}
46+
-n NUMERIC override the numeric library GHC is built against; either 'gmp' or 'simple'
47+
default: ${numeric}
48+
-C CABAL_VER override the default version of 'cabal-install' to build
49+
default: ${cabal_version}
50+
-S STACK_VER override the default version of 'stack' to download and install
51+
default: ${stack_version}
52+
-H HLS_VER override the default version of 'haskell-language-server' to download and install
53+
default: ${hls_version}"
54+
55+
while getopts "a:c:g:i:n:C:S:H:h" opt; do
56+
case ${opt} in
57+
a ) {
58+
alpine_ver="${OPTARG}"
59+
};;
60+
c ) {
61+
container="${OPTARG}"
62+
};;
63+
g ) {
64+
ghc_version="${OPTARG}"
65+
};;
66+
i ) {
67+
image="${OPTARG}"
68+
};;
69+
n ) {
70+
if [ "${OPTARG}" = "gmp" ] || [ "${OPTARG}" = "simple" ]; then
71+
numeric="${OPTARG}"
72+
else
73+
echo "Invalid NUMERIC argument (i.e. '-n')." >&2
74+
echo "Expected either 'gmp' or 'simple', got '${OPTARG}'" >&2
75+
exit 1
76+
fi;
77+
};;
78+
C ) {
79+
cabal_version="${OPTARG}"
80+
};;
81+
S ) {
82+
stack_version="${OPTARG}"
83+
};;
84+
H ) {
85+
hls_version="${OPTARG}"
86+
};;
87+
h ) {
88+
echo "${usage}"
89+
exit 0
90+
};;
91+
\? ) {
92+
echo "${usage}"
93+
exit 1
94+
};;
95+
esac
96+
done
97+
shift $((OPTIND -1))
98+
99+
if [ "$#" -ne 0 ]; then
100+
exit 1
101+
fi
102+
103+
# Add the GHC version and numeric library to container and image names.
104+
container="${container}-${numeric}-${ghc_version}"
105+
image="${image}-${numeric}"
106+
107+
################################################################################
108+
# Container.
109+
################################################################################
110+
111+
# Create the container that will be used to download and/or compile various bits
112+
# of Haskell tooling.
113+
buildah \
114+
--signature-policy=./policy.json \
115+
--name "${container}" \
116+
from --pull "docker.io/library/alpine:${alpine_ver}"
117+
118+
# Install common dependencies.
119+
buildah run "${container}" \
120+
apk add \
121+
binutils-gold \
122+
curl \
123+
gcc \
124+
musl-dev \
125+
ncurses-libs \
126+
xz \
127+
zlib
128+
129+
if [ "${numeric}" = "gmp" ]; then
130+
buildah run "${container}" \
131+
apk add gmp-dev
132+
fi
133+
134+
################################################################################
135+
# Copy `ghcup` (and files) from other containers.
136+
################################################################################
137+
138+
buildah unshare ./common/copy_ghcup.sh "ghcup" "${container}"
139+
buildah unshare ./common/copy_ghcup_bin_dir.sh "ghc-${numeric}:${ghc_version}" "${container}"
140+
141+
# Add `ghcup`'s bin directory to the container's `PATH`.
142+
#
143+
# NOTE: This little bit of indirection is needed to get the container's 'PATH',
144+
# since '$PATH' would be sourced from the host.
145+
cntr_path=$(buildah run "${container}" printenv PATH)
146+
buildah config \
147+
--env PATH="${cntr_path}:/root/.ghcup/bin" \
148+
"${container}"
149+
150+
################################################################################
151+
# Download and install `cabal-install.
152+
#
153+
# TODO: Compile `cabal-install` from source for non-gmp images so that the
154+
# library won't be necessary at all.
155+
#
156+
# This should be easier once `ghcup` re-adds the `ghcup compile cabal`
157+
# subcommand; cf. https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/254
158+
################################################################################
159+
160+
buildah run "${container}" \
161+
ghcup install cabal "${cabal_version}"
162+
163+
################################################################################
164+
# Download and install `stack`.
165+
################################################################################
166+
167+
# Fetch `stack`.
168+
buildah run "${container}" \
169+
wget \
170+
-O "/tmp/stack-${stack_version}.tar.gz" \
171+
"https://github.com/commercialhaskell/stack/releases/download/v${stack_version}/stack-${stack_version}-linux-x86_64-static.tar.gz"
172+
173+
# Copy the checksum validation script into the container...
174+
buildah copy --chmod 111 "${container}" \
175+
./common/validate_checksum.sh \
176+
/tmp/validate_checksum.sh
177+
178+
# ...and verify that the expected and actual actual `stack` checksums match.
179+
buildah run "${container}" \
180+
./tmp/validate_checksum.sh \
181+
"/tmp/stack-${stack_version}.tar.gz" \
182+
"${stack_expected_checksum}"
183+
184+
# Extract the `stack` binary...
185+
buildah run "${container}" \
186+
tar -xvzf "/tmp/stack-${stack_version}.tar.gz" \
187+
--directory "/tmp"
188+
189+
# ...relocate it...
190+
buildah run "${container}" \
191+
mv "/tmp/stack-${stack_version}-linux-x86_64-static/stack" /usr/bin/stack
192+
193+
# ...make it executable...
194+
buildah run "${container}" \
195+
chmod +x /usr/bin/stack
196+
197+
# ...and clean up after ourselves.
198+
buildah run "${container}" rm "/tmp/stack-${stack_version}.tar.gz"
199+
buildah run "${container}" rm -rf "/tmp/stack-${stack_version}-linux-x86_64-static"
200+
buildah run "${container}" rm /tmp/validate_checksum.sh
201+
202+
################################################################################
203+
# Compile the Haskell Language Server (HLS) from source.
204+
################################################################################
205+
206+
# Install HLS-specific dependencies.
207+
buildah run "${container}" \
208+
apk add \
209+
ncurses-dev \
210+
zlib-dev
211+
212+
# NOTE: This is just some arbirary time, but it's fixed here so that the package
213+
# set chosen by `cabal-install` should be consistent.
214+
buildah run "${container}" \
215+
cabal update hackage.haskell.org,2021-10-03T23:05:17Z
216+
217+
# Compile HLS...
218+
buildah run "${container}" \
219+
ghcup compile hls \
220+
--version "${hls_version}" \
221+
--jobs "$(nproc)" \
222+
"${ghc_version}"
223+
224+
# ...and set it as the default version.
225+
buildah run "${container}" \
226+
ghcup set hls "${hls_version}"
227+
228+
# Remove HLS-specific system dependencies...
229+
buildah run "${container}" \
230+
apk del \
231+
ncurses-dev \
232+
zlib-dev
233+
234+
# ...and leftover `cabal-install` build cruft.
235+
buildah run "${container}" \
236+
rm -rf /root/.cabal
237+
238+
################################################################################
239+
# Generate the final image.
240+
################################################################################
241+
242+
buildah \
243+
--signature-policy=./policy.json \
244+
commit --rm "${container}" "${image}:${ghc_version}"

0 commit comments

Comments
 (0)