diff --git a/build/ab.mk b/build/ab.mk index e7c3172b..b272585a 100644 --- a/build/ab.mk +++ b/build/ab.mk @@ -1,4 +1,8 @@ -ifeq ($(findstring 4.,$(MAKE_VERSION)),) +MAKENOT4 := $(if $(findstring 3.9999, $(lastword $(sort 3.9999 $(MAKE_VERSION)))),yes,no) +MAKE4.3 := $(if $(findstring 4.3, $(firstword $(sort 4.3 $(MAKE_VERSION)))),yes,no) +MAKE4.1 := $(if $(findstring no_no,$(MAKENOT4)_$(MAKE4.3)),yes,no) + +ifeq ($(MAKENOT3),yes) $(error You need GNU Make 4.x for this (if you're on OSX, use gmake).) endif @@ -10,9 +14,12 @@ AR ?= ar CFLAGS ?= -g -Og LDFLAGS ?= -g PKG_CONFIG ?= pkg-config +HOST_PKG_CONFIG ?= $(PKG_CONFIG) ECHO ?= echo CP ?= cp -TARGETS ?= +all + +export PKG_CONFIG +export HOST_PKG_CONFIG ifdef VERBOSE hide = @@ -24,17 +31,44 @@ else endif endif +WINDOWS := no +OSX := no +LINUX := no +ifeq ($(OS),Windows_NT) + WINDOWS := yes +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Linux) + LINUX := yes + endif + ifeq ($(UNAME_S),Darwin) + OSX := yes + endif +endif + ifeq ($(OS), Windows_NT) EXT ?= .exe endif EXT ?= ifeq ($(PROGRESSINFO),) -rulecount := $(shell $(MAKE) --no-print-directory -q $(OBJ)/build.mk PROGRESSINFO=1 && $(MAKE) -n $(MAKECMDGOALS) PROGRESSINFO=XXXPROGRESSINFOXXX | grep XXXPROGRESSINFOXXX | wc -l) +# The first make invocation here has to have its output discarded or else it +# produces spurious 'Leaving directory' messages... don't know why. +rulecount := $(strip $(shell $(MAKE) --no-print-directory -q $(OBJ)/build.mk PROGRESSINFO=1 > /dev/null \ + && $(MAKE) --no-print-directory -n $(MAKECMDGOALS) PROGRESSINFO=XXXPROGRESSINFOXXX | grep XXXPROGRESSINFOXXX | wc -l)) ruleindex := 1 -PROGRESSINFO = "$(shell $(PYTHON) build/_progress.py $(ruleindex) $(rulecount))$(eval ruleindex := $(shell expr $(ruleindex) + 1))" +PROGRESSINFO = "[$(ruleindex)/$(rulecount)]$(eval ruleindex := $(shell expr $(ruleindex) + 1))" endif +PKG_CONFIG_HASHES = $(OBJ)/.pkg-config-hashes/target-$(word 1, $(shell $(PKG_CONFIG) --list-all | md5sum)) +HOST_PKG_CONFIG_HASHES = $(OBJ)/.pkg-config-hashes/host-$(word 1, $(shell $(HOST_PKG_CONFIG) --list-all | md5sum)) + +$(OBJ)/build.mk : $(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES) +$(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES) &: + $(hide) rm -rf $(OBJ)/.pkg-config-hashes + $(hide) mkdir -p $(OBJ)/.pkg-config-hashes + $(hide) touch $(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES) + include $(OBJ)/build.mk MAKEFLAGS += -r -j$(shell nproc) diff --git a/build/ab.py b/build/ab.py index 4983c9ae..5ad3ca8f 100644 --- a/build/ab.py +++ b/build/ab.py @@ -148,6 +148,7 @@ def __init__(self, cwd, name): self.dir = join("$(OBJ)", name) self.ins = [] self.outs = [] + self.deps = [] self.materialised = False self.args = {} @@ -419,10 +420,18 @@ def emit_rule(name, ins, outs, cmds=[], label=None): emit(".PHONY:", name, into=lines) if outs: emit(name, ":", *fouts, into=lines) - emit(*fouts, "&:" if len(fouts) > 1 else ":", *fins, "\x01", into=lines) + if len(fouts) == 1: + emit(*fouts, ":", *fins, "\x01", into=lines) + else: + emit("ifeq ($(MAKE4.3),yes)", into=lines) + emit(*fouts, "&:", *fins, "\x01", into=lines) + emit("else", into=lines) + emit(*(fouts[1:]), ":", fouts[0], into=lines) + emit(fouts[0], ":", *fins, "\x01", into=lines) + emit("endif", into=lines) if label: - emit("\t$(hide)", "$(ECHO) $(PROGRESSINFO) ", label, into=lines) + emit("\t$(hide)", "$(ECHO) $(PROGRESSINFO)", label, into=lines) for c in cmds: emit("\t$(hide)", c, into=lines) else: @@ -472,7 +481,7 @@ def simplerule( name=self.name, ins=ins + deps, outs=outs, - label=self.templateexpand("{label} {name}"), + label=self.templateexpand("{label} {name}") if label else None, cmds=cs, ) @@ -498,7 +507,7 @@ def export(self, name=None, items: TargetsMap = {}, deps: Targets = []): ins=[srcs[0]], outs=[destf], commands=["$(CP) %s %s" % (srcs[0], destf)], - label="CP", + label="", ) subrule.materialise() diff --git a/build/c.py b/build/c.py index 52b942b7..0045e634 100644 --- a/build/c.py +++ b/build/c.py @@ -6,45 +6,46 @@ filenamesof, flatten, simplerule, + emit, ) -from build.utils import ( - filenamesmatchingof, - stripext, - targetswithtraitsof, - collectattrs, -) +from build.utils import filenamesmatchingof, stripext, collectattrs from os.path import * +emit( + """ +ifeq ($(OSX),no) +STARTGROUP ?= -Wl,--start-group +ENDGROUP ?= -Wl,--end-group +endif +""" +) -class Toolchain: - label = "" - cfile = ["$(CC) -c -o {outs[0]} {ins[0]} $(CFLAGS) {cflags}"] - cxxfile = ["$(CXX) -c -o {outs[0]} {ins[0]} $(CFLAGS) {cflags}"] - clibrary = ["$(AR) cqs {outs[0]} {ins}"] - cxxlibrary = ["$(AR) cqs {outs[0]} {ins}"] - cprogram = ["$(CC) -o {outs[0]} {ins} {ldflags} $(LDFLAGS)"] - cxxprogram = ["$(CXX) -o {outs[0]} {ins} {ldflags} $(LDFLAGS)"] - +def _combine(list1, list2): + r = list(list1) + for i in list2: + if i not in r: + r.append(i) + return r -class HostToolchain: - label = "HOST " - cfile = ["$(HOSTCC) -c -o {outs[0]} {ins[0]} $(HOSTCFLAGS) {cflags}"] - cxxfile = ["$(HOSTCXX) -c -o {outs[0]} {ins[0]} $(HOSTCFLAGS) {cflags}"] - clibrary = ["$(HOSTAR) cqs {outs[0]} {ins}"] - cxxlibrary = ["$(HOSTAR) cqs {outs[0]} {ins}"] - cprogram = ["$(HOSTCC) -o {outs[0]} {ins} {ldflags} $(HOSTLDFLAGS)"] - cxxprogram = ["$(HOSTCXX) -o {outs[0]} {ins} {ldflags} $(HOSTLDFLAGS)"] +def _indirect(deps, name): + r = [] + for d in deps: + r = _combine(r, d.args.get(name, [d])) + return r -def cfileimpl(self, name, srcs, deps, suffix, commands, label, kind, cflags): +def cfileimpl(self, name, srcs, deps, suffix, commands, label, cflags): outleaf = "=" + stripext(basename(filenameof(srcs[0]))) + suffix - cflags = collectattrs(targets=deps, name="caller_cflags", initial=cflags) + hdr_deps = _indirect(deps, "cheader_deps") + cflags = collectattrs( + targets=hdr_deps, name="caller_cflags", initial=cflags + ) t = simplerule( replaces=self, ins=srcs, - deps=deps, + deps=sorted(_indirect(hdr_deps, "cheader_files")), outs=[outleaf], label=label, commands=commands, @@ -60,15 +61,10 @@ def cfile( deps: Targets = None, cflags=[], suffix=".o", - toolchain=Toolchain, - commands=None, - label=None, + commands=["$(CC) -c -o {outs[0]} {ins[0]} $(CFLAGS) {cflags}"], + label="CC", ): - if not label: - label = toolchain.label + "CC" - if not commands: - commands = toolchain.cfile - cfileimpl(self, name, srcs, deps, suffix, commands, label, "cfile", cflags) + cfileimpl(self, name, srcs, deps, suffix, commands, label, cflags) @Rule @@ -79,23 +75,16 @@ def cxxfile( deps: Targets = None, cflags=[], suffix=".o", - toolchain=Toolchain, - commands=None, - label=None, + commands=["$(CXX) -c -o {outs[0]} {ins[0]} $(CFLAGS) {cflags}"], + label="CXX", ): - if not label: - label = toolchain.label + "CXX" - if not commands: - commands = toolchain.cxxfile - cfileimpl( - self, name, srcs, deps, suffix, commands, label, "cxxfile", cflags - ) + cfileimpl(self, name, srcs, deps, suffix, commands, label, cflags) -def findsources(name, srcs, deps, cflags, toolchain, filerule, cwd): - headers = filenamesmatchingof(srcs, "*.h") - cflags = cflags + ["-I" + dirname(h) for h in headers] - deps = deps + headers +def findsources(name, srcs, deps, cflags, filerule, cwd): + for f in filenamesof(srcs): + if f.endswith(".h") or f.endswith(".hh"): + cflags = cflags + [f"-I{dirname(f)}"] objs = [] for s in flatten(srcs): @@ -104,8 +93,7 @@ def findsources(name, srcs, deps, cflags, toolchain, filerule, cwd): name=join(name, f.removeprefix("$(OBJ)/")), srcs=[f], deps=deps, - cflags=cflags, - toolchain=toolchain, + cflags=sorted(set(cflags)), cwd=cwd, ) for f in filenamesof([s]) @@ -121,39 +109,6 @@ def findsources(name, srcs, deps, cflags, toolchain, filerule, cwd): return objs -@Rule -def cheaders( - self, - name, - hdrs: TargetsMap = None, - caller_cflags=[], - deps: Targets = None, -): - cs = [] - ins = list(hdrs.values()) - outs = [] - i = 0 - for dest, src in hdrs.items(): - s = filenamesof([src]) - assert ( - len(s) == 1 - ), "the target of a header must return exactly one file" - - cs += ["$(CP) {ins[" + str(i) + "]} {outs[" + str(i) + "]}"] - outs += ["=" + dest] - i = i + 1 - - r = simplerule( - replaces=self, - ins=ins, - outs=outs, - commands=cs, - deps=deps, - label="CHEADERS", - args={"caller_cflags": caller_cflags + ["-I" + self.dir]}, - ) - - def libraryimpl( self, name, @@ -164,57 +119,68 @@ def libraryimpl( caller_ldflags, cflags, ldflags, - toolchain, commands, label, - kind, + filerule, ): + hdr_deps = _combine(_indirect(deps, "cheader_deps"), [self]) + lib_deps = _combine(_indirect(deps, "clibrary_deps"), [self]) + hr = None - if hdrs and not srcs: - cheaders( - replaces=self, - hdrs=hdrs, - deps=targetswithtraitsof(deps, "cheaders"), - caller_cflags=caller_cflags, - ) - return + hf = [] + ar = None if hdrs: - hr = cheaders( - name=self.localname + "_hdrs", - hdrs=hdrs, - deps=targetswithtraitsof(deps, "cheaders"), - caller_cflags=caller_cflags, + cs = [] + ins = hdrs.values() + outs = [] + i = 0 + for dest, src in hdrs.items(): + s = filenamesof([src]) + assert ( + len(s) == 1 + ), "the target of a header must return exactly one file" + + cs += ["$(CP) {ins[" + str(i) + "]} {outs[" + str(i) + "]}"] + outs += ["=" + dest] + i = i + 1 + + hr = simplerule( + name=f"{self.localname}_hdr", + ins=ins, + outs=outs, + commands=cs, + label="CHEADERS", ) hr.materialise() - deps = deps + [hr] + hf = [f"-I{hr.dir}"] + + if srcs: + objs = findsources( + self.localname, + srcs, + deps + ([hr] if hr else []), + cflags + hf, + filerule, + self.cwd, + ) - objs = findsources( - self.localname, - srcs, - targetswithtraitsof(deps, "cheaders"), - cflags, - toolchain, - kind, - self.cwd, - ) + ar = simplerule( + name=f"{self.localname}_lib", + ins=objs, + outs=[f"={self.localname}.a"], + label=label, + commands=commands, + ) + ar.materialise() - simplerule( - replaces=self, - ins=objs, - outs=[f"={self.localname}.a"], - label=label, - commands=commands, - args={ - "caller_cflags": collectattrs( - targets=deps + ([hr] if hr else []), name="caller_cflags" - ), - "caller_ldflags": collectattrs( - targets=deps, name="caller_ldflags", initial=caller_ldflags - ), - }, - traits={"cheaders"}, - ) - self.outs = self.outs + (hr.outs if hr else []) + self.outs = ([hr] if hr else []) + ([ar] if ar else []) + self.deps = self.outs + self.args["cheader_deps"] = hdr_deps + self.args["clibrary_deps"] = lib_deps + self.args["cheader_files"] = [hr] if hr else [] + self.args["clibrary_files"] = [ar] if ar else [] + self.args["caller_cflags"] = caller_cflags + hf + self.args["caller_ldflags"] = caller_ldflags @Rule @@ -228,15 +194,10 @@ def clibrary( caller_ldflags=[], cflags=[], ldflags=[], - toolchain=Toolchain, - commands=None, - label=None, + commands=["rm -f {outs[0]} && $(AR) cqs {outs[0]} {ins}"], + label="LIB", cfilerule=cfile, ): - if not label: - label = toolchain.label + "LIB" - if not commands: - commands = toolchain.clibrary libraryimpl( self, name, @@ -247,7 +208,6 @@ def clibrary( caller_ldflags, cflags, ldflags, - toolchain, commands, label, cfilerule, @@ -265,14 +225,10 @@ def cxxlibrary( caller_ldflags=[], cflags=[], ldflags=[], - toolchain=Toolchain, - commands=None, - label=None, + commands=["rm -f {outs[0]} && $(AR) cqs {outs[0]} {ins}"], + label="CXXLIB", + cxxfilerule=cxxfile, ): - if not label: - label = toolchain.label + "LIB" - if not commands: - commands = toolchain.clibrary libraryimpl( self, name, @@ -283,10 +239,9 @@ def cxxlibrary( caller_ldflags, cflags, ldflags, - toolchain, commands, label, - cxxfile, + cxxfilerule, ) @@ -297,27 +252,30 @@ def programimpl( deps, cflags, ldflags, - toolchain, commands, label, filerule, - kind, ): - ars = filenamesmatchingof(deps, "*.a") - - cfiles = findsources( - self.localname, srcs, deps, cflags, toolchain, filerule, self.cwd + cfiles = findsources(self.localname, srcs, deps, cflags, filerule, self.cwd) + + lib_deps = [] + for d in deps: + lib_deps = _combine(lib_deps, d.args.get("clibrary_deps", {d})) + libs = filenamesmatchingof(lib_deps, "*.a") + ldflags = collectattrs( + targets=lib_deps, name="caller_ldflags", initial=ldflags ) + simplerule( replaces=self, - ins=cfiles + ars + ars, + ins=cfiles + libs, outs=[f"={self.localname}$(EXT)"], - deps=deps, - label=toolchain.label + label, + deps=_indirect(lib_deps, "clibrary_files"), + label=label, commands=commands, args={ "ldflags": collectattrs( - targets=deps, name="caller_ldflags", initial=ldflags + targets=lib_deps, name="caller_ldflags", initial=ldflags ) }, ) @@ -331,14 +289,12 @@ def cprogram( deps: Targets = None, cflags=[], ldflags=[], - toolchain=Toolchain, - commands=None, + commands=[ + "$(CC) -o {outs[0]} $(STARTGROUP) {ins} {ldflags} $(LDFLAGS) $(ENDGROUP)" + ], label="CLINK", cfilerule=cfile, - cfilekind="cprogram", ): - if not commands: - commands = toolchain.cprogram programimpl( self, name, @@ -346,11 +302,9 @@ def cprogram( deps, cflags, ldflags, - toolchain, commands, label, cfilerule, - cfilekind, ) @@ -362,12 +316,12 @@ def cxxprogram( deps: Targets = None, cflags=[], ldflags=[], - toolchain=Toolchain, - commands=None, + commands=[ + "$(CXX) -o {outs[0]} $(STARTGROUP) {ins} {ldflags} $(LDFLAGS) $(ENDGROUP)" + ], label="CXXLINK", + cxxfilerule=cxxfile, ): - if not commands: - commands = toolchain.cxxprogram programimpl( self, name, @@ -375,9 +329,7 @@ def cxxprogram( deps, cflags, ldflags, - toolchain, commands, label, - cxxfile, - "cxxprogram", + cxxfilerule, ) diff --git a/build/llvm.py b/build/llvm.py index 6b977e19..02478823 100644 --- a/build/llvm.py +++ b/build/llvm.py @@ -45,7 +45,6 @@ def llvmprogram( commands=commands, label=label, cfilerule=llvmcfile, - cfilekind="llvmprogram", ) @@ -56,7 +55,7 @@ def llvmrawprogram( linkscript: Target, deps: Targets = [], commands=[ - "$(LD6502) -Map {outs[0]}.map -T {deps[-1]} -o {outs[0]} {ins} {ldflags}" + "$(LD6502) -Map {outs[0]}.map -T {linkscript} -o {outs[0]} {ins} {ldflags} # {deps}" ], label="LD6502", **kwargs @@ -67,7 +66,9 @@ def llvmrawprogram( commands=commands, label=label, cfilerule=llvmcfile, - cfilekind="llvmprogram", + args={ + "linkscript": linkscript + }, **kwargs ) diff --git a/build/pkg.py b/build/pkg.py index b5709a9f..c8deb1fb 100644 --- a/build/pkg.py +++ b/build/pkg.py @@ -3,57 +3,69 @@ import os import subprocess -emit( - """ -PKG_CONFIG ?= pkg-config -PACKAGES := $(shell $(PKG_CONFIG) --list-all | cut -d' ' -f1 | sort) - -HOST_PKG_CONFIG ?= pkg-config -HOST_PACKAGES := $(shell $(HOST_PKG_CONFIG) --list-all | cut -d' ' -f1 | sort) -""" -) - - -def _package(self, name, package, fallback, prefix=""): - emit(f"ifeq ($(filter {package}, $({prefix}PACKAGES)),)") - if fallback: - emit(f"{prefix}PACKAGE_DEPS_{package} := ", *filenamesof([fallback])) - emit( - f"{prefix}PACKAGE_CFLAGS_{package} :=", - *fallback.args.get("caller_cflags", []), - ) - emit( - f"{prefix}PACKAGE_LDFLAGS_{package} := ", - *fallback.args.get("caller_ldflags", []), - f"$(filter %.a, $({prefix}PACKAGE_DEPS_{package}))", - ) - else: - emit(f"$(error Required package '{package}' not installed.)") - emit("else") - emit( - f"{prefix}PACKAGE_CFLAGS_{package} := $(shell $({prefix}PKG_CONFIG) --cflags {package})" - ) - emit( - f"{prefix}PACKAGE_LDFLAGS_{package} := $(shell $({prefix}PKG_CONFIG) --libs {package})" - ) - emit(f"{prefix}PACKAGE_DEPS_{package} :=") - emit("endif") - emit(f"{self.name}:") - - self.args["caller_cflags"] = [f"$({prefix}PACKAGE_CFLAGS_{package})"] - self.args["caller_ldflags"] = [f"$({prefix}PACKAGE_LDFLAGS_{package})"] - self.traits.add("clibrary") - self.traits.add("cheaders") - - self.ins = [] - self.outs = [f"$({prefix}PACKAGE_DEPS_{package})"] +class _PkgConfig: + package_present = set() + package_properties = {} + pkgconfig = None -@Rule -def package(self, name, package=None, fallback: Target = None): - _package(self, name, package, fallback) + def __init__(self, cmd): + assert cmd, "no pkg-config environment variable supplied" + self.pkgconfig = cmd + + r = subprocess.run(f"{cmd} --list-all", shell=True, capture_output=True) + ps = r.stdout.decode("utf-8") + self.package_present = {l.split(" ", 1)[0] for l in ps.splitlines()} + + def has_package(self, name): + return name in self.package_present + + def get_property(self, name, flag): + p = f"{name}.{flag}" + if p not in self.package_properties: + r = subprocess.run( + f"{self.pkgconfig} {flag} {name}", + shell=True, + capture_output=True, + ) + self.package_properties[p] = r.stdout.decode("utf-8").strip() + return self.package_properties[p] + + +TargetPkgConfig = _PkgConfig(os.getenv("PKG_CONFIG")) + + +def _package(self, name, package, fallback, pkgconfig): + if pkgconfig.has_package(package): + cflags = pkgconfig.get_property(package, "--cflags") + ldflags = pkgconfig.get_property(package, "--libs") + + if cflags: + self.args["caller_cflags"] = [cflags] + if ldflags: + self.args["caller_ldflags"] = [ldflags] + self.traits.add("clibrary") + self.traits.add("cheaders") + return + + assert ( + fallback + ), f"Required package '{package}' not installed when materialising target '{name}'" + + if "cheader_deps" in fallback.args: + self.args["cheader_deps"] = fallback.args["cheader_deps"] + if "clibrary_deps" in fallback.args: + self.args["clibrary_deps"] = fallback.args["clibrary_deps"] + if "cheader_files" in fallback.args: + self.args["cheader_files"] = fallback.args["cheader_files"] + if "clibrary_files" in fallback.args: + self.args["clibrary_files"] = fallback.args["clibrary_files"] + self.ins = fallback.ins + self.outs = fallback.outs + self.deps = fallback.deps + self.traits = fallback.traits @Rule -def hostpackage(self, name, package=None, fallback: Target = None): - _package(self, name, package, fallback, "HOST_") +def package(self, name, package=None, fallback: Target = None): + _package(self, name, package, fallback, TargetPkgConfig) diff --git a/build/protobuf.py b/build/protobuf.py index def6807a..d5e02cb3 100644 --- a/build/protobuf.py +++ b/build/protobuf.py @@ -1,31 +1,70 @@ from build.ab import Rule, Targets, emit, simplerule, filenamesof from build.utils import filenamesmatchingof, collectattrs -from types import SimpleNamespace -from os.path import join +from os.path import join, abspath, dirname, relpath import build.pkg # to get the protobuf package check emit( """ PROTOC ?= protoc -ifeq ($(filter protobuf, $(PACKAGES)),) -$(error Required package 'protobuf' not installed.)" -endif """ ) +assert build.pkg.TargetPkgConfig.has_package( + "protobuf" +), "required package 'protobuf' not installed" + + +def _getprotodeps(deps): + r = set() + for d in deps: + r.update(d.args.get("protodeps", {d})) + return sorted(r) + @Rule def proto(self, name, srcs: Targets = [], deps: Targets = []): + protodeps = _getprotodeps(deps) + descriptorlist = ":".join( + [ + relpath(f, start=self.dir) + for f in filenamesmatchingof(protodeps, "*.descriptor") + ] + ) + + dirs = sorted({"{dir}/" + dirname(f) for f in filenamesof(srcs)}) simplerule( replaces=self, ins=srcs, - outs=[f"={name}.descriptor"], - deps=deps, - commands=[ - "$(PROTOC) --include_source_info --descriptor_set_out={outs[0]} {ins}" - ], + outs=[f"={self.localname}.descriptor"], + deps=protodeps, + commands=( + ["mkdir -p " + (" ".join(dirs))] + + [f"$(CP) {f} {{dir}}/{f}" for f in filenamesof(srcs)] + + [ + "cd {dir} && " + + ( + " ".join( + [ + "$(PROTOC)", + "--proto_path=.", + "--include_source_info", + f"--descriptor_set_out={self.localname}.descriptor", + ] + + ( + [f"--descriptor_set_in={descriptorlist}"] + if descriptorlist + else [] + ) + + ["{ins}"] + ) + ) + ] + ), label="PROTO", - args={"protosrcs": filenamesof(srcs)}, + args={ + "protosrcs": filenamesof(srcs), + "protodeps": set(protodeps) | {self}, + }, ) @@ -40,16 +79,36 @@ def protocc(self, name, srcs: Targets = [], deps: Targets = []): cc = f.replace(".proto", ".pb.cc") h = f.replace(".proto", ".pb.h") protos += [f] - srcs += [f] outs += ["=" + cc, "=" + h] + protodeps = _getprotodeps(deps + srcs) + descriptorlist = ":".join( + [ + relpath(f, start=self.dir) + for f in filenamesmatchingof(protodeps, "*.descriptor") + ] + ) + r = simplerule( name=f"{self.localname}_srcs", cwd=self.cwd, - ins=protos, + ins=srcs, outs=outs, - deps=deps, - commands=["$(PROTOC) --cpp_out={dir} {ins}"], + deps=protodeps, + commands=[ + "cd {dir} && " + + ( + " ".join( + [ + "$(PROTOC)", + "--proto_path=.", + "--cpp_out=.", + f"--descriptor_set_in={descriptorlist}", + ] + + protos + ) + ) + ], label="PROTOCC", ) @@ -76,15 +135,30 @@ def protojava(self, name, srcs: Targets = [], deps: Targets = []): protos += [f] srcs += [f] + descriptorlist = ":".join( + [abspath(f) for f in filenamesmatchingof(srcs + deps, "*.descriptor")] + ) + r = simplerule( name=f"{self.localname}_srcs", cwd=self.cwd, ins=protos, outs=[f"={self.localname}.srcjar"], - deps=deps, + deps=srcs + deps, commands=[ "mkdir -p {dir}/srcs", - "$(PROTOC) --java_out={dir}/srcs {ins}", + "cd {dir} && " + + ( + " ".join( + [ + "$(PROTOC)", + "--proto_path=.", + "--java_out=.", + f"--descriptor_set_in={descriptorlist}", + ] + + protos + ) + ), "$(JAR) cf {outs[0]} -C {dir}/srcs .", ], traits={"srcjar"}, diff --git a/build/utils.py b/build/utils.py index 17040a8f..4d519886 100644 --- a/build/utils.py +++ b/build/utils.py @@ -30,7 +30,7 @@ def collectattrs(*, targets, name, initial=[]): s = set(initial) for a in [t.args.get(name, []) for t in targets]: s.update(a) - return sorted(list(s)) + return sorted(s) def itemsof(pattern, root=None, cwd=None): diff --git a/scripts/get-roms.sh b/scripts/get-roms.sh index e61db20f..57254ea4 100755 --- a/scripts/get-roms.sh +++ b/scripts/get-roms.sh @@ -9,29 +9,33 @@ get_rom() { if ! [ -f roms/$rom ]; then mkdir -p roms wget -q -O roms/$rom $1 + echo "Fetched $rom" + else + echo "Already have $rom" fi } URL='https://archive.org/download/MAME217RomsOnlyMerged/MAME%200.217%20ROMs%20%28merged%29.zip' -get_rom $URL/a2diskiing.zip -get_rom $URL/a800xl.zip -get_rom $URL/apple2e.zip -get_rom $URL/bbcm.zip -get_rom $URL/c1541.zip -get_rom $URL/c64.zip -get_rom $URL/d2fdc.zip -get_rom $URL/oric1.zip -get_rom $URL/oric_microdisc.zip -get_rom $URL/saa5050.zip -get_rom $URL/vic1001.zip -get_rom $URL/pet4016.zip -get_rom $URL/pet4032b.zip -get_rom $URL/pet8032.zip -get_rom $URL/c8050.zip -get_rom $URL/c8050fdc.zip -get_rom $URL/c4040.zip -get_rom $URL/c2040_fdc.zip -get_rom $URL/vic20_fe3.zip vic20.zip -get_rom $URL/votrax.zip -cp roms/votrax.zip roms/votrsc01a.zip \ No newline at end of file +get_rom $URL/a2diskiing.zip & +get_rom $URL/a800xl.zip & +get_rom $URL/apple2e.zip & +get_rom $URL/bbcm.zip & +get_rom $URL/c1541.zip & +get_rom $URL/c64.zip & +get_rom $URL/d2fdc.zip & +get_rom $URL/oric1.zip & +get_rom $URL/oric_microdisc.zip & +get_rom $URL/saa5050.zip & +get_rom $URL/vic1001.zip & +get_rom $URL/pet4016.zip & +get_rom $URL/pet4032b.zip & +get_rom $URL/pet8032.zip & +get_rom $URL/c8050.zip & +get_rom $URL/c8050fdc.zip & +get_rom $URL/c4040.zip & +get_rom $URL/c2040_fdc.zip & +get_rom $URL/vic20_fe3.zip vic20.zip & +get_rom $URL/votrax.zip & +wait +cp roms/votrax.zip roms/votrsc01a.zip