Properly propagate props from the command line + Some code cleanup.
This commit is contained in:
parent
6dd4a49043
commit
81f10de24e
|
@ -27,14 +27,14 @@ def setupLogger(verbose: bool):
|
|||
level=logging.INFO,
|
||||
filename=logFile,
|
||||
filemode="w",
|
||||
format=f"%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||||
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
)
|
||||
|
||||
def main() -> int:
|
||||
try:
|
||||
a = parse(sys.argv[1:])
|
||||
setupLogger(a.consumeOpt("verbose", False) == True)
|
||||
setupLogger(a.consumeOpt("verbose", False) is True)
|
||||
plugins.loadAll()
|
||||
cmds.exec(a)
|
||||
print()
|
||||
|
@ -47,4 +47,4 @@ def main() -> int:
|
|||
return 1
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
return 1
|
||||
return 1
|
||||
|
|
|
@ -14,9 +14,10 @@ class Args:
|
|||
|
||||
def consumePrefix(self, prefix: str) -> dict[str, Value]:
|
||||
result: dict[str, Value] = {}
|
||||
for key, value in self.opts.items():
|
||||
copy = self.opts.copy()
|
||||
for key, value in copy.items():
|
||||
if key.startswith(prefix):
|
||||
result[key[len(prefix):]] = value
|
||||
result[key[len(prefix) :]] = value
|
||||
del self.opts[key]
|
||||
return result
|
||||
|
||||
|
|
|
@ -21,8 +21,7 @@ def gen(out: TextIO, context: Context):
|
|||
|
||||
writer.separator("Tools")
|
||||
|
||||
writer.variable("cincs", " ".join(
|
||||
map(lambda i: f"-I{i}", context.cincls())))
|
||||
writer.variable("cincs", " ".join(map(lambda i: f"-I{i}", context.cincls())))
|
||||
|
||||
writer.variable("cdefs", " ".join(context.cdefs()))
|
||||
|
||||
|
@ -35,10 +34,12 @@ def gen(out: TextIO, context: Context):
|
|||
tool = target.tools[i]
|
||||
rule = rules.rules[i]
|
||||
writer.variable(i, tool.cmd)
|
||||
writer.variable(
|
||||
i + "flags", " ".join(rule.args + tool.args))
|
||||
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)
|
||||
i,
|
||||
f"{tool.cmd} {rule.rule.replace('$flags',f'${i}flags')}",
|
||||
depfile=rule.deps,
|
||||
)
|
||||
writer.newline()
|
||||
|
||||
writer.separator("Components")
|
||||
|
@ -56,7 +57,7 @@ def gen(out: TextIO, context: Context):
|
|||
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)
|
||||
writer.build(obj[1], r.id, obj[0], order_only=t.files)
|
||||
|
||||
for asset in assets:
|
||||
writer.build(asset[1], "cp", asset[0])
|
||||
|
@ -64,8 +65,12 @@ def gen(out: TextIO, context: Context):
|
|||
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)))
|
||||
writer.build(
|
||||
instance.outfile(),
|
||||
"ar",
|
||||
list(map(lambda o: o[1], objects)),
|
||||
implicit=list(map(lambda o: o[1], assets)),
|
||||
)
|
||||
else:
|
||||
libraries: list[str] = []
|
||||
|
||||
|
@ -80,8 +85,12 @@ def gen(out: TextIO, context: Context):
|
|||
|
||||
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)))
|
||||
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())
|
||||
|
||||
|
@ -109,9 +118,10 @@ def build(componentSpec: str, targetSpec: str, props: Props = {}) -> ComponentIn
|
|||
|
||||
if not instance.enabled:
|
||||
raise RuntimeError(
|
||||
f"Component {componentSpec} is disabled: {instance.disableReason}")
|
||||
f"Component {componentSpec} is disabled: {instance.disableReason}"
|
||||
)
|
||||
|
||||
shell.exec(f"ninja", "-f", ninjaPath, instance.outfile())
|
||||
shell.exec("ninja", "-f", ninjaPath, instance.outfile())
|
||||
|
||||
return instance
|
||||
|
||||
|
@ -127,8 +137,8 @@ class Paths:
|
|||
self.obj = obj
|
||||
|
||||
|
||||
def buildAll(targetSpec: str) -> Context:
|
||||
context = contextFor(targetSpec)
|
||||
def buildAll(targetSpec: str, props: Props = {}) -> Context:
|
||||
context = contextFor(targetSpec, props)
|
||||
|
||||
shell.mkdir(context.builddir())
|
||||
ninjaPath = os.path.join(context.builddir(), "build.ninja")
|
||||
|
@ -136,7 +146,7 @@ def buildAll(targetSpec: str) -> Context:
|
|||
with open(ninjaPath, "w") as f:
|
||||
gen(f, context)
|
||||
|
||||
shell.exec(f"ninja", "-v", "-f", ninjaPath)
|
||||
shell.exec("ninja", "-v", "-f", ninjaPath)
|
||||
|
||||
return context
|
||||
|
||||
|
@ -150,7 +160,7 @@ def testAll(targetSpec: str):
|
|||
with open(ninjaPath, "w") as f:
|
||||
gen(f, context)
|
||||
|
||||
shell.exec(f"ninja", "-v", "-f", ninjaPath, "all")
|
||||
shell.exec("ninja", "-v", "-f", ninjaPath, "all")
|
||||
|
||||
for instance in context.enabledInstances():
|
||||
if instance.isLib():
|
||||
|
|
|
@ -22,7 +22,13 @@ class Cmd:
|
|||
callback: Callable[[Args], NoReturn]
|
||||
isPlugin: bool = False
|
||||
|
||||
def __init__(self, shortName: Optional[str], longName: str, helpText: str, callback: Callable[[Args], NoReturn]):
|
||||
def __init__(
|
||||
self,
|
||||
shortName: Optional[str],
|
||||
longName: str,
|
||||
helpText: str,
|
||||
callback: Callable[[Args], NoReturn],
|
||||
):
|
||||
self.shortName = shortName
|
||||
self.longName = longName
|
||||
self.helpText = helpText
|
||||
|
@ -41,15 +47,15 @@ def append(cmd: Cmd):
|
|||
def runCmd(args: Args):
|
||||
project.chdir()
|
||||
|
||||
targetSpec = cast(str, args.consumeOpt(
|
||||
"target", "host-" + shell.uname().machine))
|
||||
targetSpec = cast(str, args.consumeOpt("target", "host-" + shell.uname().machine))
|
||||
props = args.consumePrefix("prop:")
|
||||
|
||||
componentSpec = args.consumeArg()
|
||||
|
||||
if componentSpec is None:
|
||||
raise RuntimeError("Component not specified")
|
||||
|
||||
component = builder.build(componentSpec, targetSpec)
|
||||
component = builder.build(componentSpec, targetSpec, props)
|
||||
|
||||
os.environ["CK_TARGET"] = component.context.target.id
|
||||
os.environ["CK_COMPONENT"] = component.id()
|
||||
|
@ -64,8 +70,7 @@ cmds += [Cmd("r", "run", "Run the target", runCmd)]
|
|||
def testCmd(args: Args):
|
||||
project.chdir()
|
||||
|
||||
targetSpec = cast(str, args.consumeOpt(
|
||||
"target", "host-" + shell.uname().machine))
|
||||
targetSpec = cast(str, args.consumeOpt("target", "host-" + shell.uname().machine))
|
||||
builder.testAll(targetSpec)
|
||||
|
||||
|
||||
|
@ -75,15 +80,15 @@ cmds += [Cmd("t", "test", "Run all test targets", testCmd)]
|
|||
def debugCmd(args: Args):
|
||||
project.chdir()
|
||||
|
||||
targetSpec = cast(str, args.consumeOpt(
|
||||
"target", "host-" + shell.uname().machine))
|
||||
targetSpec = cast(str, args.consumeOpt("target", "host-" + shell.uname().machine))
|
||||
props = args.consumePrefix("prop:")
|
||||
|
||||
componentSpec = args.consumeArg()
|
||||
|
||||
if componentSpec is None:
|
||||
raise RuntimeError("Component not specified")
|
||||
|
||||
component = builder.build(componentSpec, targetSpec)
|
||||
component = builder.build(componentSpec, targetSpec, props)
|
||||
|
||||
os.environ["CK_TARGET"] = component.context.target.id
|
||||
os.environ["CK_COMPONENT"] = component.id()
|
||||
|
@ -98,15 +103,14 @@ cmds += [Cmd("d", "debug", "Debug the target", debugCmd)]
|
|||
def buildCmd(args: Args):
|
||||
project.chdir()
|
||||
|
||||
targetSpec = cast(str, args.consumeOpt(
|
||||
"target", "host-" + shell.uname().machine))
|
||||
|
||||
targetSpec = cast(str, args.consumeOpt("target", "host-" + shell.uname().machine))
|
||||
props = args.consumePrefix("prop:")
|
||||
componentSpec = args.consumeArg()
|
||||
|
||||
if componentSpec is None:
|
||||
builder.buildAll(targetSpec)
|
||||
builder.buildAll(targetSpec, props)
|
||||
else:
|
||||
builder.build(componentSpec, targetSpec)
|
||||
builder.build(componentSpec, targetSpec, props)
|
||||
|
||||
|
||||
cmds += [Cmd("b", "build", "Build the target", buildCmd)]
|
||||
|
@ -120,16 +124,15 @@ def listCmd(args: Args):
|
|||
|
||||
vt100.title("Components")
|
||||
if len(components) == 0:
|
||||
print(f" (No components available)")
|
||||
print(" (No components available)")
|
||||
else:
|
||||
print(vt100.indent(vt100.wordwrap(
|
||||
", ".join(map(lambda m: m.id, components)))))
|
||||
print(vt100.indent(vt100.wordwrap(", ".join(map(lambda m: m.id, components)))))
|
||||
print()
|
||||
|
||||
vt100.title("Targets")
|
||||
|
||||
if len(targets) == 0:
|
||||
print(f" (No targets available)")
|
||||
print(" (No targets available)")
|
||||
else:
|
||||
print(vt100.indent(vt100.wordwrap(", ".join(map(lambda m: m.id, targets)))))
|
||||
|
||||
|
@ -171,11 +174,12 @@ def helpCmd(args: Args):
|
|||
pluginText = f"{vt100.CYAN}(plugin){vt100.RESET}"
|
||||
|
||||
print(
|
||||
f" {vt100.GREEN}{cmd.shortName or ' '}{vt100.RESET} {cmd.longName} - {cmd.helpText} {pluginText}")
|
||||
f" {vt100.GREEN}{cmd.shortName or ' '}{vt100.RESET} {cmd.longName} - {cmd.helpText} {pluginText}"
|
||||
)
|
||||
|
||||
print()
|
||||
vt100.title("Logging")
|
||||
print(f" Logs are stored in:")
|
||||
print(" Logs are stored in:")
|
||||
print(f" - {const.PROJECT_LOG_FILE}")
|
||||
print(f" - {const.GLOBAL_LOG_FILE}")
|
||||
|
||||
|
@ -193,17 +197,15 @@ cmds += [Cmd("v", "version", "Show current version", versionCmd)]
|
|||
def graphCmd(args: Args):
|
||||
project.chdir()
|
||||
|
||||
targetSpec = cast(str, args.consumeOpt(
|
||||
"target", "host-" + shell.uname().machine))
|
||||
targetSpec = cast(str, args.consumeOpt("target", "host-" + shell.uname().machine))
|
||||
|
||||
scope: Optional[str] = cast(Optional[str], args.tryConsumeOpt("scope"))
|
||||
onlyLibs: bool = args.consumeOpt("only-libs", False) == True
|
||||
showDisabled: bool = args.consumeOpt("show-disabled", False) == True
|
||||
onlyLibs: bool = args.consumeOpt("only-libs", False) is True
|
||||
showDisabled: bool = args.consumeOpt("show-disabled", False) is True
|
||||
|
||||
context = contextFor(targetSpec)
|
||||
|
||||
graph.view(context, scope=scope, showExe=not onlyLibs,
|
||||
showDisabled=showDisabled)
|
||||
graph.view(context, scope=scope, showExe=not onlyLibs, showDisabled=showDisabled)
|
||||
|
||||
|
||||
cmds += [Cmd("g", "graph", "Show dependency graph", graphCmd)]
|
||||
|
@ -218,8 +220,9 @@ def grabExtern(extern: dict[str, Extern]):
|
|||
continue
|
||||
|
||||
print(f"Installing {extSpec}-{ext.tag} from {ext.git}...")
|
||||
shell.popen("git", "clone", "--depth", "1", "--branch",
|
||||
ext.tag, ext.git, extPath)
|
||||
shell.popen(
|
||||
"git", "clone", "--depth", "1", "--branch", ext.tag, ext.git, extPath
|
||||
)
|
||||
|
||||
if os.path.exists(os.path.join(extPath, "project.json")):
|
||||
grabExtern(context.loadProject(extPath).extern)
|
||||
|
@ -238,31 +241,33 @@ cmds += [Cmd("i", "install", "Install all the external packages", installCmd)]
|
|||
def initCmd(args: Args):
|
||||
import requests
|
||||
|
||||
repo = args.consumeOpt('repo', const.DEFAULT_REPO_TEMPLATES)
|
||||
list = args.consumeOpt('list')
|
||||
repo = args.consumeOpt("repo", const.DEFAULT_REPO_TEMPLATES)
|
||||
list = args.consumeOpt("list")
|
||||
|
||||
template = args.consumeArg()
|
||||
name = args.consumeArg()
|
||||
|
||||
logger.info("Fetching registry...")
|
||||
r = requests.get(
|
||||
f'https://raw.githubusercontent.com/{repo}/main/registry.json')
|
||||
r = requests.get(f"https://raw.githubusercontent.com/{repo}/main/registry.json")
|
||||
|
||||
if r.status_code != 200:
|
||||
logger.error('Failed to fetch registry')
|
||||
logger.error("Failed to fetch registry")
|
||||
exit(1)
|
||||
|
||||
registry = r.json()
|
||||
|
||||
if list:
|
||||
print('\n'.join(
|
||||
f"* {entry['id']} - {entry['description']}" for entry in registry))
|
||||
print(
|
||||
"\n".join(f"* {entry['id']} - {entry['description']}" for entry in registry)
|
||||
)
|
||||
return
|
||||
|
||||
if not template:
|
||||
raise RuntimeError('Template not specified')
|
||||
raise RuntimeError("Template not specified")
|
||||
|
||||
def template_match(t: Json) -> str:
|
||||
return t["id"] == template
|
||||
|
||||
template_match: Callable[[Json], str] = lambda t: t['id'] == template
|
||||
if not any(filter(template_match, registry)):
|
||||
raise LookupError(f"Couldn't find a template named {template}")
|
||||
|
||||
|
@ -279,9 +284,12 @@ def initCmd(args: Args):
|
|||
|
||||
print("We suggest that you begin by typing:")
|
||||
print(f" {vt100.GREEN}cd {name}{vt100.RESET}")
|
||||
print(f" {vt100.GREEN}cutekit install{vt100.BRIGHT_BLACK} # Install external packages{vt100.RESET}")
|
||||
print(
|
||||
f" {vt100.GREEN}cutekit build{vt100.BRIGHT_BLACK} # Build the project{vt100.RESET}")
|
||||
f" {vt100.GREEN}cutekit install{vt100.BRIGHT_BLACK} # Install external packages{vt100.RESET}"
|
||||
)
|
||||
print(
|
||||
f" {vt100.GREEN}cutekit build{vt100.BRIGHT_BLACK} # Build the project{vt100.RESET}"
|
||||
)
|
||||
|
||||
|
||||
cmds += [Cmd("I", "init", "Initialize a new project", initCmd)]
|
||||
|
|
|
@ -21,13 +21,13 @@ UNSUPORTED_MANIFEST = {
|
|||
|
||||
|
||||
def ensureSupportedManifest(manifest: Any, path: str):
|
||||
if not "$schema" in manifest:
|
||||
if "$schema" not in manifest:
|
||||
raise RuntimeError(f"Missing $schema in {path}")
|
||||
|
||||
if manifest["$schema"] in UNSUPORTED_MANIFEST:
|
||||
raise RuntimeError(
|
||||
f"Unsupported manifest schema {manifest['$schema']} in {path}: {UNSUPORTED_MANIFEST[manifest['$schema']]}")
|
||||
|
||||
if not manifest["$schema"] in SUPPORTED_MANIFEST:
|
||||
if manifest["$schema"] not in SUPPORTED_MANIFEST:
|
||||
raise RuntimeError(
|
||||
f"Unsupported manifest schema {manifest['$schema']} in {path}")
|
||||
|
|
|
@ -11,7 +11,7 @@ BUILD_DIR = os.path.join(PROJECT_CK_DIR, "build")
|
|||
CACHE_DIR = os.path.join(PROJECT_CK_DIR, "cache")
|
||||
EXTERN_DIR = os.path.join(PROJECT_CK_DIR, "extern")
|
||||
SRC_DIR = "src"
|
||||
META_DIR = f"meta"
|
||||
META_DIR = "meta"
|
||||
TARGETS_DIR = os.path.join(META_DIR, "targets")
|
||||
DEFAULT_REPO_TEMPLATES = "cute-engineering/cutekit-templates"
|
||||
DESCRIPTION = "A build system and package manager for low-level software development"
|
||||
|
|
|
@ -288,7 +288,7 @@ def contextFor(targetSpec: str, props: Props = {}) -> Context:
|
|||
instances: list[ComponentInstance] = list(
|
||||
map(lambda c: instanciateDisabled(c, target), disabled))
|
||||
|
||||
instances += cast(list[ComponentInstance], list(filter(lambda e: e != None, map(lambda c: instanciate(
|
||||
instances += cast(list[ComponentInstance], list(filter(lambda e: e is not None, map(lambda c: instanciate(
|
||||
c.id, components, target), components))))
|
||||
|
||||
context[targetSpec] = Context(
|
||||
|
|
|
@ -10,15 +10,21 @@ Builtin = Callable[..., Json]
|
|||
|
||||
BUILTINS: Final[dict[str, Builtin]] = {
|
||||
"uname": lambda arg, ctx: getattr(shell.uname(), arg).lower(),
|
||||
"include": lambda arg, ctx: evalRead(arg),
|
||||
"evalRead": lambda arg, ctx: evalRead(arg),
|
||||
"join": lambda lhs, rhs, ctx: cast(Json, {**lhs, **rhs} if isinstance(lhs, dict) else lhs + rhs),
|
||||
"include": lambda arg, ctx: evalRead(arg, compatibilityCheck=False),
|
||||
"evalRead": lambda arg, ctx: evalRead(arg, compatibilityCheck=False),
|
||||
"join": lambda lhs, rhs, ctx: cast(
|
||||
Json, {**lhs, **rhs} if isinstance(lhs, dict) else lhs + rhs
|
||||
),
|
||||
"concat": lambda *args, ctx: "".join(args),
|
||||
"first": lambda arg, ctx: arg[0],
|
||||
"last": lambda arg, ctx: arg[-1],
|
||||
"eval": lambda arg, ctx: eval(arg, ctx["filepath"]),
|
||||
"read": lambda arg, ctx: read(arg),
|
||||
"exec": lambda *args, ctx: shell.popen(*args).splitlines(),
|
||||
"latest": lambda arg, ctx: shell.latest(arg),
|
||||
"abspath": lambda *args, ctx: os.path.normpath(os.path.join(os.path.dirname(ctx["filepath"]), *args))
|
||||
"abspath": lambda *args, ctx: os.path.normpath(
|
||||
os.path.join(os.path.dirname(ctx["filepath"]), *args)
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,7 +39,9 @@ def eval(jexpr: Json, filePath: str) -> Json:
|
|||
if len(jexpr) > 0 and isinstance(jexpr[0], str) and jexpr[0].startswith("@"):
|
||||
funcName = jexpr[0][1:]
|
||||
if funcName in BUILTINS:
|
||||
return BUILTINS[funcName](*eval(jexpr[1:], filePath), ctx={"filepath": filePath})
|
||||
return BUILTINS[funcName](
|
||||
*eval(jexpr[1:], filePath), ctx={"filepath": filePath}
|
||||
)
|
||||
|
||||
raise RuntimeError(f"Unknown macro {funcName}")
|
||||
else:
|
||||
|
@ -50,7 +58,8 @@ def read(path: str) -> Json:
|
|||
raise RuntimeError(f"Failed to read {path}")
|
||||
|
||||
|
||||
def evalRead(path: str) -> Json:
|
||||
def evalRead(path: str, compatibilityCheck: bool = True) -> Json:
|
||||
data = read(path)
|
||||
ensureSupportedManifest(data, path)
|
||||
if compatibilityCheck:
|
||||
ensureSupportedManifest(data, path)
|
||||
return eval(data, path)
|
||||
|
|
105
cutekit/model.py
105
cutekit/model.py
|
@ -24,14 +24,16 @@ class Manifest:
|
|||
type: Type = Type.UNKNOWN
|
||||
path: str = ""
|
||||
|
||||
def __init__(self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any):
|
||||
def __init__(
|
||||
self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any
|
||||
):
|
||||
if json is not None:
|
||||
if not "id" in json:
|
||||
if "id" not in json:
|
||||
raise RuntimeError("Missing id")
|
||||
|
||||
self.id = json["id"]
|
||||
|
||||
if not "type" in json and strict:
|
||||
if "type" not in json and strict:
|
||||
raise RuntimeError("Missing type")
|
||||
|
||||
self.type = Type(json["type"])
|
||||
|
@ -44,11 +46,7 @@ class Manifest:
|
|||
setattr(self, key, kwargs[key])
|
||||
|
||||
def toJson(self) -> Json:
|
||||
return {
|
||||
"id": self.id,
|
||||
"type": self.type.value,
|
||||
"path": self.path
|
||||
}
|
||||
return {"id": self.id, "type": self.type.value, "path": self.path}
|
||||
|
||||
def __str__(self):
|
||||
return f"Manifest(id={self.id}, type={self.type}, path={self.path})"
|
||||
|
@ -66,12 +64,12 @@ class Extern:
|
|||
|
||||
def __init__(self, json: Json = None, strict: bool = True, **kwargs: Any):
|
||||
if json is not None:
|
||||
if not "git" in json and strict:
|
||||
if "git" not in json and strict:
|
||||
raise RuntimeError("Missing git")
|
||||
|
||||
self.git = json["git"]
|
||||
|
||||
if not "tag" in json and strict:
|
||||
if "tag" not in json and strict:
|
||||
raise RuntimeError("Missing tag")
|
||||
|
||||
self.tag = json["tag"]
|
||||
|
@ -82,10 +80,7 @@ class Extern:
|
|||
setattr(self, key, kwargs[key])
|
||||
|
||||
def toJson(self) -> Json:
|
||||
return {
|
||||
"git": self.git,
|
||||
"tag": self.tag
|
||||
}
|
||||
return {"git": self.git, "tag": self.tag}
|
||||
|
||||
def __str__(self):
|
||||
return f"Extern(git={self.git}, tag={self.tag})"
|
||||
|
@ -98,15 +93,16 @@ class ProjectManifest(Manifest):
|
|||
description: str = ""
|
||||
extern: dict[str, Extern] = {}
|
||||
|
||||
def __init__(self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any):
|
||||
def __init__(
|
||||
self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any
|
||||
):
|
||||
if json is not None:
|
||||
if not "description" in json and strict:
|
||||
if "description" not in json and strict:
|
||||
raise RuntimeError("Missing description")
|
||||
|
||||
self.description = json["description"]
|
||||
|
||||
self.extern = {k: Extern(v)
|
||||
for k, v in json.get("extern", {}).items()}
|
||||
self.extern = {k: Extern(v) for k, v in json.get("extern", {}).items()}
|
||||
elif strict:
|
||||
raise RuntimeError("Missing json")
|
||||
|
||||
|
@ -116,7 +112,7 @@ class ProjectManifest(Manifest):
|
|||
return {
|
||||
**super().toJson(),
|
||||
"description": self.description,
|
||||
"extern": {k: v.toJson() for k, v in self.extern.items()}
|
||||
"extern": {k: v.toJson() for k, v in self.extern.items()},
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
|
@ -133,12 +129,12 @@ class Tool:
|
|||
|
||||
def __init__(self, json: Json = None, strict: bool = True, **kwargs: Any):
|
||||
if json is not None:
|
||||
if not "cmd" in json and strict:
|
||||
if "cmd" not in json and strict:
|
||||
raise RuntimeError("Missing cmd")
|
||||
|
||||
self.cmd = json.get("cmd", self.cmd)
|
||||
|
||||
if not "args" in json and strict:
|
||||
if "args" not in json and strict:
|
||||
raise RuntimeError("Missing args")
|
||||
|
||||
self.args = json.get("args", [])
|
||||
|
@ -151,11 +147,7 @@ class Tool:
|
|||
setattr(self, key, kwargs[key])
|
||||
|
||||
def toJson(self) -> Json:
|
||||
return {
|
||||
"cmd": self.cmd,
|
||||
"args": self.args,
|
||||
"files": self.files
|
||||
}
|
||||
return {"cmd": self.cmd, "args": self.args, "files": self.files}
|
||||
|
||||
def __str__(self):
|
||||
return f"Tool(cmd={self.cmd}, args={self.args}, files={self.files})"
|
||||
|
@ -172,14 +164,16 @@ class TargetManifest(Manifest):
|
|||
tools: Tools
|
||||
routing: dict[str, str]
|
||||
|
||||
def __init__(self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any):
|
||||
def __init__(
|
||||
self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any
|
||||
):
|
||||
if json is not None:
|
||||
if not "props" in json and strict:
|
||||
if "props" not in json and strict:
|
||||
raise RuntimeError("Missing props")
|
||||
|
||||
self.props = json["props"]
|
||||
|
||||
if not "tools" in json and strict:
|
||||
if "tools" not in json and strict:
|
||||
raise RuntimeError("Missing tools")
|
||||
|
||||
self.tools = {k: Tool(v) for k, v in json["tools"].items()}
|
||||
|
@ -193,27 +187,34 @@ class TargetManifest(Manifest):
|
|||
**super().toJson(),
|
||||
"props": self.props,
|
||||
"tools": {k: v.toJson() for k, v in self.tools.items()},
|
||||
"routing": self.routing
|
||||
"routing": self.routing,
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f"TargetManifest({self.id})"
|
||||
|
||||
def route(self, componentSpec: str):
|
||||
return self.routing[componentSpec] if componentSpec in self.routing else componentSpec
|
||||
return (
|
||||
self.routing[componentSpec]
|
||||
if componentSpec in self.routing
|
||||
else componentSpec
|
||||
)
|
||||
|
||||
def cdefs(self) -> list[str]:
|
||||
defines: list[str] = []
|
||||
|
||||
def sanatize(s: str) -> str:
|
||||
return s.lower().replace(" ", "_").replace("-", "_").replace(".", "_")
|
||||
|
||||
for key in self.props:
|
||||
macroname = key.lower().replace("-", "_")
|
||||
prop = self.props[key]
|
||||
macrovalue = str(prop).lower().replace(" ", "_").replace("-", "_")
|
||||
propStr = str(prop)
|
||||
if isinstance(prop, bool):
|
||||
if prop:
|
||||
defines += [f"-D__ck_{macroname}__"]
|
||||
defines += [f"-D__ck_{sanatize(key)}__"]
|
||||
else:
|
||||
defines += [f"-D__ck_{macroname}_{macrovalue}__"]
|
||||
defines += [f"-D__ck_{sanatize(key)}_{sanatize(propStr)}__"]
|
||||
defines += [f"-D__ck_{sanatize(key)}_value={propStr}"]
|
||||
|
||||
return defines
|
||||
|
||||
|
@ -227,17 +228,24 @@ class ComponentManifest(Manifest):
|
|||
provides: list[str] = []
|
||||
subdirs: list[str] = []
|
||||
|
||||
def __init__(self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any):
|
||||
def __init__(
|
||||
self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any
|
||||
):
|
||||
if json is not None:
|
||||
self.decription = json.get("description", self.decription)
|
||||
self.props = json.get("props", self.props)
|
||||
self.tools = {k: Tool(v, strict=False)
|
||||
for k, v in json.get("tools", {}).items()}
|
||||
self.tools = {
|
||||
k: Tool(v, strict=False) for k, v in json.get("tools", {}).items()
|
||||
}
|
||||
self.enableIf = json.get("enableIf", self.enableIf)
|
||||
self.requires = json.get("requires", self.requires)
|
||||
self.provides = json.get("provides", self.provides)
|
||||
self.subdirs = list(map(lambda x: os.path.join(os.path.dirname(
|
||||
path), x), json.get("subdirs", [""])))
|
||||
self.subdirs = list(
|
||||
map(
|
||||
lambda x: os.path.join(os.path.dirname(path), x),
|
||||
json.get("subdirs", [""]),
|
||||
)
|
||||
)
|
||||
|
||||
super().__init__(json, path, strict, **kwargs)
|
||||
|
||||
|
@ -250,7 +258,7 @@ class ComponentManifest(Manifest):
|
|||
"enableIf": self.enableIf,
|
||||
"requires": self.requires,
|
||||
"provides": self.provides,
|
||||
"subdirs": self.subdirs
|
||||
"subdirs": self.subdirs,
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -258,15 +266,18 @@ class ComponentManifest(Manifest):
|
|||
|
||||
def isEnabled(self, target: TargetManifest) -> tuple[bool, str]:
|
||||
for k, v in self.enableIf.items():
|
||||
if not k in target.props:
|
||||
logger.info(
|
||||
f"Component {self.id} disabled by missing {k} in target")
|
||||
if k not in target.props:
|
||||
logger.info(f"Component {self.id} disabled by missing {k} in target")
|
||||
return False, f"Missing props '{k}' in target"
|
||||
|
||||
if not target.props[k] in v:
|
||||
if target.props[k] not in v:
|
||||
vStrs = [f"'{str(x)}'" for x in v]
|
||||
logger.info(
|
||||
f"Component {self.id} disabled by {k}={target.props[k]} not in {v}")
|
||||
return False, f"Props missmatch for '{k}': Got '{target.props[k]}' but expected {', '.join(vStrs)}"
|
||||
f"Component {self.id} disabled by {k}={target.props[k]} not in {v}"
|
||||
)
|
||||
return (
|
||||
False,
|
||||
f"Props missmatch for '{k}': Got '{target.props[k]}' but expected {', '.join(vStrs)}",
|
||||
)
|
||||
|
||||
return True, ""
|
||||
|
|
|
@ -23,11 +23,11 @@ def loadAll():
|
|||
logger.info("Loading plugins...")
|
||||
|
||||
projectRoot = project.root()
|
||||
|
||||
|
||||
if projectRoot is None:
|
||||
logger.info("Not in project, skipping plugin loading")
|
||||
return
|
||||
|
||||
|
||||
pj = context.loadProject(projectRoot)
|
||||
paths = list(map(lambda e: os.path.join(const.EXTERN_DIR, e), pj.extern.keys())) + ["."]
|
||||
|
||||
|
|
Loading…
Reference in a new issue