diff --git a/examples/config-variants/__main__.py b/examples/config-variants/__main__.py index 93daeba..f63c2f6 100644 --- a/examples/config-variants/__main__.py +++ b/examples/config-variants/__main__.py @@ -3,15 +3,15 @@ from os.path import dirname, join from time import time from typing import Iterable, Union +import icmtoolchain.builtin_tasks from icmtoolchain import GLOBALS, iterate_config_directories from icmtoolchain.cli import execute_task from icmtoolchain.config import FileConfig from icmtoolchain.language import MakeAssetData, MakeDataConfig +from icmtoolchain.logger import attention, success from icmtoolchain.parser import parse_arguments from icmtoolchain.project_graph import Artifact, ProjectGraph -from icmtoolchain.logger import attention, success from icmtoolchain.task import TASKS -import icmtoolchain.builtin_tasks startup_millis = time() build_command = "--release ensureProjectExists clearOutput --force buildScripts compileNative compileJava buildResources buildInfo buildPackage" @@ -42,9 +42,7 @@ graph.resolve_dependencies() for edge in graph.traverse_dependencies(): if isinstance(edge.project, IsolatedWorkspace): continue - GLOBALS.shutdown_project() - assert isinstance(edge.project, MakeDataConfig) - GLOBALS.make_config = edge.project + GLOBALS.switch_to_project(edge) targets, tasks = tee(targets) while True: try: diff --git a/src/icmtoolchain/cli.py b/src/icmtoolchain/cli.py index 343558a..d4d47f6 100644 --- a/src/icmtoolchain/cli.py +++ b/src/icmtoolchain/cli.py @@ -109,9 +109,7 @@ def run_sequential_build(graph: ProjectGraph, targets: Iterator['BaseScheduledTa for scheduled_task in targets: scheduled_task.prepare(dependencies) for edge in dependencies: - GLOBALS.shutdown_project() - assert isinstance(edge.project, MakeDataConfig) - GLOBALS.make_config = edge.project + GLOBALS.switch_to_project(edge) targets, tasks = tee(targets) for scheduled_task in tasks: execute_task(scheduled_task) diff --git a/src/icmtoolchain/concurrent_build.py b/src/icmtoolchain/concurrent_build.py index 3fc642b..eed2be4 100644 --- a/src/icmtoolchain/concurrent_build.py +++ b/src/icmtoolchain/concurrent_build.py @@ -13,7 +13,6 @@ from prompt_toolkit.widgets import TextArea from .context import GLOBALS from .errors import abort -from .language import MakeDataConfig from .logger import error, print, trace from .project_graph import ConcurrentScheduler, ProjectEdge, ProjectGraph from .shell import Interactable, Progress @@ -34,12 +33,7 @@ class BuildStatus: failure_code: int = 1 def worker_execute_project_tasks(node: ProjectEdge, scheduled_tasks: Iterator['BaseScheduledTask'], queue: Optional[Queue] = None) -> Tuple[int, List[Tuple[str, str]]]: - if not isinstance(node.project, MakeDataConfig): - raise RuntimeError(f"Project {node} is not populated!") - - GLOBALS.shutdown_project() - GLOBALS.make_config = node.project - project_spec = str(node) + GLOBALS.switch_to_project(node) overall_result = 0 all_task_logs = [] @@ -51,11 +45,11 @@ def worker_execute_project_tasks(node: ProjectEdge, scheduled_tasks: Iterator['B if queue: queue.put(TaskEvent( type="start", - project=project_spec, + project=str(node), task_name=task_name, text=scheduled_task.description )) - scheduled_task.on_status_changed = lambda status, pn=project_spec, tn=task_name: queue.put(TaskEvent( + scheduled_task.on_status_changed = lambda status, pn=str(node), tn=task_name: queue.put(TaskEvent( type="status", project=pn, task_name=tn, diff --git a/src/icmtoolchain/context.py b/src/icmtoolchain/context.py index 154f3dc..8280e6b 100644 --- a/src/icmtoolchain/context.py +++ b/src/icmtoolchain/context.py @@ -5,9 +5,11 @@ from os.path import abspath, dirname, isfile, join from typing import TYPE_CHECKING, Iterable, Optional from .config import Config, FileConfig +from .logger import print if TYPE_CHECKING: from .language import MakeDataConfig + from .project_graph import ProjectEdge def find_config_directory(path: str, filename: str) -> Optional[str]: working_directory = abspath(path) @@ -38,6 +40,8 @@ def iterate_config_directories(path: str, max_depth: int = 5) -> Iterable['MakeD break for relative_directory in dirnames: + if os.path.basename(relative_directory) == "output": + continue working_directory = join(dirpath, relative_directory) config = MakeDataConfig.of(working_directory) if config: @@ -90,12 +94,14 @@ class Globals(threading.local): toolchain_config_path = join(get_config_directory(), "toolchain.json") toolchain_config = FileConfig(toolchain_config_path) workspace_config_path = find_config_directory(get_current_directory(), "toolchain.json") + from .utils import ensure_not_whitespace if workspace_config_path and ensure_not_whitespace(workspace_config_path): workspace_config = FileConfig(workspace_config_path, defaults=toolchain_config, raise_non_existing=True) self.toolchain_config = workspace_config else: self.toolchain_config = toolchain_config + if hasattr(self, "make_config"): self.MAKE_CONFIG.defaults = self.toolchain_config return self.toolchain_config @@ -106,6 +112,7 @@ class Globals(threading.local): make_config = find_project_config(get_current_directory()) if make_config: self.make_config = make_config + if not hasattr(self, "make_config"): from .errors import abort for directory in iterate_config_directories(get_current_directory()): @@ -191,6 +198,17 @@ class Globals(threading.local): self.parameter_signature = inspect.Signature(parameters, return_annotation=int) return self.parameter_signature + def switch_to_project(self, node: 'ProjectEdge', silent: bool = False): + from .language import MakeDataConfig + if not isinstance(node.project, MakeDataConfig): + raise RuntimeError(f"Project {node} is not populated!") + if not silent and hasattr(self, "make_config"): + print() # XXX: Do we actually logged anything? In most cases YES. + self.shutdown_project() + if not silent: + print(f"{node} in {node.project.directory}", style="class:task.execute") + self.make_config = node.project + def is_project_available(self, which_project: Optional[str] = None): from .language import MakeDataConfig if not isinstance(self.PREFERRED_CONFIG, MakeDataConfig):