Files
jsix_import/scripts/bonnibel/project.py
Justin C. Miller aba45b9b67 [boot] Go back to loading symbol table in boot
The symbol table needs to be passed to the panic handler very early in
the kernel, loading it in init is far less useful. Return it to the boot
directory and remove it from the initrd.
2023-02-04 00:03:03 -08:00

293 lines
10 KiB
Python

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_file):
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 / "assets/build/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()
build.variable("cogflags", [
"-I", "${source_root}/scripts",
"-D", "definitions_path=${source_root}/definitions",
])
build.newline()
for target in targets:
build.subninja(output / target.name / "target.ninja")
build.newline()
for mod in modules.values():
build.subninja(output / f"headers.{mod.name}.ninja")
build.newline()
build.build(
rule = "touch",
outputs = "${build_root}/.all_headers",
implicit = [f"${{build_root}}/include/{m.name}/.headers.phony"
for m in modules.values() if m.public_headers],
)
build.build(
rule = "phony",
outputs = ["all-headers"],
inputs = ["${build_root}/.all_headers"])
from .manifest import Manifest
manifest = Manifest(manifest_file, modules)
debugroot = output / ".debug"
debugroot.mkdir(exist_ok=True)
fatroot = output / "fatroot"
fatroot.mkdir(exist_ok=True)
(fatroot / manifest.location).mkdir(exist_ok=True)
initrdroot = output / "initrd_root"
initrdroot.mkdir(exist_ok=True)
fatroot_content = []
initrd_content = []
def add_fatroot(source, name):
output = join(manifest.location, name)
fatroot_output = f"${{build_root}}/fatroot/{output}"
build.build(
rule = "cp",
outputs = [fatroot_output],
inputs = [source],
variables = {
"description": f"Installing {output}",
})
fatroot_content.append(fatroot_output)
build.newline()
def add_fatroot_exe(entry):
input_path = f"${{build_root}}/{entry.target}/{entry.output}"
intermediary = f"${{build_root}}/{entry.output}"
build.build(
rule = "strip",
outputs = [intermediary],
inputs = [input_path],
implicit = [f"{input_path}.dump"],
variables = {
"name": f"Stripping {entry.module}",
"debug": f"${{build_root}}/.debug/{entry.output}.debug",
})
add_fatroot(intermediary, entry.output)
def add_initrd_content(root, name):
output = join(root, name)
initrd_output = f"${{build_root}}/initrd_root/{output}"
build.build(
rule = "cp",
outputs = [initrd_output],
inputs = [f"${{build_root}}/{name}"],
variables = {
"description": f"Installing {name}",
})
initrd_content.append(initrd_output)
build.newline()
def add_initrd_stripped(root, entry):
input_path = f"${{build_root}}/{entry.target}/{entry.output}"
intermediary = f"${{build_root}}/{entry.output}"
build.build(
rule = "strip",
outputs = [intermediary],
inputs = [input_path],
implicit = [f"{input_path}.dump"],
variables = {
"name": f"Stripping {entry.module}",
"debug": f"${{build_root}}/.debug/{entry.output}.debug",
})
add_initrd_content(root, entry.output)
add_fatroot_exe(manifest.kernel)
add_fatroot_exe(manifest.init)
for program in manifest.panics:
add_fatroot_exe(program)
for program in manifest.services:
add_initrd_stripped("jsix/services", program)
for program in manifest.drivers:
add_initrd_stripped("jsix/drivers", program)
syms = manifest.add_data("symbol_table.dat",
"Symbol table", ("symbols",))
syms_file = "jsix.symbols"
syms_path = join(manifest.location, syms_file );
syms_out = join(fatroot, syms_path)
build.build(
rule = "makest",
outputs = [syms_out],
inputs = [f"${{build_root}}/kernel/{modules['kernel'].output}"],
)
fatroot_content.append(syms_out)
manifest.symbols = syms_file
bootloader = "${build_root}/fatroot/efi/boot/bootx64.efi"
build.build(
rule = "cp",
outputs = [bootloader],
inputs = ["${build_root}/boot/boot.efi"],
variables = {
"description": "Installing bootloader",
})
build.newline()
boot_config = join(fatroot, "jsix", "boot.conf")
manifest.write_boot_config(boot_config)
initrd = str(fatroot / manifest.location / manifest.initrd["name"])
build.build(
rule = "makeinitrd",
outputs = [initrd],
inputs = [str(initrdroot)],
implicit = initrd_content + ["${source_root}/scripts/mkj6romfs.py"],
variables = {"format": manifest.initrd["format"]},
)
build.newline()
fatroot_content.append(initrd)
build.build(
rule = "makefat",
outputs = ["${build_root}/jsix.img"],
inputs = ["${source_root}/assets/diskbase.img"],
implicit = fatroot_content + [bootloader],
variables = {"name": "jsix.img"},
)
build.newline()
default_assets = {
"UEFI Variables": ("ovmf/x64/ovmf_vars.fd", "ovmf_vars.fd"),
"GDB Debug Helpers": ("debugging/jsix.elf-gdb.py", "jsix.elf-gdb.py"),
}
for name, assets in default_assets.items():
p = root / "assets" / assets[0]
out = f"${{build_root}}/{assets[1]}"
build.build(
rule = "cp",
outputs = [out],
inputs = [str(p)],
variables = {"name": name},
)
build.default([out])
build.newline()
compdb = "${source_root}/compile_commands.json"
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_file)] + \
[str(mod.modfile) for mod in modules.values()]
for target in targets:
regen_implicits += target.depfiles
build.build(
rule = "compdb",
outputs = [compdb],
implicit = regen_implicits,
)
build.default([compdb])
build.newline()
build.build(
rule = "regen",
outputs = ['build.ninja'],
implicit = regen_implicits,
implicit_outputs =
[f"module.{mod.name}.ninja" for mod in modules.values()] +
[f"{target.name}/target.ninja" for target in targets] +
[boot_config],
)
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"module.{mod}.ninja")