mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[build] Refactor build options definitions
Split out build definition YAML files to allow different options based on config, target, kind of module, and target/kind combination.
This commit is contained in:
68
scripts/bonnibel/config.py
Normal file
68
scripts/bonnibel/config.py
Normal file
@@ -0,0 +1,68 @@
|
||||
_config_cache = {}
|
||||
|
||||
def _load(filename, depfiles):
|
||||
from . import load_config
|
||||
if not filename in _config_cache:
|
||||
if filename.exists():
|
||||
depfiles.add(filename)
|
||||
data = load_config(filename)
|
||||
_config_cache[filename] = data
|
||||
return _config_cache.get(filename, dict())
|
||||
|
||||
|
||||
def _build_config(chain, depfiles):
|
||||
config = {}
|
||||
for d in [_load(c, depfiles) for c in chain]:
|
||||
for k, v in d.items():
|
||||
if isinstance(v, (list, tuple)):
|
||||
config[k] = config.get(k, list()) + list(v)
|
||||
elif isinstance(v, dict):
|
||||
config[k] = config.get(k, dict())
|
||||
config[k].update(v)
|
||||
else:
|
||||
config[k] = v
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def _make_ninja_config(outfile, config, files):
|
||||
from os import makedirs
|
||||
from ninja.ninja_syntax import Writer
|
||||
|
||||
makedirs(outfile.parent, exist_ok=True)
|
||||
|
||||
with open(outfile, "w") as buildfile:
|
||||
build = Writer(buildfile)
|
||||
build.comment("This file is automatically generated by bonnibel")
|
||||
build.comment("Source config files:")
|
||||
for f in files:
|
||||
build.comment(f" - {f}")
|
||||
|
||||
build.newline()
|
||||
for k, v in config.items():
|
||||
build.variable(k, v)
|
||||
|
||||
|
||||
def generate_configs(root, output, config, targets, kinds):
|
||||
|
||||
assets = root / "assets" / "build"
|
||||
base = ["global.yaml", f"config.{config}.yaml"]
|
||||
|
||||
depfiles = set()
|
||||
|
||||
for target in targets:
|
||||
chain = base + [f"target.{target}.yaml"]
|
||||
|
||||
files = [assets / f for f in chain]
|
||||
config = _build_config(files, depfiles)
|
||||
outfile = output / target / f"config.ninja"
|
||||
_make_ninja_config(outfile, config, files)
|
||||
|
||||
for kind in kinds:
|
||||
custom = [f"kind.{kind}.yaml", f"target.{target}.{kind}.yaml"]
|
||||
files = [assets / f for f in chain + custom]
|
||||
config = _build_config(files, depfiles)
|
||||
outfile = output / target / f"config.{kind}.ninja"
|
||||
_make_ninja_config(outfile, config, files)
|
||||
|
||||
return depfiles
|
||||
@@ -37,6 +37,9 @@ class Manifest:
|
||||
self.drivers = [self.__build_entry(modules, i)
|
||||
for i in config.get("drivers", tuple())]
|
||||
|
||||
self.tools = [self.__build_entry(modules, i)
|
||||
for i in config.get("tools", tuple())]
|
||||
|
||||
self.flags = config.get("flags", tuple())
|
||||
|
||||
self.symbols = ""
|
||||
|
||||
@@ -88,6 +88,8 @@ class Module:
|
||||
|
||||
if self.kind == "lib":
|
||||
return f"lib{self.name}.a"
|
||||
elif self.kind == "driver":
|
||||
return f"{self.name}.drv"
|
||||
else:
|
||||
return f"{self.name}.elf"
|
||||
|
||||
@@ -157,6 +159,11 @@ class Module:
|
||||
build.newline()
|
||||
|
||||
build.variable("module_dir", target_rel(self.name + ".dir"))
|
||||
build.variable("module_kind", self.kind)
|
||||
build.newline()
|
||||
|
||||
build.include(f"${{target_dir}}/config.{self.kind}.ninja")
|
||||
build.newline()
|
||||
|
||||
modopts = BuildOptions(
|
||||
local = [self.root, "${module_dir}"],
|
||||
|
||||
@@ -12,14 +12,17 @@ class Project:
|
||||
|
||||
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()
|
||||
kinds = set()
|
||||
for mod in modules.values():
|
||||
targets.update({Target.load(root, t, config) for t in mod.targets})
|
||||
targets.update(mod.targets)
|
||||
kinds.add(mod.kind)
|
||||
|
||||
from .config import generate_configs
|
||||
config_deps = generate_configs(root, output, config, targets, kinds)
|
||||
|
||||
with open(output / "build.ninja", "w") as buildfile:
|
||||
build = Writer(buildfile)
|
||||
@@ -47,7 +50,7 @@ class Project:
|
||||
build.newline()
|
||||
|
||||
for target in targets:
|
||||
build.subninja(output / target.name / "target.ninja")
|
||||
build.subninja(output / target / "target.ninja")
|
||||
build.newline()
|
||||
|
||||
build.build(
|
||||
@@ -151,6 +154,9 @@ class Project:
|
||||
for program in manifest.drivers:
|
||||
add_initrd_stripped("jsix/drivers", program)
|
||||
|
||||
for program in manifest.tools:
|
||||
add_initrd_stripped("jsix/tools", program)
|
||||
|
||||
syms = manifest.add_data("symbol_table.dat",
|
||||
"Symbol table", ("symbols",))
|
||||
|
||||
@@ -229,8 +235,7 @@ class Project:
|
||||
[f"{self.root}/configure", str(manifest_file)] + \
|
||||
[str(mod.modfile) for mod in modules.values()]
|
||||
|
||||
for target in targets:
|
||||
regen_implicits += target.depfiles
|
||||
regen_implicits += list(map(str, config_deps))
|
||||
|
||||
build.build(
|
||||
rule = "compdb",
|
||||
@@ -246,7 +251,7 @@ class Project:
|
||||
implicit = regen_implicits,
|
||||
implicit_outputs =
|
||||
[f"module.{mod.name}.ninja" for mod in modules.values()] +
|
||||
[f"{target.name}/target.ninja" for target in targets] +
|
||||
[f"{target}/target.ninja" for target in targets] +
|
||||
[boot_config],
|
||||
)
|
||||
|
||||
@@ -254,9 +259,9 @@ class Project:
|
||||
build.default(["${build_root}/jsix.img"])
|
||||
|
||||
for target in targets:
|
||||
mods = [m.name for m in modules.values() if target.name in m.targets]
|
||||
mods = [m.name for m in modules.values() if target in m.targets]
|
||||
|
||||
targetdir = output / target.name
|
||||
targetdir = output / target
|
||||
targetdir.mkdir(exist_ok=True)
|
||||
|
||||
buildfilename = str(targetdir / "target.ninja")
|
||||
@@ -265,17 +270,16 @@ class Project:
|
||||
build.comment("This file is automatically generated by bonnibel")
|
||||
build.newline()
|
||||
|
||||
build.variable("target", target.name)
|
||||
build.variable("target_dir", output / target.name)
|
||||
build.variable("target", target)
|
||||
build.variable("target_dir", output / target)
|
||||
build.newline()
|
||||
|
||||
for name, value in target.items():
|
||||
build.variable(name, value)
|
||||
build.include(f"{target}/config.ninja")
|
||||
|
||||
build.newline()
|
||||
for kind in ('defs', 'run'):
|
||||
for lang in ('c', 'cpp'):
|
||||
deffile = str(output / target.name / f"{lang}.{kind}")
|
||||
deffile = str(output / target / f"{lang}.{kind}")
|
||||
|
||||
build.build(
|
||||
rule = f"dump_{lang}_{kind}",
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
class Target(dict):
|
||||
__targets = {}
|
||||
|
||||
@classmethod
|
||||
def load(cls, root, name, config=None):
|
||||
from . import load_config
|
||||
|
||||
if (name, config) in cls.__targets:
|
||||
return cls.__targets[(name, config)]
|
||||
|
||||
configs = root / "assets/build"
|
||||
|
||||
dicts = []
|
||||
depfiles = []
|
||||
basename = name
|
||||
if config:
|
||||
basename += f"-{config}"
|
||||
|
||||
while basename is not None:
|
||||
filename = str(configs / (basename + ".yaml"))
|
||||
depfiles.append(filename)
|
||||
desc = load_config(filename)
|
||||
basename = desc.get("extends")
|
||||
dicts.append(desc.get("variables", dict()))
|
||||
|
||||
t = Target(name, config, depfiles)
|
||||
for d in reversed(dicts):
|
||||
for k, v in d.items():
|
||||
if isinstance(v, (list, tuple)):
|
||||
t[k] = t.get(k, list()) + list(v)
|
||||
elif isinstance(v, dict):
|
||||
t[k] = t.get(k, dict())
|
||||
t[k].update(v)
|
||||
else:
|
||||
t[k] = v
|
||||
|
||||
cls.__targets[(name, config)] = t
|
||||
return t
|
||||
|
||||
def __init__(self, name, config, depfiles):
|
||||
self.__name = name
|
||||
self.__config = config
|
||||
self.__depfiles = tuple(depfiles)
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.__name, self.__config))
|
||||
|
||||
name = property(lambda self: self.__name)
|
||||
config = property(lambda self: self.__config)
|
||||
depfiles = property(lambda self: self.__depfiles)
|
||||
Reference in New Issue
Block a user