Changing bonnibel to respect the --arch flag to configure. This requires some reworking of modules, mostly in the addition of the ModuleList class instead of just a dict of modules.
278 lines
10 KiB
Python
278 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, arch, manifest_file):
|
|
import sys
|
|
from os.path import join
|
|
from ninja.ninja_syntax import Writer
|
|
|
|
from .config import generate_configs
|
|
config_deps = generate_configs(root, output, config, arch, modules.targets, modules.kinds)
|
|
|
|
with open(output / "build.ninja", "w") as buildfile:
|
|
build = Writer(buildfile)
|
|
default_builds = []
|
|
|
|
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.variable("build_config", config)
|
|
build.newline()
|
|
|
|
build.include(root / "assets" / "build" / arch / "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 modules.targets:
|
|
build.subninja(output / target / "target.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.used.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)
|
|
|
|
image_content = {'initrd_root': [], 'fatroot': []}
|
|
|
|
def add_image_content(image, path, name):
|
|
output = join(path, name)
|
|
image_output = f"${{build_root}}/{image}/{output}"
|
|
|
|
build.build(
|
|
rule = "cp",
|
|
outputs = [image_output],
|
|
inputs = [f"${{build_root}}/{name}"],
|
|
variables = {
|
|
"description": f"Installing {name}",
|
|
})
|
|
|
|
image_content[image].append(image_output)
|
|
build.newline()
|
|
|
|
def add_image_content_exe(image, path, 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",
|
|
})
|
|
|
|
build.build(
|
|
rule = "phony",
|
|
outputs = [entry.output],
|
|
inputs = [intermediary])
|
|
|
|
add_image_content(image, path, entry.output)
|
|
|
|
if 'kernel' in modules.used:
|
|
add_image_content_exe("fatroot", manifest.location, manifest.kernel)
|
|
|
|
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'].get_output(static=True)}"],
|
|
)
|
|
image_content['fatroot'].append(syms_out)
|
|
manifest.symbols = syms_file
|
|
|
|
build.newline()
|
|
default_builds.append("${build_root}/jsix.img")
|
|
|
|
def try_add_manifest_module(entry, section, image, path="jsix"):
|
|
if entry.module in modules.used:
|
|
add_image_content_exe(image, path, entry)
|
|
elif entry.module not in modules:
|
|
raise BonnibelError(f'unknown {section} module in manifest: {entry.module}')
|
|
|
|
try_add_manifest_module(manifest.init, "init", "fatroot")
|
|
|
|
for program in manifest.panics:
|
|
try_add_manifest_module(program, "panic", "fatroot")
|
|
|
|
for program in manifest.services:
|
|
try_add_manifest_module(program, "services", "initrd_root", "jsix/services")
|
|
|
|
for program in manifest.drivers:
|
|
try_add_manifest_module(program, "drivers", "initrd_root", "jsix/drivers")
|
|
|
|
for program in manifest.libs:
|
|
try_add_manifest_module(program, "libs", "initrd_root", "jsix/lib")
|
|
|
|
extra_regen_outputs = []
|
|
|
|
if 'boot' in modules.used:
|
|
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)
|
|
extra_regen_outputs.append(boot_config)
|
|
|
|
initrd = str(fatroot / manifest.location / manifest.initrd["name"])
|
|
build.build(
|
|
rule = "makeinitrd",
|
|
outputs = [initrd],
|
|
inputs = [str(initrdroot)],
|
|
implicit = image_content['initrd_root'] + ["${source_root}/scripts/mkj6romfs.py"],
|
|
variables = {"format": manifest.initrd["format"]},
|
|
)
|
|
build.newline()
|
|
|
|
image_content['fatroot'].append(initrd)
|
|
|
|
build.build(
|
|
rule = "makefat",
|
|
outputs = ["${build_root}/jsix.img"],
|
|
inputs = ["${source_root}/assets/diskbase.img"],
|
|
implicit = image_content['fatroot'] + [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.newline()
|
|
default_builds.append(out)
|
|
|
|
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.used.values()]
|
|
|
|
regen_implicits += list(map(str, config_deps))
|
|
|
|
build.build(
|
|
rule = "compdb",
|
|
outputs = [compdb],
|
|
implicit = regen_implicits,
|
|
)
|
|
build.newline()
|
|
default_builds.append(compdb)
|
|
|
|
build.build(
|
|
rule = "regen",
|
|
outputs = ['build.ninja'],
|
|
implicit = regen_implicits,
|
|
implicit_outputs =
|
|
[f"module.{mod.name}.ninja" for mod in modules.used.values()] +
|
|
[f"{target}/target.ninja" for target in modules.targets] +
|
|
extra_regen_outputs,
|
|
)
|
|
|
|
build.newline()
|
|
build.default(default_builds)
|
|
|
|
for target in modules.targets:
|
|
mods = modules.target_mods(target)
|
|
|
|
targetdir = output / target
|
|
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)
|
|
build.variable("target_dir", output / target)
|
|
build.newline()
|
|
|
|
build.include(f"{target}/config.ninja")
|
|
|
|
build.newline()
|
|
for kind in ('defs', 'run'):
|
|
for lang in ('c', 'cpp'):
|
|
deffile = str(output / target / 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.name}.ninja")
|