Update to build with ab.

This commit is contained in:
David Given
2024-03-29 23:53:05 +01:00
parent df83b558bf
commit c115de9d40
13 changed files with 395 additions and 244 deletions

View File

@@ -44,7 +44,7 @@ all: +all README.md
binaries: all
tests: all
README.md: $(OBJ)/scripts+mkdocindex/scripts+mkdocindex$(EXT)
README.md: $(OBJ)/scripts/+mkdocindex/+mkdocindex$(EXT)
@echo MKDOC $@
@csplit -s -f$(OBJ)/README. README.md '/<!-- FORMATSSTART -->/' '%<!-- FORMATSEND -->%'
@(cat $(OBJ)/README.00 && $< && cat $(OBJ)/README.01) > README.md

View File

@@ -9,9 +9,19 @@ CXX ?= g++
AR ?= ar
CFLAGS ?= -g -Og
LDFLAGS ?= -g
hide = @
PKG_CONFIG ?= pkg-config
ECHO ?= echo
TARGETS ?= +all
ifdef VERBOSE
hide =
else
ifdef V
hide =
else
hide = @
endif
endif
ifeq ($(OS), Windows_NT)
EXT ?= .exe
@@ -20,6 +30,9 @@ EXT ?=
include $(OBJ)/build.mk
MAKEFLAGS += -r
.DELETE_ON_ERROR:
.PHONY: update-ab
update-ab:
@echo "Press RETURN to update ab from the repository, or CTRL+C to cancel." \
@@ -33,10 +46,10 @@ clean::
$(hide) rm -rf $(OBJ) bin
export PYTHONHASHSEED = 1
build-files = $(shell find . -name 'build.py') build/*.py config.py
build-files = $(shell find . -name 'build.py') $(wildcard build/*.py) $(wildcard config.py)
$(OBJ)/build.mk: Makefile $(build-files)
@echo "AB"
@mkdir -p $(OBJ)
$(hide) $(PYTHON) -X pycache_prefix=$(OBJ) build/ab.py -t +all -o $@ \
$(hide) $(PYTHON) -X pycache_prefix=$(OBJ) build/ab.py $(patsubst %,-t %,$(TARGETS)) -o $@ \
build.py || rm -f $@

View File

@@ -2,7 +2,6 @@ from collections.abc import Iterable, Sequence
from os.path import *
from types import SimpleNamespace
import argparse
import copy
import functools
import importlib
import importlib.abc
@@ -10,10 +9,10 @@ import importlib.util
import inspect
import re
import sys
import types
import pathlib
import builtins
import os
import string
import fnmatch
import traceback
defaultGlobals = {}
targets = {}
@@ -52,27 +51,6 @@ class ABException(BaseException):
pass
class ParameterList(Sequence):
def __init__(self, parent=[]):
self.data = parent
def __getitem__(self, i):
return self.data[i]
def __len__(self):
return len(self.data)
def __str__(self):
return " ".join(self.data)
def __add__(self, other):
newdata = self.data.copy() + other
return ParameterList(newdata)
def __repr__(self):
return f"<PList: {self.data}>"
class Invocation:
name = None
callback = None
@@ -80,6 +58,20 @@ class Invocation:
ins = None
outs = None
binding = None
traits = None
attr = None
attrdeps = None
def __init__(self):
self.attr = SimpleNamespace()
self.attrdeps = SimpleNamespace()
self.traits = set()
def __eq__(self, other):
return self.name is other.name
def __hash__(self):
return id(self.name)
def materialise(self, replacing=False):
if self in unmaterialisedTargets:
@@ -115,9 +107,7 @@ class Invocation:
self.callback(**self.args)
cwdStack.pop()
except BaseException as e:
print(
f"Error materialising {self} ({id(self)}): {self.callback}"
)
print(f"Error materialising {self}: {self.callback}")
print(f"Arguments: {self.args}")
raise e
@@ -129,8 +119,18 @@ class Invocation:
materialisingStack.pop()
def bubbleattr(self, attr, xs):
xs = targetsof(xs, cwd=self.cwd)
a = set()
if hasattr(self.attrdeps, attr):
a = getattr(self.attrdeps, attr)
for x in xs:
a.add(x)
setattr(self.attrdeps, attr, a)
def __repr__(self):
return "<Invocation %s>" % self.name
return "'%s'" % self.name
def Rule(func):
@@ -150,7 +150,7 @@ def Rule(func):
if name.startswith("./"):
name = join(cwd, name)
elif "+" not in name:
name = cwd + "+" + name
name = join(cwd, "+" + name)
i.name = name
i.localname = name.split("+")[-1]
@@ -162,12 +162,13 @@ def Rule(func):
i = replaces
name = i.name
else:
raise ABException("you must supply either name or replaces")
raise ABException("you must supply either 'name' or 'replaces'")
i.cwd = cwd
i.sentinel = "$(OBJ)/.sentinels/" + name + ".mark"
i.types = func.__annotations__
i.callback = func
setattr(i, func.__name__, SimpleNamespace())
i.traits.add(func.__name__)
i.binding = sig.bind(name=name, self=i, **kwargs)
i.binding.apply_defaults()
@@ -186,9 +187,21 @@ class Type:
self.value = value
class List(Type):
def convert(self, invocation):
value = self.value
if not value:
return []
if type(value) is str:
return [value]
return list(value)
class Targets(Type):
def convert(self, invocation):
value = self.value
if not value:
return []
if type(value) is str:
value = [value]
if type(value) is list:
@@ -207,6 +220,8 @@ class Target(Type):
class TargetsMap(Type):
def convert(self, invocation):
value = self.value
if not value:
return {}
if type(value) is dict:
return {
k: targetof(v, cwd=invocation.cwd) for k, v in value.items()
@@ -233,20 +248,29 @@ def fileinvocation(s):
return i
def targetof(s, cwd):
def targetof(s, cwd=None):
if isinstance(s, Invocation):
s.materialise()
return s
if type(s) != str:
raise ABException("parameter of targetof is not a single target")
if s in targets:
t = targets[s]
t.materialise()
return t
if s.startswith(".+"):
s = cwd + s[1:]
elif s.startswith("./"):
s = normpath(join(cwd, s))
if s.startswith("."):
if cwd == None:
raise ABException(
"relative target names can't be used in targetof without supplying cwd"
)
if s.startswith(".+"):
s = cwd + s[1:]
elif s.startswith("./"):
s = normpath(join(cwd, s))
elif s.endswith("/"):
return fileinvocation(s)
elif s.startswith("$"):
@@ -259,15 +283,18 @@ def targetof(s, cwd):
return fileinvocation(s)
(path, target) = s.split("+", 2)
s = join(path, "+" + target)
loadbuildfile(join(path, "build.py"))
if not s in targets:
raise ABException(f"build file at {path} doesn't contain +{target}")
raise ABException(
f"build file at {path} doesn't contain +{target} when trying to resolve {s}"
)
i = targets[s]
i.materialise()
return i
def targetsof(*xs, cwd):
def targetsof(*xs, cwd=None):
return flatten([targetof(x, cwd) for x in flatten(xs)])
@@ -282,6 +309,14 @@ def filenamesof(*xs):
return s
def filenamesmatchingof(xs, pattern):
return fnmatch.filter(filenamesof(xs), pattern)
def targetswithtraitsof(xs, trait):
return [target for target in targetsof(xs) if trait in target.traits]
def targetnamesof(*xs):
s = []
for x in flatten(xs):
@@ -302,6 +337,24 @@ def filenameof(x):
return xs[0]
def bubbledattrsof(x, attr):
x = targetsof(x)
alltargets = set()
pending = set(x) if isinstance(x, Iterable) else {x}
while pending:
t = pending.pop()
if t not in alltargets:
alltargets.add(t)
if hasattr(t.attrdeps, attr):
pending.update(getattr(t.attrdeps, attr))
values = []
for t in alltargets:
if hasattr(t.attr, attr):
values += getattr(t.attr, attr)
return values
def stripext(path):
return splitext(path)[0]
@@ -312,30 +365,43 @@ def emit(*args):
def templateexpand(s, invocation):
class Converter:
def __getitem__(self, key):
if key == "self":
return invocation
f = filenamesof(invocation.args[key])
if isinstance(f, Sequence):
f = ParameterList(f)
return f
class Formatter(string.Formatter):
def get_field(self, name, a1, a2):
return (
eval(name, invocation.callback.__globals__, invocation.args),
False,
)
return eval("f%r" % s, invocation.callback.__globals__, Converter())
def format_field(self, value, format_spec):
if type(self) == str:
return value
return " ".join(
[templateexpand(f, invocation) for f in filenamesof(value)]
)
return Formatter().format(s)
def emitter_rule(name, ins, outs, deps=[]):
def emitter_rule(rule, ins, outs, deps=[]):
emit("")
emit(".PHONY:", name)
if outs:
emit(name, ":", filenamesof(outs), ";")
emit(filenamesof(outs), "&:", filenamesof(ins), filenamesof(deps))
else:
emit(name, "&:", filenamesof(ins), filenamesof(deps))
emit(".PHONY:", rule.name)
emit(rule.name, ":", rule.sentinel)
emit(
rule.sentinel,
# filenamesof(outs) if outs else [],
":",
filenamesof(ins),
filenamesof(deps),
)
def emitter_endrule(name):
pass
def emitter_endrule(rule, outs):
emit("\t$(hide) mkdir -p", dirname(rule.sentinel))
emit("\t$(hide) touch", rule.sentinel)
for f in filenamesof(outs):
emit(f, ":", rule.sentinel, ";")
def emitter_label(s):
@@ -357,47 +423,50 @@ def unmake(*ss):
def simplerule(
self,
name,
ins: Targets = [],
outs=[],
deps: Targets = [],
commands=[],
ins: Targets = None,
outs: List = [],
deps: Targets = None,
commands: List = [],
label="RULE",
**kwargs,
):
self.ins = ins
self.outs = outs
self.deps = deps
emitter_rule(self.name, ins + deps, outs)
emitter_rule(self, ins + deps, outs)
emitter_label(templateexpand("{label} {name}", self))
dirs = []
cs = []
for out in filenamesof(outs):
dir = dirname(out)
if dir and dir not in dirs:
dirs += [dir]
cs = [("mkdir -p %s" % dir) for dir in dirs]
for c in commands:
cs += [templateexpand(c, self)]
emitter_exec(cs)
emitter_endrule(self.name)
emitter_endrule(self, outs)
@Rule
def normalrule(
self,
name=None,
ins: Targets = [],
deps: Targets = [],
outs=[],
ins: Targets = None,
deps: Targets = None,
outs: List = [],
label="RULE",
objdir=None,
commands=[],
commands: List = [],
**kwargs,
):
objdir = objdir or join("$(OBJ)", name)
self.normalrule.objdir = objdir
self.attr.objdir = objdir
simplerule(
replaces=self,
ins=ins,
@@ -410,9 +479,9 @@ def normalrule(
@Rule
def export(self, name=None, items: TargetsMap = {}, deps: Targets = []):
def export(self, name=None, items: TargetsMap = {}, deps: Targets = None):
cs = []
self.ins = items.values()
self.ins = []
self.outs = []
for dest, src in items.items():
destf = filenameof(dest)
@@ -424,23 +493,26 @@ def export(self, name=None, items: TargetsMap = {}, deps: Targets = []):
"a dependency of an export must have exactly one output file"
)
emitter_rule(self.name + "+" + destf, srcs, [destf])
emitter_label(f"CP {destf}")
if dir:
emitter_exec(["mkdir -p " + dir])
emitter_exec(["cp %s %s" % (srcs[0], destf)])
self.outs += [destf]
emitter_rule(self.name, self.outs, [], deps)
emit("\t@")
if self.outs:
subrule = simplerule(
name=self.name + "/+" + destf,
ins=[srcs[0]],
outs=[destf],
commands=["cp %s %s" % (srcs[0], destf)],
label="CP",
)
subrule.materialise()
emit("clean::")
emit("\t$(hide) rm -f " + (" ".join(filenamesof(self.outs))))
self.outs += deps
emit("\t$(hide) rm -f", destf)
emitter_endrule(self.name)
self.ins += [subrule]
emitter_rule(
self,
self.ins,
self.outs,
[(d.outs if d.outs else d.sentinel) for d in deps],
)
emitter_endrule(self, self.outs)
def loadbuildfile(filename):
@@ -478,9 +550,11 @@ def main():
loadbuildfile(f)
for t in flatten([a.split(",") for a in args.targets]):
if t not in targets:
raise ABException("target %s is not defined" % t)
targets[t].materialise()
(path, target) = t.split("+", 2)
s = join(path, "+" + target)
if s not in targets:
raise ABException("target %s is not defined" % s)
targets[s].materialise()
emit("AB_LOADED = 1\n")

View File

@@ -1,14 +1,18 @@
from os.path import basename, join
from build.ab import (
ABException,
List,
Rule,
Targets,
TargetsMap,
filenameof,
flatten,
filenamesmatchingof,
filenamesof,
flatten,
normalrule,
bubbledattrsof,
stripext,
targetswithtraitsof,
)
from os.path import *
from types import SimpleNamespace
@@ -24,7 +28,7 @@ def cfileimpl(self, name, srcs, deps, suffix, commands, label, kind, cflags):
outs=[outleaf],
label=label,
commands=commands,
cflags=cflags,
cflags=cflags + bubbledattrsof(deps, "caller_cflags"),
)
@@ -32,9 +36,9 @@ def cfileimpl(self, name, srcs, deps, suffix, commands, label, kind, cflags):
def cfile(
self,
name,
srcs: Targets = [],
deps: Targets = [],
cflags=[],
srcs: Targets = None,
deps: Targets = None,
cflags: List = [],
suffix=".o",
commands=["$(CC) -c -o {outs[0]} {ins[0]} $(CFLAGS) {cflags}"],
label="CC",
@@ -46,9 +50,9 @@ def cfile(
def cxxfile(
self,
name,
srcs: Targets = [],
deps: Targets = [],
cflags=[],
srcs: Targets = None,
deps: Targets = None,
cflags: List = [],
suffix=".o",
commands=["$(CXX) -c -o {outs[0]} {ins[0]} $(CFLAGS) {cflags}"],
label="CXX",
@@ -69,7 +73,11 @@ def findsources(name, srcs, deps, cflags, filerule):
cflags=cflags,
)
for f in filenamesof(s)
if f.endswith(".c") or f.endswith(".cc") or f.endswith(".cpp")
if f.endswith(".c")
or f.endswith(".cc")
or f.endswith(".cpp")
or f.endswith(".S")
or f.endswith(".s")
]
if any(f.endswith(".o") for f in filenamesof(s)):
objs += [s]
@@ -77,100 +85,126 @@ def findsources(name, srcs, deps, cflags, filerule):
return objs
def libraryimpl(
self, name, srcs, deps, hdrs, cflags, ldflags, commands, label, kind
@Rule
def cheaders(
self,
name,
hdrs: TargetsMap = None,
caller_cflags: List = None,
deps: Targets = None,
):
if not srcs and not hdrs:
raise ABException(
"clibrary contains no sources and no exported headers"
)
libraries = [d for d in deps if hasattr(d, "clibrary")]
for library in libraries:
if library.clibrary.cflags:
cflags += library.clibrary.cflags
if library.clibrary.ldflags:
ldflags += library.clibrary.ldflags
for f in filenamesof(srcs):
if f.endswith(".h"):
deps += [f]
hdrcs = []
hdrins = list(hdrs.values())
hdrouts = []
cs = []
ins = list(hdrs.values())
outs = []
i = 0
for dest, src in hdrs.items():
s = filenamesof(src)
if len(s) != 1:
raise ABException(
"a dependency of an export must have exactly one output file"
"the target of a header must return exactly one file"
)
hdrcs += ["cp {ins[" + str(i) + "]} {outs[" + str(i) + "]}"]
hdrouts += [dest]
cs += ["cp {ins[" + str(i) + "]} {outs[" + str(i) + "]}"]
outs += [dest]
i = i + 1
if not hasattr(self, "clibrary"):
self.clibrary = SimpleNamespace()
if srcs:
hr = None
if hdrcs:
hr = normalrule(
name=f"{name}_hdrs",
ins=hdrins,
outs=hdrouts,
label="HEADERS",
commands=hdrcs,
)
hr.materialise()
r = normalrule(
replaces=self,
ins=ins,
outs=outs,
commands=cs,
deps=deps,
label="CHEADERS",
)
r.materialise()
self.attr.caller_cflags = caller_cflags + ["-I" + r.attr.objdir]
self.bubbleattr("caller_cflags", deps)
actualsrcs = findsources(
name,
srcs,
deps + ([f"{name}_hdrs"] if hr else []),
cflags + ([f"-I{hr.normalrule.objdir}"] if hr else []),
kind,
)
normalrule(
def libraryimpl(
self,
name,
srcs,
deps,
hdrs,
caller_cflags,
caller_ldflags,
cflags,
ldflags,
commands,
label,
kind,
):
hr = None
if hdrs and not srcs:
cheaders(
replaces=self,
ins=actualsrcs,
outs=[basename(name) + ".a"],
label=label,
commands=commands if actualsrcs else [],
hdrs=hdrs,
deps=targetswithtraitsof(deps, "cheaders"),
caller_cflags=caller_cflags,
)
self.clibrary.ldflags = ldflags
self.clibrary.cflags = ["-I" + hr.normalrule.objdir] if hr else []
else:
r = normalrule(
replaces=self,
ins=hdrins,
outs=hdrouts,
label="HEADERS",
commands=hdrcs,
return
if hdrs:
hr = cheaders(
name=self.localname + "_hdrs",
hdrs=hdrs,
deps=targetswithtraitsof(deps, "cheaders"),
caller_cflags=caller_cflags,
)
r.materialise()
hr.materialise()
deps = deps + [hr]
self.clibrary.ldflags = ldflags
self.clibrary.cflags = ["-I" + r.normalrule.objdir]
objs = findsources(
name,
srcs,
targetswithtraitsof(deps, "cheaders"),
cflags + bubbledattrsof(deps, "caller_cflags"),
kind,
)
normalrule(
replaces=self,
ins=objs,
outs=[basename(name) + ".a"],
label=label,
commands=commands,
)
self.outs = self.outs + (hr.outs if hr else [])
self.traits.add("cheaders")
self.attr.caller_ldflags = caller_ldflags
self.bubbleattr("caller_ldflags", deps)
self.bubbleattr("caller_cflags", deps)
@Rule
def clibrary(
self,
name,
srcs: Targets = [],
deps: Targets = [],
hdrs: TargetsMap = {},
cflags=[],
ldflags=[],
srcs: Targets = None,
deps: Targets = None,
hdrs: TargetsMap = None,
caller_cflags: List = [],
caller_ldflags: List = [],
cflags: List = [],
ldflags: List = [],
commands=["$(AR) cqs {outs[0]} {ins}"],
label="LIB",
cfilerule=cfile,
):
return libraryimpl(
self, name, srcs, deps, hdrs, cflags, ldflags, commands, label, cfile
libraryimpl(
self,
name,
srcs,
deps,
hdrs,
caller_cflags,
caller_ldflags,
cflags,
ldflags,
commands,
label,
cfilerule,
)
@@ -178,35 +212,43 @@ def clibrary(
def cxxlibrary(
self,
name,
srcs: Targets = [],
deps: Targets = [],
hdrs: TargetsMap = {},
cflags=[],
ldflags=[],
srcs: Targets = None,
deps: Targets = None,
hdrs: TargetsMap = None,
caller_cflags: List = [],
caller_ldflags: List = [],
cflags: List = [],
ldflags: List = [],
commands=["$(AR) cqs {outs[0]} {ins}"],
label="LIB",
):
return libraryimpl(
self, name, srcs, deps, hdrs, cflags, ldflags, commands, label, cxxfile
libraryimpl(
self,
name,
srcs,
deps,
hdrs,
caller_cflags,
caller_ldflags,
cflags,
ldflags,
commands,
label,
cxxfile,
)
def programimpl(
self, name, srcs, deps, cflags, ldflags, commands, label, filerule, kind
):
libraries = [d for d in deps if hasattr(d, "clibrary")]
for library in libraries:
if library.clibrary.cflags:
cflags += library.clibrary.cflags
if library.clibrary.ldflags:
ldflags += library.clibrary.ldflags
ars = filenamesmatchingof(deps, "*.a")
deps = deps + filenamesmatchingof(srcs, "*.h")
ldflags = ldflags + bubbledattrsof(deps, "caller_ldflags")
deps += [f for f in filenamesof(srcs) if f.endswith(".h")]
ars = [f for f in filenamesof(libraries) if f.endswith(".a")]
cfiles = findsources(name, srcs, deps, cflags, filerule)
normalrule(
replaces=self,
ins=(findsources(name, srcs, deps, cflags, filerule) + ars + ars),
ins=cfiles + ars + ars,
outs=[basename(name) + "$(EXT)"],
deps=deps,
label=label,
@@ -219,12 +261,14 @@ def programimpl(
def cprogram(
self,
name,
srcs: Targets = [],
deps: Targets = [],
cflags=[],
ldflags=[],
srcs: Targets = None,
deps: Targets = None,
cflags: List = [],
ldflags: List = [],
commands=["$(CC) -o {outs[0]} {ins} {ldflags} $(LDFLAGS)"],
label="CLINK",
cfilerule=cfile,
cfilekind="cprogram",
):
programimpl(
self,
@@ -235,8 +279,8 @@ def cprogram(
ldflags,
commands,
label,
cfile,
"cprogram",
cfilerule,
cfilekind,
)
@@ -244,10 +288,10 @@ def cprogram(
def cxxprogram(
self,
name,
srcs: Targets = [],
deps: Targets = [],
cflags=[],
ldflags=[],
srcs: Targets = None,
deps: Targets = None,
cflags: List = [],
ldflags: List = [],
commands=["$(CXX) -o {outs[0]} {ins} {ldflags} $(LDFLAGS)"],
label="CXXLINK",
):

View File

@@ -1,4 +1,4 @@
from build.ab import Rule, emit, Target
from build.ab import Rule, emit, Target, bubbledattrsof
from types import SimpleNamespace
import os
import subprocess
@@ -15,8 +15,14 @@ PACKAGES := $(shell $(PKG_CONFIG) --list-all | cut -d' ' -f1 | sort)
def package(self, name, package=None, fallback: Target = None):
emit("ifeq ($(filter %s, $(PACKAGES)),)" % package)
if fallback:
emit(f"PACKAGE_CFLAGS_{package} :=", fallback.clibrary.cflags)
emit(f"PACKAGE_LDFLAGS_{package} := ", fallback.clibrary.ldflags)
emit(
f"PACKAGE_CFLAGS_{package} :=",
bubbledattrsof(fallback, "caller_cflags"),
)
emit(
f"PACKAGE_LDFLAGS_{package} := ",
bubbledattrsof(fallback, "caller_ldflags"),
)
emit(f"PACKAGE_DEP_{package} := ", fallback.name)
else:
emit(f"$(error Required package '{package}' not installed.)")
@@ -30,9 +36,8 @@ def package(self, name, package=None, fallback: Target = None):
emit(f"PACKAGE_DEP_{package} := ")
emit("endif")
self.clibrary = SimpleNamespace()
self.clibrary.cflags = [f"$(PACKAGE_CFLAGS_{package})"]
self.clibrary.ldflags = [f"$(PACKAGE_LDFLAGS_{package})"]
self.attr.caller_cflags = [f"$(PACKAGE_CFLAGS_{package})"]
self.attr.caller_ldflags = [f"$(PACKAGE_LDFLAGS_{package})"]
self.ins = []
self.outs = [f"$(PACKAGE_DEP_{package})"]

View File

@@ -1,8 +1,17 @@
from os.path import join
from build.ab import Rule, Targets, emit, normalrule, filenamesof, flatten
from build.ab import (
Rule,
Targets,
emit,
normalrule,
filenamesof,
filenamesmatchingof,
bubbledattrsof,
targetswithtraitsof,
)
from build.c import cxxlibrary
import build.pkg
from types import SimpleNamespace
import build.pkg
emit(
"""
@@ -15,7 +24,7 @@ endif
@Rule
def proto(self, name, srcs: Targets = [], deps: Targets = []):
def proto(self, name, srcs: Targets = None, deps: Targets = None):
normalrule(
replaces=self,
ins=srcs,
@@ -26,40 +35,38 @@ def proto(self, name, srcs: Targets = [], deps: Targets = []):
],
label="PROTO",
)
self.proto.srcs = filenamesof(srcs) + flatten(
[s.proto.srcs for s in flatten(deps)]
)
self.attr.protosrcs = filenamesof(srcs)
self.bubbleattr("protosrcs", deps)
@Rule
def protocc(self, name, srcs: Targets = [], deps: Targets = []):
def protocc(self, name, srcs: Targets = None, deps: Targets = None):
outs = []
protos = []
for f in flatten([s.proto.srcs for s in flatten(srcs + deps)]):
if f.endswith(".proto"):
cc = f.replace(".proto", ".pb.cc")
h = f.replace(".proto", ".pb.h")
protos += [f]
srcs += [f]
outs += [cc, h]
for f in filenamesmatchingof(bubbledattrsof(srcs, "protosrcs"), "*.proto"):
cc = f.replace(".proto", ".pb.cc")
h = f.replace(".proto", ".pb.h")
protos += [f]
srcs += [f]
outs += [cc, h]
srcname = f"{name}_srcs"
objdir = join("$(OBJ)", srcname)
r = normalrule(
name=f"{name}_srcs",
name=srcname,
ins=protos,
outs=outs,
deps=deps,
commands=["$(PROTOC) --cpp_out={self.normalrule.objdir} {ins}"],
commands=["$(PROTOC) --cpp_out={self.attr.objdir} {ins}"],
label="PROTOCC",
)
r.materialise()
headers = {
f: join(r.normalrule.objdir, f) for f in outs if f.endswith(".pb.h")
}
headers = {f: join(objdir, f) for f in outs if f.endswith(".pb.h")}
cxxlibrary(
replaces=self,
srcs=[f"{name}_srcs"],
srcs=[r],
deps=targetswithtraitsof(deps, "cheaders"),
hdrs=headers,
cflags=[f"-I{r.normalrule.objdir}"],
)

View File

@@ -19,8 +19,8 @@ def test(
name,
command: Target = None,
commands=None,
ins: Targets = [],
deps: Targets = [],
ins: Targets = None,
deps: Targets = None,
label="TEST",
):
if command:

View File

@@ -22,4 +22,4 @@ proto(
deps=[".+common_proto", "+fl2_proto"],
)
protocc(name="config_proto_lib", srcs=[".+config_proto", "arch+arch_proto"])
protocc(name="config_proto_lib", srcs=[".+common_proto", ".+config_proto", "arch+arch_proto"])

View File

@@ -16,6 +16,7 @@ def protoencode(self, name, srcs: Targets, proto, symbol):
"tests+test_proto_lib",
"+protobuf_lib",
"+fmt_lib",
"+lib",
],
)
encoders[proto] = r
@@ -36,11 +37,11 @@ def protoencode(self, name, srcs: Targets, proto, symbol):
cxxprogram(
name="mkdoc",
srcs=["./mkdoc.cc"],
deps=["src/formats", "lib+config_proto_lib", "+lib"],
deps=["src/formats", "lib+config_proto_lib", "+lib", "+fmt_lib", "+protobuf_lib"],
)
cxxprogram(
name="mkdocindex",
srcs=["./mkdocindex.cc"],
deps=["src/formats", "lib+config_proto_lib", "+lib"],
deps=["src/formats", "lib+config_proto_lib", "+lib", "+fmt_lib", "+protobuf_lib"],
)

View File

@@ -24,7 +24,7 @@ if config.windows:
outs=["rc.o"],
deps=["./manifest.xml", "extras+fluxengine_ico"],
commands=["$(WINDRES) {ins[0]} {outs[0]}"],
label="WINDRES"
label="WINDRES",
)
]

View File

@@ -31,4 +31,4 @@ encoded = [
for name in drivetypes
]
cxxlibrary(name="drivetypes", srcs=[".+drivetypes_cc"] + encoded)
cxxlibrary(name="drivetypes", srcs=[".+drivetypes_cc"] + encoded, deps=["+lib"])

View File

@@ -13,9 +13,7 @@ proto(
)
protocc(
name="test_proto_lib",
srcs=[".+test_proto"],
deps=["lib+config_proto", "arch+arch_proto"],
name="test_proto_lib", srcs=[".+test_proto"], deps=["lib+config_proto_lib"]
)
tests = [
@@ -60,6 +58,9 @@ export(
],
deps=[
"+fl2_proto_lib",
"+fmt_lib",
"+lib",
"+protobuf_lib",
"+protocol",
"+z_lib",
".+test_proto_lib",
@@ -70,7 +71,6 @@ export(
"dep/libusbp",
"dep/snowhouse",
"dep/stb",
"+lib",
"lib+config_proto_lib",
"src/formats",
],
@@ -85,7 +85,11 @@ export(
srcs=[f"./{n}.cc"],
deps=[
"+fl2_proto_lib",
"+fmt_lib",
"+lib",
"+protobuf_lib",
"+protocol",
"+z_lib",
"dep/adflib",
"dep/agg",
"dep/fatfs",
@@ -93,10 +97,10 @@ export(
"dep/libusbp",
"dep/snowhouse",
"dep/stb",
"+lib",
"lib+config_proto_lib",
"src/formats",
],
]
+ ([".+test_proto_lib"] if n == "options" else []),
),
)
for n in tests

View File

@@ -8,25 +8,28 @@ if config.windows:
cxxprogram(
name="brother120tool",
srcs=["./brother120tool.cc"],
deps=["+lib", "lib+config_proto_lib"] + emu,
deps=["+lib", "lib+config_proto_lib", "+fmt_lib", "+z_lib"] + emu,
)
cxxprogram(
name="brother240tool",
srcs=["./brother240tool.cc"],
deps=["+lib", "lib+config_proto_lib"] + emu,
deps=["+lib", "lib+config_proto_lib", "+fmt_lib", "+z_lib"] + emu,
)
cxxprogram(
name="upgrade-flux-file",
srcs=["./upgrade-flux-file.cc"],
deps=[
"+lib",
"src/formats",
"lib+config_proto_lib",
"+protocol",
"+fl2_proto_lib",
"+fmt_lib",
"+lib",
"+protobuf_lib",
"+protocol",
"+sqlite3_lib",
"+z_lib",
"dep/libusbp",
"lib+config_proto_lib",
"src/formats",
],
)