diff --git a/Makefile b/Makefile index e35b3088..0d0114fb 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,8 @@ else endif export CC = gcc - export CXX = g++ -std=c++20 + export CXX = g++ -std=c++20 \ + -Wno-deprecated-declarations export CFLAGS export CXXFLAGS export LDFLAGS diff --git a/build/_sandbox.py b/build/_sandbox.py index 2450c537..f7667a68 100644 --- a/build/_sandbox.py +++ b/build/_sandbox.py @@ -26,7 +26,7 @@ def main(): print("link", sf) os.makedirs(dirname(sf), exist_ok=True) try: - os.link(abspath(f), sf) + os.symlink(abspath(f), sf) except PermissionError: shutil.copy(f, sf) @@ -38,6 +38,11 @@ def main(): df = dirname(f) if df: os.makedirs(df, exist_ok=True) + + try: + os.remove(f) + except FileNotFoundError: + pass os.rename(sf, f) diff --git a/build/ab.mk b/build/ab.mk index fa622330..4226f069 100644 --- a/build/ab.mk +++ b/build/ab.mk @@ -1,23 +1,28 @@ 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) +ifeq ($(MAKENOT4),yes) $(error You need GNU Make 4.x for this (if you're on OSX, use gmake).) endif OBJ ?= .obj PYTHON ?= python3 -CC ?= gcc -CXX ?= g++ -AR ?= ar -CFLAGS ?= -g -Og -LDFLAGS ?= -g PKG_CONFIG ?= pkg-config HOST_PKG_CONFIG ?= $(PKG_CONFIG) ECHO ?= echo CP ?= cp +HOSTCC ?= gcc +HOSTCXX ?= g++ +HOSTAR ?= ar +HOSTCFLAGS ?= -g -Og +HOSTLDFLAGS ?= -g + +CC ?= $(HOSTCC) +CXX ?= $(HOSTCXX) +AR ?= $(HOSTAR) +CFLAGS ?= $(HOSTCFLAGS) +LDFLAGS ?= $(HOSTLDFLAGS) + export PKG_CONFIG export HOST_PKG_CONFIG @@ -31,6 +36,11 @@ else endif endif +# If enabled, shows a nice display of how far through the build you are. This +# doubles Make startup time. Also, on Make 4.3 and above, rebuilds don't show +# correct progress information. +AB_ENABLE_PROGRESS_INFO ?= true + WINDOWS := no OSX := no LINUX := no @@ -53,13 +63,17 @@ EXT ?= CWD=$(shell pwd) -ifeq ($(PROGRESSINFO),) -# 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 = "[$(ruleindex)/$(rulecount)]$(eval ruleindex := $(shell expr $(ruleindex) + 1))" +ifeq ($(AB_ENABLE_PROGRESS_INFO),true) + ifeq ($(PROGRESSINFO),) + # 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 = "[$(ruleindex)/$(rulecount)]$(eval ruleindex := $(shell expr $(ruleindex) + 1)) " + endif +else + PROGRESSINFO = "" endif PKG_CONFIG_HASHES = $(OBJ)/.pkg-config-hashes/target-$(word 1, $(shell $(PKG_CONFIG) --list-all | md5sum)) diff --git a/build/ab.py b/build/ab.py index bc8fc21d..9870400e 100644 --- a/build/ab.py +++ b/build/ab.py @@ -6,7 +6,6 @@ from copy import copy import functools import importlib -import importlib.abc import importlib.util from importlib.machinery import ( SourceFileLoader, @@ -21,6 +20,8 @@ import ast from collections import namedtuple +VERBOSE_MK_FILE = False + verbose = False quiet = False cwdStack = [""] @@ -28,6 +29,8 @@ unmaterialisedTargets = {} # dict, not set, to get consistent ordering materialisingStack = [] defaultGlobals = {} +globalId = 1 +wordCache = {} RE_FORMAT_SPEC = re.compile( r"(?:(?P[\s\S])?(?P[<>=^]))?" @@ -157,7 +160,8 @@ def wrapper(*, name=None, replaces=None, **kwargs): t.callback = func t.traits.add(func.__name__) if "args" in kwargs: - t.args.update(kwargs["args"]) + t.explicit_args = kwargs["args"] + t.args.update(t.explicit_args) del kwargs["args"] if "traits" in kwargs: t.traits |= kwargs["traits"] @@ -406,8 +410,17 @@ def _removesuffix(self, suffix): def loadbuildfile(filename): - filename = _removesuffix(filename.replace("/", "."), ".py") - builtins.__import__(filename) + modulename = _removesuffix(filename.replace("/", "."), ".py") + if modulename not in sys.modules: + spec = importlib.util.spec_from_file_location( + name=modulename, + location=filename, + loader=BuildFileLoaderImpl(fullname=modulename, path=filename), + submodule_search_locations=[], + ) + module = importlib.util.module_from_spec(spec) + sys.modules[modulename] = module + spec.loader.exec_module(module) def flatten(items): @@ -433,6 +446,7 @@ def filenamesof(items): def generate(xs): for x in xs: if isinstance(x, Target): + x.materialise() yield from generate(x.outs) else: yield x @@ -458,63 +472,67 @@ def emit(*args, into=None): def emit_rule(self, ins, outs, cmds=[], label=None): name = self.name - fins = set(filenamesof(ins)) + fins_list = filenamesof(ins) + fins = set(fins_list) fouts = filenamesof(outs) nonobjs = [f for f in fouts if not f.startswith("$(OBJ)")] emit("") + if VERBOSE_MK_FILE: + for k, v in self.args.items(): + emit(f"# {k} = {v}") lines = [] if nonobjs: emit("clean::", into=lines) emit("\t$(hide) rm -f", *nonobjs, into=lines) + hashable = cmds + fins_list + fouts + hash = hashlib.sha1(bytes("\n".join(hashable), "utf-8")).hexdigest() + hashfile = join(self.dir, f"hash_{hash}") + + global globalId emit(".PHONY:", name, into=lines) if outs: - emit(name, ":", *fouts, 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) + outsn = globalId + globalId = globalId + 1 + insn = globalId + globalId = globalId + 1 + + emit(f"OUTS_{outsn}", "=", *fouts, into=lines) + emit(f"INS_{insn}", "=", *fins, into=lines) + emit(name, ":", f"$(OUTS_{outsn})") + emit(hashfile, ":") + emit(f"\t@mkdir -p {self.dir}") + emit(f"\t@touch {hashfile}") + emit(f"$(OUTS_{outsn})", "&:",f"$(INS_{insn})", hashfile, into=lines) if label: - emit("\t$(hide)", "$(ECHO) $(PROGRESSINFO)", label, into=lines) + emit("\t$(hide)", "$(ECHO) $(PROGRESSINFO)" + label, into=lines) sandbox = join(self.dir, "sandbox") emit("\t$(hide)", f"rm -rf {sandbox}", into=lines) emit( "\t$(hide)", - f"$(PYTHON) build/_sandbox.py --link -s {sandbox}", - *fins, + "$(PYTHON) build/_sandbox.py --link -s", + sandbox, + f"$(INS_{insn})", into=lines, ) for c in cmds: emit(f"\t$(hide) cd {sandbox} && (", c, ")", into=lines) emit( "\t$(hide)", - f"$(PYTHON) build/_sandbox.py --export -s {sandbox}", - *fouts, + "$(PYTHON) build/_sandbox.py --export -s", + sandbox, + f"$(OUTS_{outsn})", into=lines, ) else: assert len(cmds) == 0, "rules with no outputs cannot have commands" emit(name, ":", *fins, into=lines) - cmd = "".join(lines) - hash = hashlib.sha1(bytes(cmd, "utf-8")).hexdigest() - - outputFp.write(cmd.replace("\x01", f"$(OBJ)/.hashes/{hash}")) - - if outs: - emit(f"$(OBJ)/.hashes/{hash}:") - emit( - f"\t$(hide) mkdir -p $(OBJ)/.hashes && touch $(OBJ)/.hashes/{hash}" - ) + outputFp.write("".join(lines)) emit("") @@ -578,13 +596,12 @@ def export(self, name=None, items: TargetsMap = {}, deps: Targets = []): ) subrule.materialise() - simplerule( - replaces=self, - ins=outs + deps, - outs=["=sentinel"], - commands=["touch $[outs[0]]"], - label="EXPORT", - ) + self.ins = [] + self.outs = deps + outs + + emit("") + emit(".PHONY:", name) + emit(name, ":", *filenamesof(outs + deps)) def main(): diff --git a/build/c.py b/build/c.py index 658def28..21050393 100644 --- a/build/c.py +++ b/build/c.py @@ -9,6 +9,7 @@ emit, ) from build.utils import filenamesmatchingof, stripext, collectattrs +from build.toolchain import Toolchain, HostToolchain from os.path import * emit( @@ -20,6 +21,71 @@ """ ) +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]] $(CFLAGS) $[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) @@ -36,10 +102,18 @@ def _indirect(deps, name): return r -def cfileimpl(self, name, srcs, deps, suffix, commands, label, cflags): +def cfileimpl( + self, name, srcs, deps, suffix, commands, label, toolchain, cflags +): outleaf = "=" + stripext(basename(filenameof(srcs[0]))) + suffix - hdr_deps = _indirect(deps, "cheader_deps") + 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 ) @@ -47,7 +121,7 @@ def cfileimpl(self, name, srcs, deps, suffix, commands, label, cflags): t = simplerule( replaces=self, ins=srcs, - deps=sorted(_indirect(hdr_deps, "cheader_files")), + deps=other_deps + hdr_files, outs=[outleaf], label=label, commands=commands, @@ -63,10 +137,20 @@ def cfile( deps: Targets = None, cflags=[], suffix=".o", - commands=["$(CC) -c -o $[outs[0]] $[ins[0]] $(CFLAGS) $[cflags]"], + toolchain=Toolchain, label="CC", ): - cfileimpl(self, name, srcs, deps, suffix, commands, label, cflags) + cfileimpl( + self, + name, + srcs, + deps, + suffix, + toolchain.CC, + toolchain.PREFIX + label, + toolchain, + cflags, + ) @Rule @@ -77,10 +161,20 @@ def cxxfile( deps: Targets = None, cflags=[], suffix=".o", - commands=["$(CXX) -c -o $[outs[0]] $[ins[0]] $(CFLAGS) $[cflags]"], + toolchain=Toolchain, label="CXX", ): - cfileimpl(self, name, srcs, deps, suffix, commands, label, cflags) + cfileimpl( + self, + name, + srcs, + deps, + suffix, + toolchain.CXX, + toolchain.PREFIX + label, + toolchain, + cflags, + ) def _removeprefix(self, prefix): @@ -90,21 +184,9 @@ def _removeprefix(self, prefix): return self[:] -def _isSourceFile(f): - return ( - 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") - ) - - -def findsources(name, srcs, deps, cflags, filerule, cwd): +def findsources(self, srcs, deps, cflags, filerule, toolchain, cwd): for f in filenamesof(srcs): - if not _isSourceFile(f): + if not toolchain.is_source_file(f): cflags = cflags + [f"-I{dirname(f)}"] deps = deps + [f] @@ -112,14 +194,16 @@ def findsources(name, srcs, deps, cflags, filerule, cwd): for s in flatten(srcs): objs += [ filerule( - name=join(name, _removeprefix(f, "$(OBJ)/")), + name=join(self.localname, _removeprefix(f, "$(OBJ)/")), srcs=[f], deps=deps, cflags=sorted(set(cflags)), + toolchain=toolchain, cwd=cwd, + args=getattr(self, "explicit_args", {}), ) for f in filenamesof([s]) - if _isSourceFile(f) + if toolchain.is_source_file(f) ] if any(f.endswith(".o") for f in filenamesof([s])): objs += [s] @@ -137,12 +221,13 @@ def libraryimpl( caller_ldflags, cflags, ldflags, + toolchain, commands, label, filerule, ): - hdr_deps = _combine(_indirect(deps, "cheader_deps"), [self]) - lib_deps = _combine(_indirect(deps, "clibrary_deps"), [self]) + hdr_deps = toolchain.find_c_header_targets(deps) + [self] + lib_deps = toolchain.find_c_library_targets(deps) + [self] hr = None hf = [] @@ -167,18 +252,22 @@ def libraryimpl( ins=ins, outs=outs, commands=cs, - label="CHEADERS", + label=toolchain.PREFIX + "CHEADERS", ) - hr.materialise() + 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.localname, + self, srcs, deps + ([hr] if hr else []), cflags + hf, filerule, + toolchain, self.cwd, ) @@ -186,6 +275,7 @@ def libraryimpl( name=f"{self.localname}_lib", ins=objs, outs=[f"={self.localname}.a"], + deps=deps, label=label, commands=commands, ) @@ -212,7 +302,7 @@ def clibrary( caller_ldflags=[], cflags=[], ldflags=[], - commands=["rm -f $[outs[0]] && $(AR) cqs $[outs[0]] $[ins]"], + toolchain=Toolchain, label="LIB", cfilerule=cfile, ): @@ -226,8 +316,41 @@ def clibrary( caller_ldflags, cflags, ldflags, - commands, - label, + 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, ) @@ -243,7 +366,39 @@ def cxxlibrary( caller_ldflags=[], cflags=[], ldflags=[], - commands=["rm -f $[outs[0]] && $(AR) cqs $[outs[0]] $[ins]"], + 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, ): @@ -257,8 +412,9 @@ def cxxlibrary( caller_ldflags, cflags, ldflags, - commands, - label, + toolchain, + toolchain.ARXX, + toolchain.PREFIX + label, cxxfilerule, ) @@ -270,16 +426,17 @@ def programimpl( deps, cflags, ldflags, + toolchain, commands, label, filerule, ): - cfiles = findsources(self.localname, srcs, deps, cflags, filerule, self.cwd) + cfiles = findsources( + self, srcs, deps, cflags, filerule, toolchain, self.cwd + ) - lib_deps = [] - for d in deps: - lib_deps = _combine(lib_deps, d.args.get("clibrary_deps", {d})) - libs = filenamesmatchingof(lib_deps, "*.a") + 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 ) @@ -288,14 +445,10 @@ def programimpl( replaces=self, ins=cfiles + libs, outs=[f"={self.localname}$(EXT)"], - deps=_indirect(lib_deps, "clibrary_files"), + deps=deps, label=label, commands=commands, - args={ - "ldflags": collectattrs( - targets=lib_deps, name="caller_ldflags", initial=ldflags - ) - }, + args={"ldflags": ldflags}, ) @@ -307,9 +460,33 @@ def cprogram( deps: Targets = None, cflags=[], ldflags=[], - commands=[ - "$(CC) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(LDFLAGS) $(ENDGROUP)" - ], + 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, ): @@ -320,8 +497,9 @@ def cprogram( deps, cflags, ldflags, - commands, - label, + toolchain, + toolchain.CLINK, + toolchain.PREFIX + label, cfilerule, ) @@ -334,9 +512,7 @@ def cxxprogram( deps: Targets = None, cflags=[], ldflags=[], - commands=[ - "$(CXX) -o $[outs[0]] $(STARTGROUP) $[ins] $[ldflags] $(LDFLAGS) $(ENDGROUP)" - ], + toolchain=Toolchain, label="CXXLINK", cxxfilerule=cxxfile, ): @@ -347,7 +523,75 @@ def cxxprogram( deps, cflags, ldflags, - commands, - label, + 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) diff --git a/build/pkg.py b/build/pkg.py index d7f0376a..6103e716 100644 --- a/build/pkg.py +++ b/build/pkg.py @@ -1,5 +1,4 @@ -from build.ab import Rule, emit, Target, filenamesof -from types import SimpleNamespace +from build.ab import Rule, Target import os import subprocess @@ -33,6 +32,7 @@ def get_property(self, name, flag): TargetPkgConfig = _PkgConfig(os.getenv("PKG_CONFIG")) +HostPkgConfig = _PkgConfig(os.getenv("HOST_PKG_CONFIG")) def _package(self, name, package, fallback, pkgconfig): @@ -44,8 +44,9 @@ def _package(self, name, package, fallback, pkgconfig): self.args["caller_cflags"] = [cflags] if ldflags: self.args["caller_ldflags"] = [ldflags] - self.traits.add("clibrary") - self.traits.add("cheaders") + self.args["clibrary_deps"] = [self] + self.args["cheader_deps"] = [self] + self.traits.update({"clibrary", "cxxlibrary"}) return assert ( @@ -69,3 +70,16 @@ def _package(self, name, package, fallback, pkgconfig): @Rule def package(self, name, package=None, fallback: Target = None): _package(self, name, package, fallback, TargetPkgConfig) + + +@Rule +def hostpackage(self, name, package=None, fallback: Target = None): + _package(self, name, package, fallback, HostPkgConfig) + + +def has_package(name): + return TargetPkgConfig.has_package(name) + + +def has_host_package(name): + return HostPkgConfig.has_package(name) diff --git a/build/toolchain.py b/build/toolchain.py new file mode 100644 index 00000000..b47d3e8a --- /dev/null +++ b/build/toolchain.py @@ -0,0 +1,6 @@ +class Toolchain: + PREFIX = "" + + +class HostToolchain(Toolchain): + PREFIX = "HOST" diff --git a/build/utils.py b/build/utils.py index 077fc089..53a85e0d 100644 --- a/build/utils.py +++ b/build/utils.py @@ -11,7 +11,6 @@ from os.path import relpath, splitext, join, basename, isfile from glob import iglob import fnmatch -import itertools def filenamesmatchingof(xs, pattern): @@ -78,7 +77,7 @@ def test( replaces=self, ins=[command], outs=["=sentinel"], - commands=["$[ins[0]]", "touch {outs}"], + commands=["$[ins[0]]", "touch $[outs[0]]"], deps=deps, label=label, ) @@ -87,7 +86,7 @@ def test( replaces=self, ins=ins, outs=["=sentinel"], - commands=commands + ["touch {outs}"], + commands=commands + ["touch $[outs[0]]"], deps=deps, label=label, )