from typing import TextIO, Tuple import json import copy from . import ninja from . import manifests as m from . import targets from . import utils def genNinja(out: TextIO, manifests: dict, target: dict) -> None: target = copy.deepcopy(target) target = targets.patchToolArgs(target, "cc", [m.cincludes(manifests)]) target = targets.patchToolArgs(target, "cxx", [m.cincludes(manifests)]) writer = ninja.Writer(out) writer.comment("Generated by the meta build system") writer.newline() writer.comment("Tools:") for key in target["tools"]: tool = target["tools"][key] writer.variable(key, tool["cmd"]) writer.variable(key + "flags", " ".join(tool["args"])) writer.newline() writer.newline() writer.comment("Rules:") writer.rule( "cc", "$cc -c -o $out $in -MD -MF $out.d $ccflags", depfile="$out.d") writer.rule( "cxx", "$cxx -c -o $out $in -MD -MF $out.d $cxxflags", depfile="$out.d") writer.rule("ld", "$ld -o $out $in $ldflags") writer.rule("ar", "$ar crs $out $in") writer.rule("as", "$as -o $out $in $asflags") writer.newline() writer.comment("Build:") all = [] for key in manifests: item = manifests[key] writer.comment("Project: " + item["id"]) for obj in item["objs"]: if obj[1].endswith(".c"): writer.build( obj[0], "cc", obj[1], order_only=target["tools"]["cc"].get("files", "")) elif obj[1].endswith(".cpp"): writer.build( obj[0], "cxx", obj[1], order_only=target["tools"]["cxx"].get("files", "")) elif obj[1].endswith(".s") or obj[1].endswith(".asm"): writer.build( obj[0], "as", obj[1], order_only=target["tools"]["as"].get("files", "")) writer.newline() objs = [x[0] for x in item["objs"]] if item["type"] == "lib": writer.build(item["out"], "ar", objs, order_only=target["tools"]["ar"].get("files", "")) else: objs = objs + item["libs"] writer.build(item["out"], "ld", objs, order_only=target["tools"]["ld"].get("files", "")) all.append(item["out"]) writer.newline() writer.comment("Phony:") writer.build("all", "phony", all) def prepare(targetId: str) -> Tuple[dict, dict]: target = targets.load(targetId) manifests = m.loadAll("src", target) utils.mkdirP(target["dir"]) genNinja(open(target["ninjafile"], "w"), manifests, target) meta = {} meta["id"] = target["key"] meta["type"] = "artifacts" meta["components"] = manifests meta["target"] = target with open(target["dir"] + "/manifest.json", "w") as f: json.dump(meta, f, indent=4) with open(target["dir"] + "/_key", "w") as f: json.dump(target["key"], f, indent=4) return target, manifests def buildAll(targetId: str) -> None: target, _ = prepare(targetId) print(f"{utils.Colors.BOLD}Building all components for target '{targetId}{utils.Colors.RESET}'") try: utils.runCmd("ninja", "-v", "-j", "1", "-f", target["ninjafile"]) except: raise utils.CliException( "Failed to build all for " + target["key"]) def buildOne(targetId: str, componentId: str) -> str: print(f"{utils.Colors.BOLD}Building {componentId} for target '{targetId}'{utils.Colors.RESET}") target, manifests = prepare(targetId) if not componentId in manifests: raise utils.CliException("Unknown component: " + componentId) try: utils.runCmd("ninja", "-v", "-j", "1", "-f", target["ninjafile"], manifests[componentId]["out"]) except: raise utils.CliException( f"Failed to build {componentId} for target '{target['key']}'") return manifests[componentId]["out"]