170 lines
4.4 KiB
Python
170 lines
4.4 KiB
Python
import os
|
|
import logging
|
|
from typing import TextIO
|
|
|
|
from . import shell, rules, model, ninja, context
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
def gen(out: TextIO, context: context.Context):
|
|
writer = ninja.Writer(out)
|
|
|
|
target = context.target
|
|
|
|
writer.comment("File generated by the build system, do not edit")
|
|
writer.newline()
|
|
writer.variable("builddir", context.builddir())
|
|
|
|
writer.separator("Tools")
|
|
|
|
writer.variable("cincs", " ".join(map(lambda i: f"-I{i}", context.cincls())))
|
|
|
|
writer.variable("cdefs", " ".join(context.cdefs()))
|
|
|
|
writer.newline()
|
|
|
|
writer.rule("cp", "cp $in $out")
|
|
writer.newline()
|
|
|
|
for i in target.tools:
|
|
tool = target.tools[i]
|
|
rule = rules.rules[i]
|
|
writer.variable(i, tool.cmd)
|
|
writer.variable(i + "flags", " ".join(rule.args + tool.args))
|
|
writer.rule(
|
|
i,
|
|
f"{tool.cmd} {rule.rule.replace('$flags',f'${i}flags')}",
|
|
depfile=rule.deps,
|
|
)
|
|
writer.newline()
|
|
|
|
writer.separator("Components")
|
|
|
|
all: list[str] = []
|
|
|
|
for instance in context.enabledInstances():
|
|
objects = instance.objsfiles()
|
|
assets = instance.resfiles()
|
|
writer.comment(f"Component: {instance.manifest.id}")
|
|
writer.comment(f"Resolved: {', '.join(instance.resolved)}")
|
|
|
|
for obj in objects:
|
|
r = rules.byFileIn(obj[0])
|
|
if r is None:
|
|
raise RuntimeError(f"Unknown rule for file {obj[0]}")
|
|
t = target.tools[r.id]
|
|
writer.build(obj[1], r.id, obj[0], order_only=t.files)
|
|
|
|
for asset in assets:
|
|
writer.build(asset[1], "cp", asset[0])
|
|
|
|
writer.newline()
|
|
|
|
if instance.isLib():
|
|
writer.build(
|
|
instance.outfile(),
|
|
"ar",
|
|
list(map(lambda o: o[1], objects)),
|
|
implicit=list(map(lambda o: o[1], assets)),
|
|
)
|
|
else:
|
|
libraries: list[str] = []
|
|
|
|
for req in instance.resolved:
|
|
reqInstance = context.componentByName(req)
|
|
|
|
if reqInstance is None:
|
|
raise RuntimeError(f"Component {req} not found")
|
|
|
|
if not reqInstance.isLib():
|
|
raise RuntimeError(f"Component {req} is not a library")
|
|
|
|
libraries.append(reqInstance.outfile())
|
|
|
|
writer.build(
|
|
instance.outfile(),
|
|
"ld",
|
|
list(map(lambda o: o[1], objects)) + libraries,
|
|
implicit=list(map(lambda o: o[1], assets)),
|
|
)
|
|
|
|
all.append(instance.outfile())
|
|
|
|
writer.newline()
|
|
|
|
writer.separator("Phony targets")
|
|
|
|
writer.build("all", "phony", all)
|
|
writer.default("all")
|
|
|
|
|
|
def build(
|
|
componentSpec: str, targetSpec: str, props: model.Props = {}
|
|
) -> context.ComponentInstance:
|
|
ctx = context.contextFor(targetSpec, props)
|
|
|
|
shell.mkdir(ctx.builddir())
|
|
ninjaPath = os.path.join(ctx.builddir(), "build.ninja")
|
|
|
|
with open(ninjaPath, "w") as f:
|
|
gen(f, ctx)
|
|
|
|
instance = ctx.componentByName(componentSpec)
|
|
|
|
if instance is None:
|
|
raise RuntimeError(f"Component {componentSpec} not found")
|
|
|
|
if not instance.enabled:
|
|
raise RuntimeError(
|
|
f"Component {componentSpec} is disabled: {instance.disableReason}"
|
|
)
|
|
|
|
shell.exec("ninja", "-f", ninjaPath, instance.outfile())
|
|
|
|
return instance
|
|
|
|
|
|
class Paths:
|
|
bin: str
|
|
lib: str
|
|
obj: str
|
|
|
|
def __init__(self, bin: str, lib: str, obj: str):
|
|
self.bin = bin
|
|
self.lib = lib
|
|
self.obj = obj
|
|
|
|
|
|
def buildAll(targetSpec: str, props: model.Props = {}) -> context.Context:
|
|
ctx = context.contextFor(targetSpec, props)
|
|
|
|
shell.mkdir(ctx.builddir())
|
|
ninjaPath = os.path.join(ctx.builddir(), "build.ninja")
|
|
|
|
with open(ninjaPath, "w") as f:
|
|
gen(f, ctx)
|
|
|
|
shell.exec("ninja", "-v", "-f", ninjaPath)
|
|
|
|
return ctx
|
|
|
|
|
|
def testAll(targetSpec: str):
|
|
ctx = context.contextFor(targetSpec)
|
|
|
|
shell.mkdir(ctx.builddir())
|
|
ninjaPath = os.path.join(ctx.builddir(), "build.ninja")
|
|
|
|
with open(ninjaPath, "w") as f:
|
|
gen(f, ctx)
|
|
|
|
shell.exec("ninja", "-v", "-f", ninjaPath, "all")
|
|
|
|
for instance in ctx.enabledInstances():
|
|
if instance.isLib():
|
|
continue
|
|
|
|
if instance.id().endswith("-tests"):
|
|
print(f"Running {instance.id()}")
|
|
shell.exec(instance.outfile())
|