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