cutekit/osdk/__init__.py

187 lines
4.7 KiB
Python

import importlib
import shutil
import sys
from types import ModuleType
import osdk.build as build
import osdk.utils as utils
import osdk.targets as targets
import osdk.manifests as manifests
CMDS = {}
def parseOptions(args: list[str]) -> dict:
result = {
'opts': {},
'args': []
}
for arg in args:
if arg.startswith("--"):
if "=" in arg:
key, value = arg[2:].split("=", 1)
result['opts'][key] = value
else:
result['opts'][arg[2:]] = True
else:
result['args'].append(arg)
return result
def propsFromOptions(opt: dict) -> dict:
result = {}
for key in opt:
if key.startswith("prop:"):
result[key[5:]] = opt[key]
return result
def runCmd(opts: dict, args: list[str]) -> None:
props = propsFromOptions(opts)
if len(args) == 0:
print(f"Usage: {args[0]} run <component>")
sys.exit(1)
out = build.buildOne(opts.get('target', 'default'), args[0], props)
print(f"{utils.Colors.BOLD}Running: {args[0]}{utils.Colors.RESET}")
utils.runCmd(out, *args[1:])
print()
print(f"{utils.Colors.GREEN}Process exited with success{utils.Colors.RESET}")
def buildCmd(opts: dict, args: list[str]) -> None:
props = propsFromOptions(opts)
allTargets = opts.get('all-targets', False)
targetName = opts.get('target', 'default')
if allTargets:
for target in targets.available():
if len(args) == 0:
build.buildAll(target, props)
else:
for component in args:
build.buildOne(target, component, props)
else:
if len(args) == 0:
build.buildAll(targetName, props)
else:
for component in args:
build.buildOne(targetName, component, props)
def listCmd(opts: dict, args: list[str]) -> None:
props = propsFromOptions(opts)
targetName = opts.get('target', 'default')
target = targets.load(targetName, props)
components = manifests.loadAll("src", target)
print(f"Available components for target '{targetName}':")
componentsNames = list(components.keys())
componentsNames.sort()
for component in componentsNames:
print(" " + component)
print("")
def cleanCmd(opts: dict, args: list[str]) -> None:
shutil.rmtree(".osdk/build", ignore_errors=True)
def nukeCmd(opts: dict, args: list[str]) -> None:
shutil.rmtree(".osdk", ignore_errors=True)
def helpCmd(opts: dict, args: list[str]) -> None:
print(f"Usage: osdk <command> [options...] [<args...>]")
print("")
print("Description:")
print(" Operating System Development Kit.")
print("")
print("Commands:")
for cmd in CMDS:
print(" " + cmd + " - " + CMDS[cmd]["desc"])
print("")
print("Targets:")
availableTargets = targets.available()
if len(availableTargets) == 0:
print(" No targets available")
else:
for targetName in targets.available():
print(" " + targetName)
print("")
print("Variants:")
for var in targets.VARIANTS:
print(" " + var)
print("")
CMDS = {
"run": {
"func": runCmd,
"desc": "Run a component on the host",
},
"build": {
"func": buildCmd,
"desc": "Build one or more components",
},
"list": {
"func": listCmd,
"desc": "List available components",
},
"clean": {
"func": cleanCmd,
"desc": "Clean the build directory",
},
"nuke": {
"func": nukeCmd,
"desc": "Clean the build directory and cache",
},
"help": {
"func": helpCmd,
"desc": "Show this help message",
},
}
def loadPlugin(path: str) -> ModuleType:
"""Load a plugin from a path"""
spec = importlib.util.spec_from_file_location("plugin", path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
for files in utils.tryListDir("meta/plugins"):
if files.endswith(".py"):
plugin = loadPlugin(f"meta/plugins/{files}")
CMDS[plugin.__plugin__["name"]] = plugin.__plugin__
def main():
argv = sys.argv
try:
if len(argv) < 2:
helpCmd({}, [])
else:
o = parseOptions(argv[2:])
if not argv[1] in CMDS:
print(f"Unknown command: {argv[1]}")
print("")
print(f"Use '{argv[0]} help' for a list of commands")
return 1
CMDS[argv[1]]["func"](o['opts'], o['args'])
return 0
except utils.CliException as e:
print()
print(f"{utils.Colors.RED}{e.msg}{utils.Colors.RESET}")
return 1