Properly propagate props from the command line + Some code cleanup.
This commit is contained in:
		
							parent
							
								
									6dd4a49043
								
							
						
					
					
						commit
						81f10de24e
					
				
					 10 changed files with 159 additions and 120 deletions
				
			
		|  | @ -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…
	
	Add table
		
		Reference in a new issue