[build] Move to python build scripts per module
This change moves Bonnibel from a separate project into the jsix tree, and alters the project configuration to be jsix-specific. (I stopped using bonnibel for any other projects, so it's far easier to make it a custom generator for jsix.) The build system now also uses actual python code in `*.module` files to configure modules instead of TOML files. Target configs (boot, kernel-mode, user-mode) now moved to separate TOML files under `configs/` and can inherit from one another.
This commit is contained in:
177
scripts/bonnibel/project.py
Normal file
177
scripts/bonnibel/project.py
Normal file
@@ -0,0 +1,177 @@
|
||||
from . import BonnibelError
|
||||
|
||||
class Project:
|
||||
def __init__(self, root):
|
||||
from .version import git_version
|
||||
|
||||
self.root = root
|
||||
self.version = git_version(root)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} {self.version.major}.{self.version.minor}.{self.version.patch}-{self.version.sha}"
|
||||
|
||||
def generate(self, root, output, modules, config, manifest):
|
||||
import sys
|
||||
import bonnibel
|
||||
from os.path import join
|
||||
from ninja.ninja_syntax import Writer
|
||||
from .target import Target
|
||||
|
||||
targets = set()
|
||||
for mod in modules.values():
|
||||
targets.update({Target.load(root, t, config) for t in mod.targets})
|
||||
|
||||
with open(output / "build.ninja", "w") as buildfile:
|
||||
build = Writer(buildfile)
|
||||
|
||||
build.comment("This file is automatically generated by bonnibel")
|
||||
build.variable("ninja_required_version", "1.3")
|
||||
build.variable("build_root", output)
|
||||
build.variable("source_root", root)
|
||||
build.newline()
|
||||
|
||||
build.include(root / "configs" / "rules.ninja")
|
||||
build.newline()
|
||||
|
||||
build.variable("version_major", self.version.major)
|
||||
build.variable("version_minor", self.version.minor)
|
||||
build.variable("version_patch", self.version.patch)
|
||||
build.variable("version_sha", self.version.sha)
|
||||
build.newline()
|
||||
|
||||
for target in targets:
|
||||
build.subninja(output / target.name / "target.ninja")
|
||||
build.newline()
|
||||
|
||||
fatroot = output / "fatroot"
|
||||
fatroot.mkdir(exist_ok=True)
|
||||
|
||||
fatroot_content = []
|
||||
for line in open(manifest, 'r'):
|
||||
target, name = line.split(",", 1)
|
||||
target = target.strip()
|
||||
name = name.strip()
|
||||
|
||||
if not name in modules:
|
||||
raise BonnibelError(f"Manifest item '{name}' is not a known module")
|
||||
|
||||
mod = modules[name]
|
||||
fatroot_output = f"${{build_root}}/fatroot/{mod.output}"
|
||||
|
||||
build.build(
|
||||
rule = "strip",
|
||||
outputs = [fatroot_output],
|
||||
inputs = [f"${{build_root}}/{target}/{mod.output}"],
|
||||
variables = {
|
||||
"name": f"Installing {name}",
|
||||
"debug": f"${{build_root}}/{mod.output}.debug",
|
||||
})
|
||||
fatroot_content.append(fatroot_output)
|
||||
build.newline()
|
||||
|
||||
symbol_table = "${build_root}/fatroot/symbol_table.dat"
|
||||
build.build(
|
||||
rule = "makest",
|
||||
outputs = [symbol_table],
|
||||
inputs = ["${build_root}/fatroot/jsix.elf"],
|
||||
)
|
||||
fatroot_content.append(symbol_table)
|
||||
build.newline()
|
||||
|
||||
bootloader = "${build_root}/fatroot/efi/boot/bootx64.efi"
|
||||
build.build(
|
||||
rule = "cp",
|
||||
outputs = [bootloader],
|
||||
inputs = ["${build_root}/boot/boot.efi"],
|
||||
variables = {
|
||||
"name": "Installing bootloader",
|
||||
})
|
||||
fatroot_content.append(bootloader)
|
||||
build.newline()
|
||||
|
||||
build.build(
|
||||
rule = "makefat",
|
||||
outputs = ["${build_root}/jsix.img"],
|
||||
inputs = ["${source_root}/assets/diskbase.img"],
|
||||
implicit = fatroot_content,
|
||||
variables = {"name": "jsix.img"},
|
||||
)
|
||||
build.newline()
|
||||
|
||||
default_assets = {
|
||||
"ovmf/x64/ovmf_vars.fd": "UEFI Variables",
|
||||
"debugging/jsix.elf-gdb.py": "GDB Debug Helpers",
|
||||
}
|
||||
|
||||
for asset, name in default_assets.items():
|
||||
p = root / "assets" / asset
|
||||
out = f"${{build_root}}/{p.name}"
|
||||
build.build(
|
||||
rule = "cp",
|
||||
outputs = [out],
|
||||
inputs = [str(p)],
|
||||
variables = {"name": name},
|
||||
)
|
||||
build.default([out])
|
||||
build.newline()
|
||||
|
||||
build.rule("regen",
|
||||
command = " ".join([str(root / 'configure')] + sys.argv[1:]),
|
||||
description = "Regenerate build files",
|
||||
generator = True,
|
||||
)
|
||||
build.newline()
|
||||
|
||||
regen_implicits = \
|
||||
[f"{self.root}/configure", str(manifest)] + \
|
||||
[str(mod.modfile) for mod in modules.values()]
|
||||
|
||||
for target in targets:
|
||||
regen_implicits += target.depfiles
|
||||
|
||||
build.build(
|
||||
rule = "regen",
|
||||
outputs = ['build.ninja'],
|
||||
implicit = regen_implicits,
|
||||
implicit_outputs =
|
||||
[f"{mod.name}.ninja" for mod in modules.values()] +
|
||||
[f"{target.name}/target.ninja" for target in targets],
|
||||
)
|
||||
|
||||
build.newline()
|
||||
build.default(["${build_root}/jsix.img"])
|
||||
|
||||
for target in targets:
|
||||
mods = [m.name for m in modules.values() if target.name in m.targets]
|
||||
|
||||
targetdir = output / target.name
|
||||
targetdir.mkdir(exist_ok=True)
|
||||
|
||||
buildfilename = str(targetdir / "target.ninja")
|
||||
with open(buildfilename, "w") as buildfile:
|
||||
build = Writer(buildfile)
|
||||
build.comment("This file is automatically generated by bonnibel")
|
||||
build.newline()
|
||||
|
||||
build.variable("target", target.name)
|
||||
build.variable("target_dir", output / target.name)
|
||||
build.newline()
|
||||
|
||||
for name, value in target.items():
|
||||
build.variable(name, value)
|
||||
|
||||
build.newline()
|
||||
for kind in ('defs', 'run'):
|
||||
for lang in ('c', 'cpp'):
|
||||
deffile = str(output / target.name / f"{lang}.{kind}")
|
||||
|
||||
build.build(
|
||||
rule = f"dump_{lang}_{kind}",
|
||||
outputs = [deffile],
|
||||
implicit = [buildfilename],
|
||||
)
|
||||
build.default(deffile)
|
||||
build.newline()
|
||||
|
||||
for mod in mods:
|
||||
build.subninja(f"{mod}.ninja")
|
||||
Reference in New Issue
Block a user