aboutsummaryrefslogtreecommitdiff
path: root/runtime/build.py
blob: 895ed3956b2d50fb41f2a1cbfdec1f2a3f9a5a43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import argparse
import dataclasses
import os
from pathlib import Path
import subprocess


@dataclasses.dataclass(frozen=True)
class Target:
    name: str
    requires_sizeof_jmp_buf: bool


targets = [
    Target(
        name="amd64",
        requires_sizeof_jmp_buf=True,
    ),
    Target(
        name="i686",
        requires_sizeof_jmp_buf=True,
    ),
    Target(
        name="wasm32",
        requires_sizeof_jmp_buf=False,
    ),
    Target(
        name="wasm64",
        requires_sizeof_jmp_buf=False,
    ),
]


def _find_target_by_name(name: str):
    for target in targets:
        if target.name == name:
            return target

    raise ValueError(f"Unrecognised target: {name}")


gcs = ["bump", "mark-and-sweep"]


def main():
    args = _parse_args()
    args.func(args)


def _main_standard(args):
    for target in targets:
        target_dir = Path(__file__).parent / "target" / target.name

        for gc in gcs:
            output_dir = target_dir / gc
            _build_runtime(
                target=target,
                gc=gc,
                options=[],
                output_dir=output_dir,
            )

        if target.requires_sizeof_jmp_buf:
            sizeof_jmp_buf = subprocess.check_output([target_dir / gcs[0] / "sizeof_jmp_buf"])
            with open(target_dir / "sizeof_jmp_buf.txt", "wb") as fileobj:
                fileobj.write(sizeof_jmp_buf)


def _main_custom(args):
    target = _find_target_by_name(args.target)

    _build_runtime(
        target=target,
        gc=args.gc,
        options=args.options,
        output_dir=Path(args.output_dir),
    )


def _build_runtime(*, target: Target, gc: str, options: list[str], output_dir: Path):
    setup_command = ["meson", "setup", output_dir.absolute(), "--werror", f"-Dgc={gc}", "--wipe"] + [
        f"-D{option}" for option in options
    ]
    if target.name != "amd64":
        setup_command += ["--cross-file", f"{target.name}.meson"]
    subprocess.check_call(setup_command, cwd=Path(__file__).parent)

    subprocess.check_call(["meson", "compile", "--verbose"], cwd=output_dir)


def _parse_args():
    parser = argparse.ArgumentParser()

    subparsers = parser.add_subparsers()

    standard = subparsers.add_parser("standard", help="Build the standard set of runtimes")
    standard.set_defaults(func=_main_standard)

    custom = subparsers.add_parser("custom", help="Build a custom runtime")
    custom.add_argument("--gc", required=True, choices=gcs)
    custom.add_argument("--target", required=True, choices=[target.name for target in targets])
    custom.add_argument("-D", dest="options", nargs="*")
    custom.add_argument("--output-dir", required=True)
    custom.set_defaults(func=_main_custom)

    return parser.parse_args()


if __name__ == "__main__":
    main()