mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -07:00
581 lines
12 KiB
Python
581 lines
12 KiB
Python
from build.ab import (
|
|
Rule,
|
|
Targets,
|
|
TargetsMap,
|
|
filenameof,
|
|
filenamesof,
|
|
flatten,
|
|
simplerule,
|
|
emit,
|
|
G,
|
|
)
|
|
from build.utils import stripext, collectattrs
|
|
from build.toolchain import Toolchain, HostToolchain
|
|
from os.path import *
|
|
|
|
if G.OSX != "yes":
|
|
G.STARTGROUP = "-Wl,--start-group"
|
|
G.ENDGROUP = "-Wl,--end-group"
|
|
else:
|
|
G.STARTGROUP = ""
|
|
G.ENDGROUP = ""
|
|
|
|
Toolchain.CC = ["$(CC) -c -o $[outs[0]] $[ins[0]] $(CFLAGS) $[cflags]"]
|
|
Toolchain.CPP = ["$(CC) -E -P -o $[outs] $[cflags] -x c $[ins]"]
|
|
Toolchain.CXX = ["$(CXX) -c -o $[outs[0]] $[ins[0]] $(CXXFLAGS) $[cflags]"]
|
|
Toolchain.AR = ["$(AR) cqs $[outs[0]] $[ins]"]
|
|
Toolchain.ARXX = ["$(AR) cqs $[outs[0]] $[ins]"]
|
|
Toolchain.CLINK = [
|
|
"$(CC) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(LDFLAGS) $(ENDGROUP)"
|
|
]
|
|
Toolchain.CXXLINK = [
|
|
"$(CXX) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(LDFLAGS) $(ENDGROUP)"
|
|
]
|
|
|
|
Toolchain.is_source_file = (
|
|
lambda f: f.endswith(".c")
|
|
or f.endswith(".cc")
|
|
or f.endswith(".cpp")
|
|
or f.endswith(".S")
|
|
or f.endswith(".s")
|
|
or f.endswith(".m")
|
|
or f.endswith(".mm")
|
|
)
|
|
|
|
|
|
# Given a set of dependencies, finds the set of relevant library targets (i.e.
|
|
# contributes *.a files) for compiling C programs. The actual list of libraries
|
|
# is in dep.clibrary_files.
|
|
def _toolchain_find_library_targets(deps):
|
|
lib_deps = []
|
|
for d in deps:
|
|
lib_deps = _combine(lib_deps, d.args.get("clibrary_deps", []))
|
|
return lib_deps
|
|
|
|
|
|
Toolchain.find_c_library_targets = _toolchain_find_library_targets
|
|
|
|
|
|
# Given a set of dependencies, finds the set of relevant header targets (i.e.
|
|
# contributes *.h files) for compiling C programs. The actual list of libraries
|
|
# is in dep.cheader_files.
|
|
def _toolchain_find_header_targets(deps, initial=[]):
|
|
hdr_deps = initial
|
|
for d in deps:
|
|
hdr_deps = _combine(hdr_deps, d.args.get("cheader_deps", []))
|
|
return hdr_deps
|
|
|
|
|
|
Toolchain.find_c_header_targets = _toolchain_find_header_targets
|
|
|
|
|
|
HostToolchain.CC = ["$(HOSTCC) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]"]
|
|
HostToolchain.CPP = ["$(HOSTCC) -E -P -o $[outs] $[cflags] -x c $[ins]"]
|
|
HostToolchain.CXX = ["$(HOSTCXX) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]"]
|
|
HostToolchain.AR = ["$(HOSTAR) cqs $[outs[0]] $[ins]"]
|
|
HostToolchain.ARXX = ["$(HOSTAR) cqs $[outs[0]] $[ins]"]
|
|
HostToolchain.CLINK = [
|
|
"$(HOSTCC) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(HOSTLDFLAGS) $(ENDGROUP)"
|
|
]
|
|
HostToolchain.CXXLINK = [
|
|
"$(HOSTCXX) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(HOSTLDFLAGS) $(ENDGROUP)"
|
|
]
|
|
|
|
|
|
def _combine(list1, list2):
|
|
r = list(list1)
|
|
for i in list2:
|
|
if i not in r:
|
|
r.append(i)
|
|
return r
|
|
|
|
|
|
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, toolchain, cflags):
|
|
outleaf = "=" + stripext(basename(filenameof(srcs[0]))) + suffix
|
|
|
|
hdr_deps = toolchain.find_c_header_targets(deps)
|
|
other_deps = [
|
|
d
|
|
for d in deps
|
|
if ("cheader_deps" not in d.args) and ("clibrary_deps" not in d.args)
|
|
]
|
|
hdr_files = collectattrs(targets=hdr_deps, name="cheader_files")
|
|
cflags = collectattrs(targets=hdr_deps, name="caller_cflags", initial=cflags)
|
|
|
|
t = simplerule(
|
|
replaces=self,
|
|
ins=srcs,
|
|
deps=other_deps + hdr_files,
|
|
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,
|
|
label="CC",
|
|
):
|
|
cfileimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
suffix,
|
|
toolchain.CC,
|
|
toolchain.PREFIX + label,
|
|
toolchain,
|
|
cflags,
|
|
)
|
|
|
|
|
|
@Rule
|
|
def cxxfile(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
cflags=[],
|
|
suffix=".o",
|
|
toolchain=Toolchain,
|
|
label="CXX",
|
|
):
|
|
cfileimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
suffix,
|
|
toolchain.CXX,
|
|
toolchain.PREFIX + label,
|
|
toolchain,
|
|
cflags,
|
|
)
|
|
|
|
|
|
def _removeprefix(self, prefix):
|
|
if self.startswith(prefix):
|
|
return self[len(prefix) :]
|
|
else:
|
|
return self[:]
|
|
|
|
|
|
def findsources(self, srcs, deps, cflags, filerule, toolchain, cwd):
|
|
for f in filenamesof(srcs):
|
|
if not toolchain.is_source_file(f):
|
|
cflags = cflags + [f"-I{dirname(f)}"]
|
|
deps = deps + [f]
|
|
|
|
objs = []
|
|
for s in flatten(srcs):
|
|
objs += [
|
|
filerule(
|
|
name=join(self.localname, _removeprefix(f, G.OBJ + "/")),
|
|
srcs=[f],
|
|
deps=deps,
|
|
cflags=sorted(set(cflags)),
|
|
toolchain=toolchain,
|
|
cwd=cwd,
|
|
args=getattr(self, "explicit_args", {}),
|
|
)
|
|
for f in filenamesof([s])
|
|
if toolchain.is_source_file(f)
|
|
]
|
|
if any(f.endswith(".o") for f in filenamesof([s])):
|
|
objs += [s]
|
|
|
|
return objs
|
|
|
|
|
|
def libraryimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
hdrs,
|
|
caller_cflags,
|
|
caller_ldflags,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
commands,
|
|
label,
|
|
filerule,
|
|
):
|
|
hdr_deps = toolchain.find_c_header_targets(deps) + [self]
|
|
lib_deps = toolchain.find_c_library_targets(deps) + [self]
|
|
|
|
hr = None
|
|
hf = []
|
|
ar = None
|
|
if hdrs:
|
|
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 += [f"$(CP) $[ins[{i}]] $[outs[{i}]]"]
|
|
outs += ["=" + dest]
|
|
i = i + 1
|
|
|
|
hr = simplerule(
|
|
name=f"{self.localname}_hdr",
|
|
ins=ins,
|
|
outs=outs,
|
|
commands=cs,
|
|
label=toolchain.PREFIX + "CHEADERS",
|
|
)
|
|
hr.args["cheader_deps"] = [hr]
|
|
hr.args["cheader_files"] = [hr]
|
|
hf = [f"-I{hr.dir}"]
|
|
|
|
if srcs:
|
|
# Can't depend on the current target to get the library headers, because
|
|
# if we do it'll cause a dependency loop.
|
|
objs = findsources(
|
|
self,
|
|
srcs,
|
|
deps + ([hr] if hr else []),
|
|
cflags + hf,
|
|
filerule,
|
|
toolchain,
|
|
self.cwd,
|
|
)
|
|
|
|
ar = simplerule(
|
|
name=f"{self.localname}_lib",
|
|
ins=objs,
|
|
outs=[f"={self.localname}.a"],
|
|
deps=deps,
|
|
label=label,
|
|
commands=commands,
|
|
)
|
|
ar.materialise()
|
|
|
|
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
|
|
def clibrary(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
hdrs: TargetsMap = None,
|
|
caller_cflags=[],
|
|
caller_ldflags=[],
|
|
cflags=[],
|
|
ldflags=[],
|
|
toolchain=Toolchain,
|
|
label="LIB",
|
|
cfilerule=cfile,
|
|
):
|
|
libraryimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
hdrs,
|
|
caller_cflags,
|
|
caller_ldflags,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
toolchain.AR,
|
|
toolchain.PREFIX + label,
|
|
cfilerule,
|
|
)
|
|
|
|
|
|
@Rule
|
|
def hostclibrary(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
hdrs: TargetsMap = None,
|
|
caller_cflags=[],
|
|
caller_ldflags=[],
|
|
cflags=[],
|
|
ldflags=[],
|
|
toolchain=HostToolchain,
|
|
label="LIB",
|
|
cfilerule=cfile,
|
|
):
|
|
libraryimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
hdrs,
|
|
caller_cflags,
|
|
caller_ldflags,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
toolchain.AR,
|
|
toolchain.PREFIX + label,
|
|
cfilerule,
|
|
)
|
|
|
|
|
|
@Rule
|
|
def cxxlibrary(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
hdrs: TargetsMap = None,
|
|
caller_cflags=[],
|
|
caller_ldflags=[],
|
|
cflags=[],
|
|
ldflags=[],
|
|
toolchain=Toolchain,
|
|
label="CXXLIB",
|
|
cxxfilerule=cxxfile,
|
|
):
|
|
libraryimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
hdrs,
|
|
caller_cflags,
|
|
caller_ldflags,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
toolchain.ARXX,
|
|
toolchain.PREFIX + label,
|
|
cxxfilerule,
|
|
)
|
|
|
|
|
|
@Rule
|
|
def hostcxxlibrary(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
hdrs: TargetsMap = None,
|
|
caller_cflags=[],
|
|
caller_ldflags=[],
|
|
cflags=[],
|
|
ldflags=[],
|
|
toolchain=HostToolchain,
|
|
label="CXXLIB",
|
|
cxxfilerule=cxxfile,
|
|
):
|
|
libraryimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
hdrs,
|
|
caller_cflags,
|
|
caller_ldflags,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
toolchain.ARXX,
|
|
toolchain.PREFIX + label,
|
|
cxxfilerule,
|
|
)
|
|
|
|
|
|
def programimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
commands,
|
|
label,
|
|
filerule,
|
|
):
|
|
cfiles = findsources(self, srcs, deps, cflags, filerule, toolchain, self.cwd)
|
|
|
|
lib_deps = toolchain.find_c_library_targets(deps)
|
|
libs = collectattrs(targets=lib_deps, name="clibrary_files")
|
|
ldflags = collectattrs(targets=lib_deps, name="caller_ldflags", initial=ldflags)
|
|
|
|
simplerule(
|
|
replaces=self,
|
|
ins=cfiles + libs,
|
|
outs=[f"={self.localname}{toolchain.EXE}"],
|
|
deps=deps,
|
|
label=label,
|
|
commands=commands,
|
|
args={"ldflags": ldflags},
|
|
)
|
|
|
|
|
|
@Rule
|
|
def cprogram(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
cflags=[],
|
|
ldflags=[],
|
|
toolchain=Toolchain,
|
|
label="CLINK",
|
|
cfilerule=cfile,
|
|
):
|
|
programimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
toolchain.CLINK,
|
|
toolchain.PREFIX + label,
|
|
cfilerule,
|
|
)
|
|
|
|
|
|
@Rule
|
|
def hostcprogram(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
cflags=[],
|
|
ldflags=[],
|
|
toolchain=HostToolchain,
|
|
label="CLINK",
|
|
cfilerule=cfile,
|
|
):
|
|
programimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
toolchain.CLINK,
|
|
toolchain.PREFIX + label,
|
|
cfilerule,
|
|
)
|
|
|
|
|
|
@Rule
|
|
def cxxprogram(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
cflags=[],
|
|
ldflags=[],
|
|
toolchain=Toolchain,
|
|
label="CXXLINK",
|
|
cxxfilerule=cxxfile,
|
|
):
|
|
programimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
toolchain.CXXLINK,
|
|
toolchain.PREFIX + label,
|
|
cxxfilerule,
|
|
)
|
|
|
|
|
|
@Rule
|
|
def hostcxxprogram(
|
|
self,
|
|
name,
|
|
srcs: Targets = None,
|
|
deps: Targets = None,
|
|
cflags=[],
|
|
ldflags=[],
|
|
toolchain=HostToolchain,
|
|
label="CXXLINK",
|
|
cxxfilerule=cxxfile,
|
|
):
|
|
programimpl(
|
|
self,
|
|
name,
|
|
srcs,
|
|
deps,
|
|
cflags,
|
|
ldflags,
|
|
toolchain,
|
|
toolchain.CXXLINK,
|
|
toolchain.PREFIX + label,
|
|
cxxfilerule,
|
|
)
|
|
|
|
|
|
def _cppfileimpl(self, name, srcs, deps, cflags, toolchain):
|
|
hdr_deps = _indirect(deps, "cheader_deps")
|
|
cflags = collectattrs(targets=hdr_deps, name="caller_cflags", initial=cflags)
|
|
|
|
simplerule(
|
|
replaces=self,
|
|
ins=srcs,
|
|
outs=[f"={self.localname}"],
|
|
deps=deps,
|
|
commands=toolchain.CPP,
|
|
args={"cflags": cflags},
|
|
label=toolchain.PREFIX + "CPPFILE",
|
|
)
|
|
|
|
|
|
@Rule
|
|
def cppfile(
|
|
self,
|
|
name,
|
|
srcs: Targets = [],
|
|
deps: Targets = [],
|
|
cflags=[],
|
|
toolchain=Toolchain,
|
|
):
|
|
_cppfileimpl(self, name, srcs, deps, cflags, toolchain)
|
|
|
|
|
|
@Rule
|
|
def hostcppfile(
|
|
self,
|
|
name,
|
|
srcs: Targets = [],
|
|
deps: Targets = [],
|
|
cflags=[],
|
|
toolchain=HostToolchain,
|
|
):
|
|
_cppfileimpl(self, name, srcs, deps, cflags, toolchain)
|