From 70b4517559693c1edf6bee65d2b9fa0b7ab2b717 Mon Sep 17 00:00:00 2001 From: SoraKatadzuma Date: Fri, 26 Jun 2026 16:54:56 -0500 Subject: [PATCH] Local requirements --- chinook/management/_load.py | 9 ++++++++- chinook/models/_dependency.py | 9 ++++++++- chinook/pipeline/_build.py | 16 ++++++++++------ chinook/pipeline/_test.py | 15 +++++++++------ examples/archive/chinookfile | 5 ++++- examples/local/chinookfile | 13 +++++++++++++ examples/local/entry.cpp | 5 +++++ 7 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 examples/local/chinookfile create mode 100644 examples/local/entry.cpp diff --git a/chinook/management/_load.py b/chinook/management/_load.py index cccfbde..3deeee6 100644 --- a/chinook/management/_load.py +++ b/chinook/management/_load.py @@ -51,7 +51,7 @@ def _collect_profiles(project: Project) -> None: def _collect_required(project: Project) -> None: for required in project.requires: - _clone_then_load_required(required) + _load_required(required) def _collect_targets(project: Project) -> None: for target in project.targets: @@ -127,6 +127,13 @@ def _inherit_target(target: Target, parent: Target) -> None: if parent.type == Output.INT: target.srcs.update([v for v in parent.srcs if v.level != Access.PRIVATE]) +def _load_required(required: Dependency) -> None: + # Determine if local then load or clone then load. + if required.local: + load(Path(required.remote)) + return + _clone_then_load_required(required) + def _clone_then_load_required(required: Dependency) -> None: reqpath = Config.config_directory / required.cid if not Path.exists(reqpath): diff --git a/chinook/models/_dependency.py b/chinook/models/_dependency.py index 0b24eea..df55f6c 100644 --- a/chinook/models/_dependency.py +++ b/chinook/models/_dependency.py @@ -1,6 +1,7 @@ import yaml from dataclasses import dataclass +from dataclasses import field from typing import ClassVar from typing import Self @@ -15,7 +16,13 @@ class Dependency(yaml.YAMLError): yaml_tag: ClassVar[str] = u"!dependency" remote: str - branch: Branch + branch: Branch = field(default="main") + local: bool = field(default=False) + + def __post_init__(self) -> None: + from urllib.parse import urlparse + url = urlparse(self.remote) + self.local = not url.scheme @property def cid(self) -> str: diff --git a/chinook/pipeline/_build.py b/chinook/pipeline/_build.py index c5d58e8..0cd7483 100644 --- a/chinook/pipeline/_build.py +++ b/chinook/pipeline/_build.py @@ -23,14 +23,15 @@ def build( commands: list[Command] = [] for target in project.targets: - commands.extend(_prepare_dependencies(appcfg, target, logger)) + commands.extend(_prepare_dependencies(appcfg, project, target, logger)) commands.extend(prepare(appcfg, project, target, logger)) return execute(commands, "Building") def _prepare_dependencies( - appcfg: Config, - target: Target, - logger: Logger = _logger + appcfg: Config, + project: Project, + target: Target, + logger: Logger = _logger ) -> list[Command]: from ..management import find_target_by_name from ..management import find_project_by_target @@ -41,6 +42,9 @@ def _prepare_dependencies( dependency = find_target_by_name(required.value) if dependency._prepared: continue - project = find_project_by_target(required.value) - commands.extend(prepare(appcfg, project, target, logger)) + parent = find_project_by_target(required.value) + if project.cid != parent.cid: + if required.value not in parent.exports: + raise Exception(f"Cannot depend on non-exported target: {required.value}") + commands.extend(prepare(appcfg, parent, target, logger)) return commands diff --git a/chinook/pipeline/_test.py b/chinook/pipeline/_test.py index d929194..4ac48a9 100644 --- a/chinook/pipeline/_test.py +++ b/chinook/pipeline/_test.py @@ -24,7 +24,7 @@ def test( commands: list[Command] = [] for target in project.tests: - commands.extend(_prepare_dependencies(appcfg, target, logger)) + commands.extend(_prepare_dependencies(appcfg, project, target, logger)) commands.extend(prepare(appcfg, project, target, logger)) results = execute(commands, "Building") @@ -36,9 +36,10 @@ def test( return results def _prepare_dependencies( - appcfg: Config, - target: Target, - logger: Logger = _logger + appcfg: Config, + project: Project, + target: Target, + logger: Logger = _logger ) -> list[Command]: from ..management import find_target_by_name from ..management import find_project_by_target @@ -49,6 +50,8 @@ def _prepare_dependencies( dependency = find_target_by_name(required.value) if dependency._prepared: continue - project = find_project_by_target(required.value) - commands.extend(prepare(appcfg, project, dependency, logger)) + parent = find_project_by_target(required.value) + if project.cid != parent.cid and required not in parent.exports: + raise Exception(f"Cannot depend on non-exported target: {required}") + commands.extend(prepare(appcfg, parent, target, logger)) return commands diff --git a/examples/archive/chinookfile b/examples/archive/chinookfile index 4c2c8d0..0eb7f82 100644 --- a/examples/archive/chinookfile +++ b/examples/archive/chinookfile @@ -10,4 +10,7 @@ targets: - name: hello type: program deps: [example] - srcs: [./entry.cpp] \ No newline at end of file + srcs: [./entry.cpp] + +exports: +- example diff --git a/examples/local/chinookfile b/examples/local/chinookfile new file mode 100644 index 0000000..5284fab --- /dev/null +++ b/examples/local/chinookfile @@ -0,0 +1,13 @@ +name: local +gpid: examples +semv: 1.0.0 + +requires: +- remote: examples/archive + +targets: +- name: hello + type: program + deps: [example] # Comes from local required + srcs: + - ./entry.cpp \ No newline at end of file diff --git a/examples/local/entry.cpp b/examples/local/entry.cpp new file mode 100644 index 0000000..6a61127 --- /dev/null +++ b/examples/local/entry.cpp @@ -0,0 +1,5 @@ +extern "C" void print(const char* str); + +int main() { + print("Hello, World!"); +}