mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Update to build with ab.
This commit is contained in:
2
Makefile
2
Makefile
@@ -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
|
||||
|
||||
19
build/ab.mk
19
build/ab.mk
@@ -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 $@
|
||||
|
||||
|
||||
250
build/ab.py
250
build/ab.py
@@ -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")
|
||||
|
||||
|
||||
|
||||
254
build/c.py
254
build/c.py
@@ -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",
|
||||
):
|
||||
|
||||
17
build/pkg.py
17
build/pkg.py
@@ -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})"]
|
||||
|
||||
@@ -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}"],
|
||||
)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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"],
|
||||
)
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user