mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
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.
293 lines
10 KiB
Python
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")
|