Skip to content

Commit 7483928

Browse files
committed
Bump setup-ghc-wasm.py
1 parent cbd44b1 commit 7483928

File tree

1 file changed

+56
-18
lines changed

1 file changed

+56
-18
lines changed

setup-ghc-wasm.py

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
import subprocess
33
import shlex
44
from shlex import quote
5-
from shutil import which
5+
from shutil import Error, which
66
import sys
77
import json
88
from collections import namedtuple
99
from functools import partial
1010

11+
# This script is a manual translation of ghc-wasm-meta's setup.sh.
12+
# The snapshot of this script is based on is at (accessed around May 2025):
13+
# https://gitlab.haskell.org/haskell-wasm/ghc-wasm-meta/-/blob/fe5573f28327d12a1c47ec61d6bbe0cc9d7983dd/setup.sh
1114

15+
# TODO: sed
1216
for cmd in ['curl', 'unzip', 'tar', 'xz']:
1317
if which(cmd) is None:
1418
print(f'This script requires {cmd}')
@@ -17,30 +21,52 @@
1721
print_err = partial(print, file=sys.stderr)
1822
HostVars = namedtuple('HostVars', 'HOST WASI_SDK WASI_SDK_JOB_NAME WASI_SDK_ARTIFACT_PATH WASMTIME NODEJS CABAL BINARYEN GHC FLAVOUR')
1923

20-
def run_cmd(arg, **kwargs):
21-
is_shell = isinstance(arg, str)
24+
REPO = os.environ['PWD']
25+
26+
def _log_cmd(is_shell, arg, **kwargs):
2227
if is_shell:
2328
print_err('+', arg, kwargs)
2429
else:
2530
print_err('+', shlex.join(arg), kwargs)
31+
32+
def run_cmd(arg, **kwargs):
33+
is_shell = isinstance(arg, str)
34+
_log_cmd(arg, **kwargs)
2635
return subprocess.check_output(
2736
arg, **kwargs, shell=is_shell, universal_newlines=True
2837
).strip()
2938

39+
def run_cmd_and_get_exit_code(arg, **kwargs):
40+
is_shell = isinstance(arg, str)
41+
_log_cmd(is_shell, arg, **kwargs)
42+
return subprocess.run(
43+
arg, **kwargs, shell=is_shell, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
44+
).returncode
45+
3046
def jq_autogen(name):
3147
# cmd = f'''jq -r '."{name}".url' {REPO}/autogen.json'''
3248
# return run_cmd(cmd)
3349
with open(f'{REPO}/autogen.json') as f:
3450
data = json.load(f)
3551
return data[name]['url']
3652

53+
# TODO: remove pipe_to to mandate all output to be saved
3754
def run_curl(url, dest, *, pipe_to=None, **kwargs):
3855
cmd = f'curl -f -L --retry 5 {quote(url)}'
3956
tail = '-o %s'
4057
if pipe_to is not None:
4158
tail = '| ' + pipe_to
4259
return run_cmd(cmd + ' ' + (tail % quote(dest)), **kwargs)
4360

61+
def curl_upstream_wasi_sdk_pipeline_id(upstreamWasiSdkPipelineId, targetJobName):
62+
url = f'https://gitlab.haskell.org/api/v4/projects/3212/pipelines/{upstreamWasiSdkPipelineId}/jobs?scope[]=success'
63+
output = run_cmd(f'curl {quote(url)}')
64+
jobs = json.loads(output)
65+
for job in jobs:
66+
if job['name'] == targetJobName:
67+
return job['id']
68+
raise Error(f'Cannot find the job with name "{targetJobName}" from the upstream WASI SDK pipeline.')
69+
4470
def path_is_fresh(s):
4571
if os.path.exists(s):
4672
print(f'Found "{s}", skip downloading...')
@@ -52,7 +78,6 @@ def path_is_fresh(s):
5278
ARCH = run_cmd('uname -m')
5379
PREFIX = os.environ.get('PREFIX', run_cmd('realpath ' + quote(os.path.expandvars('$HOME/.ghc-wasm'))))
5480
WASI_SDK_ROOT = f'{PREFIX}/wasi-sdk'
55-
REPO = os.environ['PWD']
5681

5782
wasm_ghc_prefix = f'{PREFIX}/wasm32-wasi-ghc'
5883
cabal_prefix = f'{PREFIX}/wasm32-wasi-cabal'
@@ -67,7 +92,7 @@ def host_specific():
6792
'x86_64-linux',
6893
'wasi-sdk',
6994
'x86_64-linux',
70-
'dist/wasi-sdk-25.0-x86_64-linux.tar.gz',
95+
'dist/wasi-sdk-26.0-x86_64-linux.tar.gz',
7196
'wasmtime',
7297
'nodejs',
7398
'cabal',
@@ -83,7 +108,7 @@ def host_specific():
83108
'aarch64-linux',
84109
'wasi-sdk-aarch64-linux',
85110
'aarch64-linux',
86-
'dist/wasi-sdk-25.0-aarch64-linux.tar.gz',
111+
'dist/wasi-sdk-26.0-aarch64-linux.tar.gz',
87112
'wasmtime_aarch64_linux',
88113
'nodejs_aarch64_linux',
89114
'cabal_aarch64_linux',
@@ -99,7 +124,7 @@ def host_specific():
99124
'aarch64-apple-darwin',
100125
'wasi-sdk-aarch64-darwin',
101126
'aarch64-darwin',
102-
'dist/wasi-sdk-25.0-arm64-macos.tar.gz',
127+
'dist/wasi-sdk-26.0-arm64-macos.tar.gz',
103128
'wasmtime_aarch64_darwin',
104129
'nodejs_aarch64_darwin',
105130
'cabal_aarch64_darwin',
@@ -114,27 +139,40 @@ def host_specific():
114139
'x86_64-apple-darwin',
115140
'wasi-sdk-x86_64-darwin',
116141
'x86_64-darwin',
117-
'dist/wasi-sdk-25.0-arm64-macos.tar.gz',
142+
'dist/wasi-sdk-26.0-arm64-macos.tar.gz',
118143
'wasmtime_x86_64_darwin',
119144
'nodejs_x86_64_darwin',
120145
'cabal_x86_64_darwin',
121146
'binaryen_x86_64_darwin',
122-
'wasm32-wasi-ghc-gmp-x86_64-darwin',
147+
'wasm32-wasi-ghc-gmp-x86_64-darwin', # no prebuilt ghc available
123148
'gmp')
124149

125150
print(f'Host not supported: ({OS}, {ARCH}, {flavour})')
126151
sys.exit(1)
127152

128153

129154
HOST_VARS = host_specific()
155+
# unused; to be used in wasm-run's setup
156+
# BSD sed does not accept long options such as "--version".
157+
# SED_IS_GNU = run_cmd_and_get_exit_code('sed --version') == 0
130158
GHC_TMP_DIR = f'{REPO}/ghc.{HOST_VARS.FLAVOUR}'
131159

160+
# TODO: workdir; currently it unzips everything to the project dir and also use them to
161+
# avoid redownloading, but it may cause problems on readonly filesystems.
162+
# Since we do not have popd
163+
164+
def determine_wasi_sdk_bindist():
165+
UPSTREAM_WASI_SDK_PIPELINE_ID = os.environ.get('UPSTREAM_WASI_SDK_PIPELINE_ID', None)
166+
if UPSTREAM_WASI_SDK_PIPELINE_ID is not None:
167+
jobId = curl_upstream_wasi_sdk_pipeline_id(UPSTREAM_WASI_SDK_PIPELINE_ID, HOST_VARS.WASI_SDK_JOB_NAME)
168+
return f'https://gitlab.haskell.org/haskell-wasm/wasi-sdk/-/jobs/{jobId}/artifacts/raw/{HOST_VARS.WASI_SDK_ARTIFACT_PATH}'
169+
else:
170+
return jq_autogen(HOST_VARS.WASI_SDK)
132171

133172
def setup_wasi_sdk():
134173
print('--- Setting up WASI SDK ---')
135174
if path_is_fresh(WASI_SDK_ROOT):
136-
# TODO: support specifying UPSTREAM_WASI_SDK_JOB_ID
137-
wasi_sdk_bindist = jq_autogen(HOST_VARS.WASI_SDK)
175+
wasi_sdk_bindist = determine_wasi_sdk_bindist()
138176
print(f'Installing wasi-sdk from {wasi_sdk_bindist}')
139177
run_cmd(['mkdir', '-p', WASI_SDK_ROOT])
140178
run_curl(wasi_sdk_bindist, WASI_SDK_ROOT, pipe_to='tar xz -C %s --no-same-owner --strip-components=1')
@@ -159,10 +197,7 @@ def setup_wasi_sdk():
159197
run_cmd(['cp', 'binaryen/bin/wasm-opt', f'{WASI_SDK_ROOT}/bin'])
160198

161199
# utilities are NOT included, please install them by yourself:
162-
# nodejs, wabt, wasmtime
163-
164-
def setup_proot():
165-
pass
200+
# nodejs, playwright, wabt, wasmtime
166201

167202
def setup_wasm_run():
168203
pass
@@ -172,8 +207,8 @@ def write_to_github_script():
172207
pass
173208

174209
# should sync with setup.sh
175-
cc_opts = '-Wno-error=int-conversion -O3 -msimd128 -mnontrapping-fptoint -msign-ext -mbulk-memory -mmutable-globals -mmultivalue -mreference-types'
176-
cxx_opts = '-fno-exceptions -Wno-error=int-conversion -O3 -msimd128 -mnontrapping-fptoint -msign-ext -mbulk-memory -mmutable-globals -mmultivalue -mreference-types'
210+
cc_opts = '-Wno-error=int-conversion -O3 -mcpu=lime1 -mreference-types -msimd128 -mtail-call'
211+
cxx_opts = '-fno-exceptions -Wno-error=int-conversion -O3 -mcpu=lime1 -mreference-types -msimd128 -mtail-call'
177212
ld_opts = '-Wl,--error-limit=0,--keep-section=ghc_wasm_jsffi,--keep-section=target_features,--stack-first,--strip-debug '
178213

179214
_EXTRA_ENVS = {
@@ -185,6 +220,7 @@ def write_to_github_script():
185220
'CONF_GCC_LINKER_OPTS_STAGE1': ld_opts,
186221
# 'CONFIGURE_ARGS': "",
187222
# 'CROSS_EMULATOR': f'{PREFIX}/wasm-run/bin/wasm-run.mjs',
223+
# 'NODE_PATH': f'{PREFIX}/nodejs/lib/node_modules'
188224
}
189225

190226
# --prefix is defined part of the configure command
@@ -270,8 +306,9 @@ def install_ghc():
270306
run_cmd(
271307
f'. {quote(envpath)} && truncate -s0 ghc.log && ' +
272308
f'./configure {configure_args} --prefix={quote(wasm_ghc_prefix)} | tee ghc.log && ' +
273-
f'exec make install | tee ghc.log',
309+
f'RelocatableBuild=YES exec make install | tee ghc.log',
274310
cwd=GHC_TMP_DIR)
311+
# TODO: wasm32-wasi-ghc-pkg recache
275312

276313
def setup_cabal():
277314
print('--- Downloading cabal ---')
@@ -293,6 +330,7 @@ def setup_cabal():
293330

294331
with open(wasm_cabal, 'w') as f:
295332
f.write('#!/bin/sh\n')
333+
# echo 'PREFIX=$(realpath "$(dirname "$0")"/../..)'
296334

297335
wasm_ghc = f'{wasm_ghc_prefix}/bin/wasm32-wasi-ghc'
298336
wasm_hcpkg = f'{wasm_ghc_prefix}/bin/wasm32-wasi-ghc-pkg'

0 commit comments

Comments
 (0)