Skip to content

Commit 8da39c7

Browse files
committed
GH-161367: Add test and buildbottest test subcommands to Platforms/WASI
1 parent 8a5e24a commit 8da39c7

8 files changed

Lines changed: 175 additions & 49 deletions

File tree

‎.github/workflows/reusable-wasi.yml‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,4 @@ jobs:
6464
- name: "Display build info of the host/WASI Python"
6565
run: python3 Platforms/WASI pythoninfo-host
6666
- name: "Test"
67-
run: |
68-
CROSS_BUILD_WASI=$(python3 Platforms/WASI path)
69-
make --directory "${CROSS_BUILD_WASI}" test
67+
run: python3 Platforms/WASI test
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add ``test`` and ``buildbottest`` commands to :file:`Platforms/WASI` for CI
2+
and Buildbot use, respectively.

‎Platforms/WASI/README.md‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,36 @@ python3 Platforms/WASI clean
199199

200200
### Testing
201201

202-
To find out where the WASI build directory is, you can run:
202+
After building, you can run the CI tests with:
203+
204+
```shell
205+
python3 Platforms/WASI test
206+
```
207+
208+
This runs `make test` in the WASI build directory.
209+
210+
After running `gather` or `package`, you can run the buildbot tests against the
211+
distribution with:
212+
213+
```shell
214+
python3 Platforms/WASI buildbottest
215+
```
216+
217+
This uses `make buildbottest` appropriately with the binary for releasing.
218+
219+
To test the contents of the release archive instead of the gathered files, use:
220+
221+
```shell
222+
python3 Platforms/WASI buildbottest --unpack
223+
```
224+
225+
This requires an archive created by `package` or `release`. It deletes the
226+
selected versioned distribution directory inside `dist/`, then restores it
227+
from the matching `.tar.xz` archive before running `make buildbottest`.
228+
The archive and other distributions in `dist/` are left untouched.
229+
230+
You can also tests more directly. To find out where the WASI build directory
231+
is, you can run:
203232

204233
```shell
205234
python3 Platforms/WASI path

‎Platforms/WASI/__main__.py‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"_build",
66
"_package",
77
"_shared",
8+
"_test",
89
]
910

1011
import argparse
@@ -14,6 +15,7 @@
1415
import _build
1516
import _package
1617
import _shared
18+
import _test
1719

1820

1921
def main():
@@ -76,6 +78,15 @@ def main():
7678
release = subcommands.add_parser(
7779
"release", help="Build and package for a release"
7880
)
81+
test = subcommands.add_parser("test", help="Run the CI tests")
82+
buildbottest = subcommands.add_parser(
83+
"buildbottest", help="Run the buildbot tests against the distribution"
84+
)
85+
buildbottest.add_argument(
86+
"--unpack",
87+
action="store_true",
88+
help="Replace the distribution directory with the release archive's contents",
89+
)
7990
path = subcommands.add_parser(
8091
"path", help="Print the path to a build or distribution directory"
8192
)
@@ -100,6 +111,8 @@ def main():
100111
pythoninfo_host,
101112
build_host,
102113
release,
114+
test,
115+
buildbottest,
103116
):
104117
subcommand.add_argument(
105118
"--quiet",
@@ -129,6 +142,13 @@ def main():
129142
dest="clean",
130143
help="Delete any relevant directories before building",
131144
)
145+
for subcommand in build, configure_build, configure_host:
146+
subcommand.add_argument(
147+
"--release",
148+
help="Configure build for release mode",
149+
action="store_true",
150+
default=False,
151+
)
132152
for subcommand in (
133153
build,
134154
configure_build,
@@ -137,7 +157,7 @@ def main():
137157
build_host,
138158
):
139159
subcommand.add_argument(
140-
"args", nargs="*", help="Extra arguments to pass to `configure`"
160+
"_args", nargs="*", help="Extra arguments to pass to `configure`"
141161
)
142162
for subcommand in build, configure_host, build_host, release:
143163
subcommand.add_argument(
@@ -167,6 +187,8 @@ def main():
167187
package,
168188
path,
169189
release,
190+
test,
191+
buildbottest,
170192
):
171193
subcommand.add_argument(
172194
"--host-triple",
@@ -219,14 +241,18 @@ def main():
219241
_package.gather(context)
220242
_package.archive(context)
221243
case "release":
222-
context.args = ["--without-static-libpython"]
244+
context.release = True
223245
_build.clean_contents(context)
224246
_build.configure_build_python(context)
225247
_build.make_build_python(context)
226248
_build.configure_wasi_python(context)
227249
_build.make_wasi_python(context)
228250
_package.gather(context)
229251
_package.archive(context)
252+
case "test":
253+
_test.test(context)
254+
case "buildbottest":
255+
_test.buildbottest(context)
230256
case "path":
231257
paths = {
232258
"build-python": "build_python_path",

‎Platforms/WASI/_build.py‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ def call(command, *, context=None, quiet=False, **kwargs):
144144
def configure_build_python(context, working_dir):
145145
"""Configure the build/host Python."""
146146
configure = [os.path.relpath(context.checkout / "configure", working_dir)]
147-
if context.args:
148-
configure.extend(context.args)
147+
configure.extend(context.configure_args)
149148

150149
call(configure, context=context)
151150

@@ -247,8 +246,7 @@ def configure_wasi_python(context, working_dir):
247246
]
248247
if context.is_debug:
249248
configure.append("--with-pydebug")
250-
if context.args:
251-
configure.extend(context.args)
249+
configure.extend(context.configure_args)
252250
call(
253251
configure,
254252
env=updated_env(env_additions | wasi_sdk_env(context)),

‎Platforms/WASI/_package.py‎

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,18 @@ def wasmtime_script(context):
2626
2727
script_dir=$(CDPATH= cd "$(dirname "$0")" && pwd -P)
2828
root=$(CDPATH= cd "$script_dir/.." && pwd -P)
29-
wasm_file="$root/lib/python{python_version(context)}/lib-wasm/python{python_version(context, debug_ok=True)}.wasm"
29+
wasm_file="$root/lib/python{context.python_version()}/lib-wasm/python{context.python_version(debug_ok=True)}.wasm"
3030
3131
exec wasmtime run \\
3232
--argv0 "$wasm_file" \\
33-
--config "$root/etc/python{python_version(context)}/wasmtime.toml" \\
33+
--config "$root/etc/python{context.python_version()}/wasmtime.toml" \\
3434
--dir "/" \\
3535
"$wasm_file" "$@"
3636
"""
3737

3838

39-
def python_version(context, debug_ok=False):
40-
"""Calculate the M.N part of Python's version.
41-
42-
If *debug_ok* is True, then "d" is appended as appropriate.
43-
"""
44-
details = context.wasi_build_details
45-
major = details["language"]["version_info"]["major"]
46-
minor = details["language"]["version_info"]["minor"]
47-
version = f"{major}.{minor}"
48-
if debug_ok and context.is_debug:
49-
version += "d"
50-
return version
51-
52-
5339
def lib_python(context):
54-
return pathlib.PurePath("lib") / f"python{python_version(context)}"
40+
return pathlib.PurePath("lib") / f"python{context.python_version()}"
5541

5642

5743
def license_file(context):
@@ -101,12 +87,12 @@ def pkgconfig_files(context):
10187
pkgconfig = pathlib.PurePath("lib") / "pkgconfig"
10288
return [
10389
(
104-
pkgconfig / f"python-{python_version(context, debug_ok=True)}.pc",
90+
pkgconfig / f"python-{context.python_version(debug_ok=True)}.pc",
10591
misc_dir / "python.pc",
10692
),
10793
(
10894
pkgconfig
109-
/ f"python-{python_version(context, debug_ok=True)}-embed.pc",
95+
/ f"python-{context.python_version(debug_ok=True)}-embed.pc",
11096
misc_dir / "python-embed.pc",
11197
),
11298
]
@@ -127,11 +113,11 @@ def pkgconfig_symlinks(pkgconfig_files, context):
127113
paths += [
128114
(
129115
embed_path.parent
130-
/ f"python-{python_version(context)}-embed.pc",
116+
/ f"python-{context.python_version()}-embed.pc",
131117
embed_path,
132118
),
133119
(
134-
plain_path.parent / f"python-{python_version(context)}.pc",
120+
plain_path.parent / f"python-{context.python_version()}.pc",
135121
plain_path,
136122
),
137123
]
@@ -143,7 +129,7 @@ def pyconfig_file(context):
143129
"""Have <build>/pyconfig.h end up in include/pythonXYd?/pyconfig.h."""
144130
return (
145131
pathlib.PurePath("include")
146-
/ f"python{python_version(context, debug_ok=True)}"
132+
/ f"python{context.python_version(debug_ok=True)}"
147133
/ "pyconfig.h",
148134
context.wasi_build_path / "pyconfig.h",
149135
)
@@ -158,7 +144,7 @@ def header_files(context):
158144
file_path = pathlib.Path(root) / filename
159145
details = (
160146
pathlib.PurePath("include")
161-
/ f"python{python_version(context, debug_ok=True)}"
147+
/ f"python{context.python_version(debug_ok=True)}"
162148
/ file_path.relative_to(include_dir),
163149
file_path,
164150
)
@@ -171,7 +157,7 @@ def man_file(context):
171157
man_dir = pathlib.PurePath("share", "man", "man1")
172158
man_file = context.checkout / "Misc" / "python.man"
173159
return (
174-
man_dir / f"python{python_version(context)}.1",
160+
man_dir / f"python{context.python_version()}.1",
175161
man_file,
176162
)
177163

@@ -187,7 +173,7 @@ def wasmtime_config_file(context):
187173
config = context.checkout / "Platforms" / "WASI" / "wasmtime.toml"
188174
return (
189175
pathlib.PurePath("etc")
190-
/ f"python{python_version(context)}"
176+
/ f"python{context.python_version()}"
191177
/ "wasmtime.toml",
192178
config,
193179
)
@@ -198,17 +184,15 @@ def wasm_file(context):
198184
return (
199185
lib_python(context)
200186
/ "lib-wasm"
201-
/ f"python{python_version(context, debug_ok=True)}.wasm",
187+
/ f"python{context.python_version(debug_ok=True)}.wasm",
202188
context.wasi_build_path / "python.wasm",
203189
)
204190

205191

206-
def python_wasmtime_script(base, context):
192+
def python_wasmtime_script(context):
207193
"""Create bin/pythonN.Md?.wasmtime."""
208194
script = wasmtime_script(context)
209-
path = (
210-
base / f"bin/python{python_version(context, debug_ok=True)}.wasmtime"
211-
)
195+
path = context.dist_python_interpreter
212196
path.parent.mkdir(parents=True, exist_ok=True)
213197
with open(path, "w") as f:
214198
f.write(script)
@@ -221,15 +205,15 @@ def python_wasmtime_symlink(path, context):
221205
"""Symlink bin/pythonN.Md?.wasmtime.
222206
223207
- bin/pythonN.M.wasmtime (if debug build)
224-
- bin/pythonN.wasmtime (if debug build)
208+
- bin/pythonN.wasmtime
225209
"""
226210
symlinks = [
227211
path.parent / f"python{context.wasi_build_version['major']}.wasmtime"
228212
]
229213
if context.is_debug:
230214
# The file already has the debug name, so the missing symlink is the non-debug name.
231215
symlinks.append(
232-
path.parent / f"python{python_version(context)}.wasmtime"
216+
path.parent / f"python{context.python_version()}.wasmtime"
233217
)
234218

235219
return [(symlink, path) for symlink in symlinks]
@@ -239,7 +223,7 @@ def config_file(context):
239223
"""Have Misc/config.sh end up at bin/pythonN.Md?.config."""
240224
return (
241225
pathlib.PurePath("bin")
242-
/ f"python{python_version(context, debug_ok=True)}-config",
226+
/ f"python{context.python_version(debug_ok=True)}-config",
243227
context.wasi_build_path / "Misc" / "python-config.sh",
244228
)
245229

@@ -258,7 +242,7 @@ def config_symlink(config_path, context):
258242
if context.is_debug:
259243
# The file already has the debug name, so the missing symlink is the non-debug name.
260244
symlinks.append(
261-
config_path.parent / f"python{python_version(context)}-config"
245+
config_path.parent / f"python{context.python_version()}-config"
262246
)
263247

264248
return [(symlink, config_path) for symlink in symlinks]
@@ -281,8 +265,8 @@ def symlink_files(files, base):
281265

282266

283267
def gather(context):
284-
py_version = python_version(context)
285-
py_d_version = python_version(context, debug_ok=True)
268+
py_version = context.python_version()
269+
py_d_version = context.python_version(debug_ok=True)
286270

287271
dist = context.dist_path
288272
if dist.exists():
@@ -300,7 +284,7 @@ def gather(context):
300284
symlink_files(config_symlink(config_location[0], context), base)
301285

302286
_shared.log("📄", f"python{py_d_version}.wasmtime", spacing=indent * 3)
303-
script_path = python_wasmtime_script(base, context)
287+
script_path = python_wasmtime_script(context)
304288
symlink_files(python_wasmtime_symlink(script_path, context), base)
305289

306290
_shared.log("📁", "etc/", spacing=indent * 2)
@@ -353,8 +337,7 @@ def gather(context):
353337

354338

355339
def archive(context):
356-
file_name = f"{context.archive_stem}.tar.xz"
357-
file_path = context.dist_path / file_name
340+
file_path = context.archive_path
358341
if file_path.exists():
359342
_shared.log("🧹", f"Deleting {file_path} ...")
360343
file_path.unlink()

‎Platforms/WASI/_shared.py‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ def wasi_sdk_path(self):
178178

179179
return wasi_sdk_path
180180

181+
@functools.cached_property
182+
def configure_args(self):
183+
args = getattr(self, "_args", [])
184+
if self.release:
185+
args.extend(["--without-static-libpython"])
186+
return args
187+
181188
@functools.cached_property
182189
def log_path(self):
183190
if self._log_path is not None:
@@ -206,6 +213,27 @@ def archive_stem(self):
206213
def archive_dir(self):
207214
return self.dist_path / self.archive_stem
208215

216+
@functools.cached_property
217+
def archive_path(self):
218+
return self.dist_path / f"{self.archive_stem}.tar.xz"
219+
220+
@functools.cached_property
221+
def dist_python_interpreter(self):
222+
version = self.python_version(debug_ok=True)
223+
return self.archive_dir / "bin" / f"python{version}.wasmtime"
224+
225+
def python_version(self, debug_ok=False):
226+
"""Calculate the M.N part of Python's version.
227+
228+
If *debug_ok* is True, then "d" is appended as appropriate.
229+
"""
230+
major = self.wasi_build_version["major"]
231+
minor = self.wasi_build_version["minor"]
232+
version = f"{major}.{minor}"
233+
if debug_ok and "d" in self.wasi_build_details["abi"]["flags"]:
234+
version += "d"
235+
return version
236+
209237

210238
def log(emoji, message, *, spacing=None):
211239
"""Print a notification with an emoji.

0 commit comments

Comments
 (0)