class BuildNode: def __init__(self, name, cmd, deps=None, cache_key=None): self.name = name self.cmd = cmd self.deps = deps or [] self.cache_key = cache_key def __repr__(self): return f"" class BuildGraph: def __init__(self, spec): self.spec = spec self.nodes = [] # ----------------------------- # ENTRY POINT # ----------------------------- def generate(self): self._fetch_source() self._resolve_toolchain() self._compile_units() self._link_stage() self._package() self._cache() return self.nodes # ----------------------------- # STAGES # ----------------------------- def _fetch_source(self): self.nodes.append( BuildNode( name="fetch_source", cmd="git clone repo", cache_key="src" ) ) def _resolve_toolchain(self): cmd = f"setup-toolchain --arch {self.spec.arch} --target {self.spec.target}" self.nodes.append( BuildNode( name="resolve_toolchain", cmd=cmd, deps=["fetch_source"], cache_key="toolchain" ) ) def _compile_units(self): # simplified fan-out model (real version would parse AST / Makefile / Ninja) for i in range(3): self.nodes.append( BuildNode( name=f"compile_unit_{i}", cmd=f"{self.spec.toolchain} -c file_{i}.c", deps=["resolve_toolchain"], cache_key=f"obj_{i}" ) ) def _link_stage(self): self.nodes.append( BuildNode( name="link", cmd=f"{self.spec.toolchain} link *.o -o output.elf", deps=["compile_unit_0", "compile_unit_1", "compile_unit_2"], cache_key="binary" ) ) def _package(self): self.nodes.append( BuildNode( name="package", cmd=f"package --format {self.spec.output_mode}", deps=["link"], cache_key="artifact" ) ) def _cache(self): self.nodes.append( BuildNode( name="cache_upload", cmd="upload-cache", deps=["package"], cache_key="cache" ) )