diff --git a/cutekit/bootstrap.sh b/cutekit/bootstrap.sh index 2d7db7a..9b724e1 100644 --- a/cutekit/bootstrap.sh +++ b/cutekit/bootstrap.sh @@ -1,11 +1,23 @@ #!/bin/env bash -# version: {version} + +# This script is meant to be place at the root of any cutekit project. +# It will make sure that the virtual environment is set up and that the +# plugins requirements are installed. set -e -if [ "$CUTEKIT_NOVENV" == "1" ]; then +if [ -z "$CUTEKIT_PYTHON" ]; then + export CUTEKIT_PYTHON="python3.11" +fi + +if [ -z "$CUTEKIT_VERSION" ]; then + export CUTEKIT_VERSION="0.7-dev" +fi + +if [ -z "$CUTEKIT_NOVENV" ]; then echo "CUTEKIT_NOVENV is set, skipping virtual environment setup." exec cutekit $@ + exit $? fi if [ "$1" == "tools" -a "$2" == "nuke" ]; then @@ -31,20 +43,20 @@ if [ ! -f .cutekit/tools/ready ]; then mkdir -p .cutekit if [ ! -d .cutekit/venv ]; then echo "Setting up Python virtual environment..." - python3 -m venv .cutekit/venv + $CUTEKIT_PYTHON -m venv .cutekit/venv fi source .cutekit/venv/bin/activate echo "Downloading CuteKit..." if [ ! -d .cutekit/tools/cutekit ]; then - git clone --depth 1 https://github.com/cute-engineering/cutekit .cutekit/tools/cutekit --branch "0.7-dev" + git clone --depth 1 https://github.com/cute-engineering/cutekit .cutekit/tools/cutekit --branch "$CUTEKIT_VERSION" else echo "CuteKit already downloaded." fi echo "Installing Tools..." - pip3 install -e .cutekit/tools/cutekit - pip3 install -r meta/plugins/requirements.txt + $CUTEKIT_PYTHON -m pip install -e .cutekit/tools/cutekit + $CUTEKIT_PYTHON -m pip install -r meta/plugins/requirements.txt touch .cutekit/tools/ready echo "Done!" @@ -58,5 +70,5 @@ fi source .cutekit/venv/bin/activate export PATH="$PATH:.cutekit/venv/bin" -cutekit $@ +$CUTEKIT_PYTHON -m cutekit $@ diff --git a/cutekit/builder.py b/cutekit/builder.py index 3a69182..6bd5a7f 100644 --- a/cutekit/builder.py +++ b/cutekit/builder.py @@ -138,11 +138,6 @@ def subdirs(scope: ComponentScope) -> list[str]: for subs in component.subdirs: result.append(os.path.join(component.dirname(), subs)) - # for inj in component.resolved[target.id].injected: - # injected = registry.lookup(inj, model.Component) - # assert injected is not None # model.Resolver has already checked this - # result.extend(subdirs(scope.openComponentScope(injected))) - return result @@ -219,6 +214,21 @@ def collectLibs( return res +def collectInjectedLibs(scope: ComponentScope) -> list[str]: + res: list[str] = [] + for r in scope.component.resolved[scope.target.id].injected: + req = scope.registry.lookup(r, model.Component) + assert req is not None # model.Resolver has already checked this + + if r == scope.component.id: + continue + if not req.type == model.Kind.LIB: + raise RuntimeError(f"Component {r} is not a library") + res.append(outfile(scope.openComponentScope(req))) + + return res + + def link( w: ninja.Writer, scope: ComponentScope, @@ -231,8 +241,19 @@ def link( if scope.component.type == model.Kind.LIB: w.build(out, "ar", objs, implicit=res) else: + whileLibs = collectInjectedLibs(scope) libs = collectLibs(scope) - w.build(out, "ld", objs + libs, implicit=res) + w.build( + out, + "ld", + objs + whileLibs + libs, + variables={ + "objs": " ".join(objs), + "wholeLibs": " ".join(whileLibs), + "libs": " ".join(libs), + }, + implicit=res, + ) return out diff --git a/cutekit/entrypoint.sh b/cutekit/entrypoint.sh index b5ac062..90b7c37 100755 --- a/cutekit/entrypoint.sh +++ b/cutekit/entrypoint.sh @@ -5,26 +5,28 @@ set -e -export PY=python3.11 +if [ -z "$CUTEKIT_PYTHON" ]; then + export CUTEKIT_PYTHON="python3.11" +fi if [ ! -d "/tools/venv" ]; then echo "Creating virtual environment..." - $PY -m venv /tools/venv + $CUTEKIT_PYTHON -m venv /tools/venv source /tools/venv/bin/activate - $PY -m ensurepip - $PY -m pip install -r /tools/cutekit/requirements.txt + $CUTEKIT_PYTHON -m ensurepip + $CUTEKIT_PYTHON -m pip install -r /tools/cutekit/requirements.txt echo "Installing plugins requirements..." if [ -f "/project/meta/plugins/requirements.txt" ]; then echo "Root plugin requirements found." - $PY -m pip install -r /project/meta/plugins/requirements.txt + $CUTEKIT_PYTHON -m pip install -r /project/meta/plugins/requirements.txt fi for extern in /project/meta/externs/*; do if [ -f "$extern/meta/plugins/requirements.txt" ]; then echo "Plugin requirements found in $extern." - $PY -m pip install -r "$extern/meta/plugins/requirements.txt" + $CUTEKIT_PYTHON -m pip install -r "$extern/meta/plugins/requirements.txt" fi done @@ -35,4 +37,4 @@ fi cd /project export PYTHONPATH=/tools -$PY -m cutekit $@ +$CUTEKIT_PYTHON -m cutekit $@ diff --git a/cutekit/model.py b/cutekit/model.py index 4a33c63..a86b14e 100644 --- a/cutekit/model.py +++ b/cutekit/model.py @@ -583,9 +583,9 @@ class Registry(DataClassJsonMixin): # Resolve all dependencies for all targets for target in r.iter(Target): target.props |= props - resolver = Resolver(r, target) # Resolve all components + resolver = Resolver(r, target) for c in r.iter(Component): resolved = resolver.resolve(c.id) if resolved.reason: @@ -598,8 +598,15 @@ class Registry(DataClassJsonMixin): for inject in c.injects: victim = r.lookup(inject, Component, includeProvides=True) if not victim: - raise RuntimeError(f"Cannot find component '{inject}'") - victim.resolved[target.id].injected.append(c.id) + _logger.info( + f"Could not find component to inject '{inject}' with '{c.id}'" + ) + else: + victim.resolved[target.id].injected.append(c.id) + victim.resolved[target.id].required = utils.uniq( + c.resolved[target.id].required + + victim.resolved[target.id].required + ) # Resolve tooling tools: Tools = target.tools diff --git a/cutekit/rules.py b/cutekit/rules.py index 669e7b5..9538ec8 100644 --- a/cutekit/rules.py +++ b/cutekit/rules.py @@ -20,7 +20,13 @@ rules: dict[str, Rule] = { ["*.c"], "*.o", "-c -o $out $in -MD -MF $out.d $flags $cincs $cdefs", - ["-std=gnu2x", "-Wall", "-Wextra", "-Werror"], + [ + "-std=gnu2x", + "-Wall", + "-Wextra", + "-Werror", + "-fcolor-diagnostics", + ], ["$out.d"], ), "cxx": Rule( @@ -28,12 +34,25 @@ rules: dict[str, Rule] = { ["*.cpp", "*.cc", "*.cxx"], "*.o", "-c -o $out $in -MD -MF $out.d $flags $cincs $cdefs", - ["-std=gnu++2b", "-Wall", "-Wextra", "-Werror", "-fno-exceptions", "-fno-rtti"], + [ + "-std=gnu++2b", + "-Wall", + "-Wextra", + "-Werror", + "-fcolor-diagnostics", + "-fno-exceptions", + "-fno-rtti", + ], ["$out.d"], ), "as": Rule("as", ["*.s", "*.asm", "*.S"], "*.o", "-o $out $in $flags"), "ar": Rule("ar", ["*.o"], "*.a", "$flags $out $in"), - "ld": Rule("ld", ["*.o", "*.a"], "*.out", "-o $out $in $flags"), + "ld": Rule( + "ld", + ["*.o", "*.a"], + "*.out", + "-o $out $objs -Wl,--whole-archive $wholeLibs -Wl,--no-whole-archive $libs $flags", + ), }