Files
fluxengine/build/c.py
David Given a777470cda Update ab.
2024-10-02 19:46:50 +02:00

396 lines
8.0 KiB
Python

from build.ab import (
Rule,
Targets,
TargetsMap,
filenameof,
filenamesof,
flatten,
simplerule,
)
from build.utils import (
filenamesmatchingof,
stripext,
targetswithtraitsof,
collectattrs,
)
from os.path import *
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)"]
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 cfileimpl(self, name, srcs, deps, suffix, commands, label, kind, cflags):
outleaf = "=" + stripext(basename(filenameof(srcs[0]))) + suffix
cflags = collectattrs(targets=deps, name="caller_cflags", initial=cflags)
t = simplerule(
replaces=self,
ins=srcs,
deps=deps,
outs=[outleaf],
label=label,
commands=commands,
args={"cflags": cflags},
)
@Rule
def cfile(
self,
name,
srcs: Targets = None,
deps: Targets = None,
cflags=[],
suffix=".o",
toolchain=Toolchain,
commands=None,
label=None,
):
if not label:
label = toolchain.label + "CC"
if not commands:
commands = toolchain.cfile
cfileimpl(self, name, srcs, deps, suffix, commands, label, "cfile", cflags)
@Rule
def cxxfile(
self,
name,
srcs: Targets = None,
deps: Targets = None,
cflags=[],
suffix=".o",
toolchain=Toolchain,
commands=None,
label=None,
):
if not label:
label = toolchain.label + "CXX"
if not commands:
commands = toolchain.cxxfile
cfileimpl(
self, name, srcs, deps, suffix, commands, label, "cxxfile", cflags
)
def findsources(name, srcs, deps, cflags, toolchain, filerule, cwd):
headers = filenamesmatchingof(srcs, "*.h")
cflags = cflags + ["-I" + dirname(h) for h in headers]
for d in deps:
headers += d.args.get("cheaders", [d])
objs = []
for s in flatten(srcs):
objs += [
filerule(
name=join(name, f.removeprefix("$(OBJ)/")),
srcs=[f],
deps=headers,
cflags=cflags,
toolchain=toolchain,
cwd=cwd,
)
for f in filenamesof([s])
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]
return objs
@Rule
def cheaders(
self,
name,
hdrs: TargetsMap = None,
caller_cflags=[],
deps: Targets = None,
):
hdr_deps = []
for d in deps:
hdr_deps += d.args.get("cheaders", [d])
hdr_caller_cflags = collectattrs(
targets=hdr_deps, name="caller_cflags", initial=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
r = simplerule(
replaces=self,
ins=ins,
outs=outs,
commands=cs,
deps=hdr_deps,
label="CHEADERS",
args={"caller_cflags": hdr_caller_cflags + ["-I" + self.dir]},
)
def libraryimpl(
self,
name,
srcs,
deps,
hdrs,
caller_cflags,
caller_ldflags,
cflags,
ldflags,
toolchain,
commands,
label,
kind,
):
hr = None
if hdrs and not srcs:
cheaders(
replaces=self,
hdrs=hdrs,
deps=deps,
caller_cflags=caller_cflags,
)
return
if hdrs:
hr = cheaders(
name=self.localname + "_hdrs",
hdrs=hdrs,
deps=deps,
caller_cflags=caller_cflags,
)
hr.materialise()
deps = deps + [hr]
objs = findsources(
self.localname,
srcs,
deps,
cflags,
toolchain,
kind,
self.cwd,
)
simplerule(
replaces=self,
ins=objs,
outs=[f"={self.localname}.a"],
label=label,
commands=commands,
args={
"caller_ldflags": collectattrs(
targets=deps, name="caller_ldflags", initial=caller_ldflags
),
}
| (
{"cheaders": [hr], "caller_cflags": hr.args["caller_cflags"]}
if hr
else {}
),
traits={"cheaders"},
)
self.outs = self.outs + (hr.outs if hr else [])
@Rule
def clibrary(
self,
name,
srcs: Targets = None,
deps: Targets = None,
hdrs: TargetsMap = None,
caller_cflags=[],
caller_ldflags=[],
cflags=[],
ldflags=[],
toolchain=Toolchain,
commands=None,
label=None,
cfilerule=cfile,
):
if not label:
label = toolchain.label + "LIB"
if not commands:
commands = toolchain.clibrary
libraryimpl(
self,
name,
srcs,
deps,
hdrs,
caller_cflags,
caller_ldflags,
cflags,
ldflags,
toolchain,
commands,
label,
cfilerule,
)
@Rule
def cxxlibrary(
self,
name,
srcs: Targets = None,
deps: Targets = None,
hdrs: TargetsMap = None,
caller_cflags=[],
caller_ldflags=[],
cflags=[],
ldflags=[],
toolchain=Toolchain,
commands=None,
label=None,
):
if not label:
label = toolchain.label + "LIB"
if not commands:
commands = toolchain.clibrary
libraryimpl(
self,
name,
srcs,
deps,
hdrs,
caller_cflags,
caller_ldflags,
cflags,
ldflags,
toolchain,
commands,
label,
cxxfile,
)
def programimpl(
self,
name,
srcs,
deps,
cflags,
ldflags,
toolchain,
commands,
label,
filerule,
kind,
):
ars = filenamesmatchingof(deps, "*.a")
cfiles = findsources(
self.localname, srcs, deps, cflags, toolchain, filerule, self.cwd
)
simplerule(
replaces=self,
ins=cfiles + ars + ars,
outs=[f"={self.localname}$(EXT)"],
deps=deps,
label=toolchain.label + label,
commands=commands,
args={
"ldflags": collectattrs(
targets=deps, name="caller_ldflags", initial=ldflags
)
},
)
@Rule
def cprogram(
self,
name,
srcs: Targets = None,
deps: Targets = None,
cflags=[],
ldflags=[],
toolchain=Toolchain,
commands=None,
label="CLINK",
cfilerule=cfile,
cfilekind="cprogram",
):
if not commands:
commands = toolchain.cprogram
programimpl(
self,
name,
srcs,
deps,
cflags,
ldflags,
toolchain,
commands,
label,
cfilerule,
cfilekind,
)
@Rule
def cxxprogram(
self,
name,
srcs: Targets = None,
deps: Targets = None,
cflags=[],
ldflags=[],
toolchain=Toolchain,
commands=None,
label="CXXLINK",
):
if not commands:
commands = toolchain.cxxprogram
programimpl(
self,
name,
srcs,
deps,
cflags,
ldflags,
toolchain,
commands,
label,
cxxfile,
"cxxprogram",
)