cutekit/osdk/manifests.py

184 lines
4.9 KiB
Python
Raw Normal View History

2022-06-25 22:22:53 +00:00
import os
import json
import copy
2022-06-26 06:31:43 +00:00
from . import utils
2022-06-25 22:22:53 +00:00
def loadJsons(basedir: str) -> dict:
result = {}
for root, dirs, files in os.walk(basedir):
for filename in files:
if filename == 'manifest.json':
filename = os.path.join(root, filename)
manifest = utils.loadJson(filename)
result[manifest["id"]] = manifest
2022-06-25 22:22:53 +00:00
return result
2022-06-26 08:24:13 +00:00
def filter(manifests: dict, target: dict) -> dict:
2022-06-25 22:22:53 +00:00
result = {}
for id in manifests:
manifest = manifests[id]
accepted = True
if "requires" in manifest:
for req in manifest["requires"]:
2022-07-08 17:10:27 +00:00
if not req in target["props"] or \
not target["props"][req] in manifest["requires"][req]:
2022-06-25 22:22:53 +00:00
accepted = False
break
if accepted:
result[id] = manifest
return result
def doInjects(manifests: dict) -> dict:
manifests = copy.deepcopy(manifests)
for key in manifests:
item = manifests[key]
if "inject" in item:
for inject in item["inject"]:
if inject in manifests:
manifests[inject]["deps"].append(key)
return manifests
def resolveDeps(manifests: dict) -> dict:
manifests = copy.deepcopy(manifests)
2022-07-06 21:11:10 +00:00
def findProvide(key: str) -> str:
if key in manifests:
return key
result = []
for pkg in manifests:
if key in manifests[pkg].get("provide", []):
result.append(pkg)
if len(result) == 0:
raise utils.CliException(f"Failed to resolve dependency {key}")
if len(result) == 1:
return result[0]
raise utils.CliException(f"Multiple providers for {key}: {result}")
2022-06-25 22:22:53 +00:00
def resolve(key: str, stack: list[str] = []) -> list[str]:
result: list[str] = []
2022-07-06 21:11:10 +00:00
2022-06-25 22:22:53 +00:00
if key in stack:
raise utils.CliException("Circular dependency detected: " +
str(stack) + " -> " + key)
if not key in manifests:
raise utils.CliException("Unknown dependency: " + key)
if "deps" in manifests[key]:
stack.append(key)
2022-07-06 21:11:10 +00:00
2022-06-25 22:22:53 +00:00
for dep in manifests[key]["deps"]:
2022-07-06 21:11:10 +00:00
dep = findProvide(dep)
result.append(dep)
2022-06-25 22:22:53 +00:00
result += resolve(dep, stack)
2022-07-06 21:11:10 +00:00
2022-06-25 22:22:53 +00:00
stack.pop()
2022-07-06 21:11:10 +00:00
2022-06-25 22:22:53 +00:00
return result
for key in manifests:
manifests[key]["deps"] = utils.stripDups(resolve(key))
return manifests
def findFiles(manifests: dict) -> dict:
manifests = copy.deepcopy(manifests)
for key in manifests:
item = manifests[key]
path = manifests[key]["dir"]
testsPath = os.path.join(path, "tests")
assetsPath = os.path.join(path, "assets")
item["tests"] = utils.findFiles(testsPath, [".c", ".cpp"])
item["srcs"] = utils.findFiles(path, [".c", ".cpp", ".s", ".asm"])
2022-06-25 22:22:53 +00:00
item["assets"] = utils.findFiles(assetsPath)
return manifests
def prepareTests(manifests: dict) -> dict:
if not "tests" in manifests:
return manifests
manifests = copy.deepcopy(manifests)
tests = manifests["tests"]
for key in manifests:
item = manifests[key]
if "tests" in item and len(item["tests"]) > 0:
tests["deps"] += [item["id"]]
tests["srcs"] += item["tests"]
return manifests
2022-06-26 08:24:13 +00:00
def prepareInOut(manifests: dict, target: dict) -> dict:
2022-06-25 22:22:53 +00:00
manifests = copy.deepcopy(manifests)
for key in manifests:
item = manifests[key]
basedir = os.path.dirname(item["dir"])
2022-06-26 08:24:13 +00:00
item["objs"] = [(x.replace(basedir, target["objdir"]) + ".o", x)
2022-06-25 22:22:53 +00:00
for x in item["srcs"]]
if item["type"] == "lib":
2022-06-26 08:24:13 +00:00
item["out"] = target["bindir"] + "/" + key + ".a"
2022-06-25 22:22:53 +00:00
elif item["type"] == "exe":
2022-06-26 08:24:13 +00:00
item["out"] = target["bindir"] + "/" + key
2022-06-25 22:22:53 +00:00
else:
raise utils.CliException("Unknown type: " + item["type"])
for key in manifests:
item = manifests[key]
item["libs"] = [manifests[x]["out"]
for x in item["deps"] if manifests[x]["type"] == "lib"]
return manifests
def cincludes(manifests: dict) -> str:
include_paths = []
for key in manifests:
item = manifests[key]
if "root-include" in item:
include_paths.append(item["dir"])
if len(include_paths) == 0:
return ""
return " -I" + " -I".join(include_paths)
cache: dict = {}
2022-06-26 08:24:13 +00:00
def loadAll(basedir: str, target: dict) -> dict:
cacheKey = basedir + ":" + target["id"]
2022-06-25 22:22:53 +00:00
if cacheKey in cache:
return cache[cacheKey]
manifests = loadJsons(basedir)
2022-06-26 08:24:13 +00:00
manifests = filter(manifests, target)
2022-06-25 22:22:53 +00:00
manifests = doInjects(manifests)
manifests = resolveDeps(manifests)
manifests = findFiles(manifests)
manifests = prepareTests(manifests)
2022-06-26 08:24:13 +00:00
manifests = prepareInOut(manifests, target)
2022-06-25 22:22:53 +00:00
cache[cacheKey] = manifests
return manifests