mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -07:00
Merge pull request #824 from davidgiven/ab
Update ab to the new ninja version.
This commit is contained in:
2
.github/workflows/ccpp.yml
vendored
2
.github/workflows/ccpp.yml
vendored
@@ -88,7 +88,7 @@ jobs:
|
||||
wsl --import fedora fedora install.tar.gz
|
||||
wsl --set-default fedora
|
||||
wsl sh -c 'dnf -y install https://github.com/rpmsphere/noarch/raw/master/r/rpmsphere-release-40-1.noarch.rpm'
|
||||
wsl sh -c 'dnf -y install gcc gcc-c++ protobuf-c-compiler protobuf-devel fmt-devel systemd-devel sqlite-devel wxGTK-devel mingw32-gcc mingw32-gcc-c++ mingw32-zlib-static mingw32-protobuf-static mingw32-sqlite-static mingw32-wxWidgets3-static mingw32-libpng-static mingw32-libjpeg-static mingw32-libtiff-static mingw32-nsis png2ico'
|
||||
wsl sh -c 'dnf -y install gcc gcc-c++ protobuf-c-compiler protobuf-devel fmt-devel systemd-devel sqlite-devel wxGTK-devel mingw32-gcc mingw32-gcc-c++ mingw32-zlib-static mingw32-protobuf-static mingw32-sqlite-static mingw32-wxWidgets3-static mingw32-libpng-static mingw32-libjpeg-static mingw32-libtiff-static mingw32-nsis png2ico ninja-build'
|
||||
|
||||
- name: fix line endings
|
||||
run: |
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
wsl --import fedora fedora install.tar.gz
|
||||
wsl --set-default fedora
|
||||
wsl sh -c 'dnf -y install https://github.com/rpmsphere/noarch/raw/master/r/rpmsphere-release-40-1.noarch.rpm'
|
||||
wsl sh -c 'dnf -y install gcc gcc-c++ protobuf-c-compiler protobuf-devel fmt-devel systemd-devel sqlite-devel wxGTK-devel mingw32-gcc mingw32-gcc-c++ mingw32-zlib-static mingw32-protobuf-static mingw32-sqlite-static mingw32-wxWidgets3-static mingw32-libpng-static mingw32-libjpeg-static mingw32-libtiff-static mingw32-nsis png2ico'
|
||||
wsl sh -c 'dnf -y install gcc gcc-c++ protobuf-c-compiler protobuf-devel fmt-devel systemd-devel sqlite-devel wxGTK-devel mingw32-gcc mingw32-gcc-c++ mingw32-zlib-static mingw32-protobuf-static mingw32-sqlite-static mingw32-wxWidgets3-static mingw32-libpng-static mingw32-libjpeg-static mingw32-libtiff-static mingw32-nsis png2ico ninja-build'
|
||||
|
||||
- name: fix line endings
|
||||
run: |
|
||||
|
||||
9
Makefile
9
Makefile
@@ -12,12 +12,15 @@ ifeq ($(BUILDTYPE),windows)
|
||||
MINGW = i686-w64-mingw32-
|
||||
CC = $(MINGW)gcc
|
||||
CXX = $(MINGW)g++ -std=c++20
|
||||
CFLAGS += -g -O3
|
||||
CFLAGS += -g -O3 \
|
||||
-Wno-unknown-warning-option \
|
||||
-ffunction-sections \
|
||||
-fdata-sections
|
||||
CXXFLAGS += \
|
||||
-fext-numeric-literals \
|
||||
-Wno-deprecated-enum-float-conversion \
|
||||
-Wno-deprecated-enum-enum-conversion
|
||||
LDFLAGS += -static
|
||||
LDFLAGS += -static -Wl,--gc-sections
|
||||
AR = $(MINGW)ar
|
||||
PKG_CONFIG = $(MINGW)pkg-config -static
|
||||
WINDRES = $(MINGW)windres
|
||||
@@ -27,6 +30,8 @@ else
|
||||
CC = gcc
|
||||
CXX = g++ -std=c++20
|
||||
CFLAGS = -g -O3 \
|
||||
-Wno-unknown-warning-option
|
||||
CXXFLAGS += \
|
||||
-Wno-deprecated-enum-float-conversion \
|
||||
-Wno-deprecated-enum-enum-conversion
|
||||
LDFLAGS =
|
||||
|
||||
4
build.py
4
build.py
@@ -8,7 +8,7 @@ import config
|
||||
import re
|
||||
|
||||
# Hack for building on Fedora/WSL; executables get the .exe extension,
|
||||
# build the build system detects it as Linux.
|
||||
# but the build system detects it as Linux.
|
||||
import build.toolchain
|
||||
|
||||
toolchain.Toolchain.EXE = "$(EXT)"
|
||||
@@ -93,7 +93,7 @@ else:
|
||||
+ c[1]
|
||||
+ "' '"
|
||||
+ c[2]
|
||||
+ "' $(dir $[outs[0]]) > /dev/null"
|
||||
+ "' $[dirname(filenameof(outs[0]))] > /dev/null"
|
||||
],
|
||||
label="CORPUSTEST",
|
||||
)
|
||||
|
||||
69
build/ab.mk
69
build/ab.mk
@@ -15,16 +15,17 @@ HOSTCC ?= gcc
|
||||
HOSTCXX ?= g++
|
||||
HOSTAR ?= ar
|
||||
HOSTCFLAGS ?= -g -Og
|
||||
HOSTCXXFLAGS ?= $(HOSTCFLAGS)
|
||||
HOSTLDFLAGS ?= -g
|
||||
|
||||
CC ?= $(HOSTCC)
|
||||
CXX ?= $(HOSTCXX)
|
||||
AR ?= $(HOSTAR)
|
||||
CFLAGS ?= $(HOSTCFLAGS)
|
||||
CXXFLAGS ?= $(CFLAGS)
|
||||
LDFLAGS ?= $(HOSTLDFLAGS)
|
||||
|
||||
export PKG_CONFIG
|
||||
export HOST_PKG_CONFIG
|
||||
NINJA ?= ninja
|
||||
|
||||
ifdef VERBOSE
|
||||
hide =
|
||||
@@ -63,37 +64,33 @@ EXT ?=
|
||||
|
||||
CWD=$(shell pwd)
|
||||
|
||||
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
|
||||
define newline
|
||||
|
||||
PKG_CONFIG_HASHES = $(OBJ)/.pkg-config-hashes/target-$(word 1, $(shell $(PKG_CONFIG) --list-all | md5sum))
|
||||
HOST_PKG_CONFIG_HASHES = $(OBJ)/.pkg-config-hashes/host-$(word 1, $(shell $(HOST_PKG_CONFIG) --list-all | md5sum))
|
||||
|
||||
$(OBJ)/build.mk : $(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES)
|
||||
$(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES) &:
|
||||
$(hide) rm -rf $(OBJ)/.pkg-config-hashes
|
||||
$(hide) mkdir -p $(OBJ)/.pkg-config-hashes
|
||||
$(hide) touch $(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES)
|
||||
endef
|
||||
|
||||
include $(OBJ)/build.mk
|
||||
define check_for_command
|
||||
$(shell command -v $1 >/dev/null || (echo "Required command '$1' missing" >/dev/stderr && kill $$PPID))
|
||||
endef
|
||||
|
||||
ifeq ($(OSX),yes)
|
||||
MAKEFLAGS += -r -j$(shell sysctl -n hw.logicalcpu)
|
||||
else
|
||||
MAKEFLAGS += -r -j$(shell nproc)
|
||||
endif
|
||||
$(call check_for_command,ninja)
|
||||
$(call check_for_command,cmp)
|
||||
$(call check_for_command,$(PYTHON))
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
pkg-config-hash = $(shell ($(PKG_CONFIG) --list-all && $(HOST_PKG_CONFIG) --list-all) | md5sum)
|
||||
build-files = $(shell find . -name .obj -prune -o \( -name 'build.py' -a -type f \) -print) $(wildcard build/*.py) $(wildcard config.py)
|
||||
build-file-timestamps = $(shell ls -l $(build-files) | md5sum)
|
||||
|
||||
# Wipe the build file (forcing a regeneration) if the make environment is different.
|
||||
# (Conveniently, this includes the pkg-config hash calculated above.)
|
||||
|
||||
ignored-variables = MAKE_RESTARTS .VARIABLES MAKECMDGOALS MAKEFLAGS MFLAGS
|
||||
$(shell mkdir -p $(OBJ))
|
||||
$(file >$(OBJ)/newvars.txt,$(foreach v,$(filter-out $(ignored-variables),$(.VARIABLES)),$(v)=$($(v))$(newline)))
|
||||
$(shell touch $(OBJ)/vars.txt)
|
||||
#$(shell diff -u $(OBJ)/vars.txt $(OBJ)/newvars.txt > /dev/stderr)
|
||||
$(shell cmp -s $(OBJ)/newvars.txt $(OBJ)/vars.txt || (rm -f $(OBJ)/build.ninja && echo "Environment changed --- regenerating" > /dev/stderr))
|
||||
$(shell mv $(OBJ)/newvars.txt $(OBJ)/vars.txt)
|
||||
|
||||
.PHONY: update-ab
|
||||
update-ab:
|
||||
@@ -108,9 +105,15 @@ clean::
|
||||
$(hide) rm -rf $(OBJ)
|
||||
|
||||
export PYTHONHASHSEED = 1
|
||||
build-files = $(shell find . -name 'build.py') $(wildcard build/*.py) $(wildcard config.py)
|
||||
$(OBJ)/build.mk: Makefile $(build-files) build/ab.mk
|
||||
$(OBJ)/build.ninja $(OBJ)/build.targets &:
|
||||
@echo "AB"
|
||||
@mkdir -p $(OBJ)
|
||||
$(hide) $(PYTHON) -X pycache_prefix=$(OBJ)/__pycache__ build/ab.py -o $@ build.py \
|
||||
|| rm -f $@
|
||||
$(hide) $(PYTHON) -X pycache_prefix=$(OBJ)/__pycache__ build/ab.py \
|
||||
-o $(OBJ) build.py \
|
||||
-v $(OBJ)/vars.txt \
|
||||
|| (rm -f $@ && false)
|
||||
|
||||
include $(OBJ)/build.targets
|
||||
.PHONY: $(ninja-targets)
|
||||
.NOTPARALLEL:
|
||||
$(ninja-targets): $(OBJ)/build.ninja
|
||||
+$(hide) $(NINJA) -f $(OBJ)/build.ninja $@
|
||||
|
||||
2
build/ab.ninja
Normal file
2
build/ab.ninja
Normal file
@@ -0,0 +1,2 @@
|
||||
rule rule
|
||||
command = $command
|
||||
261
build/ab.py
261
build/ab.py
@@ -1,36 +1,32 @@
|
||||
from collections import namedtuple
|
||||
from copy import copy
|
||||
from importlib.machinery import SourceFileLoader, PathFinder, ModuleSpec
|
||||
from os.path import *
|
||||
from pathlib import Path
|
||||
from typing import Iterable
|
||||
import argparse
|
||||
import ast
|
||||
import builtins
|
||||
from copy import copy
|
||||
import functools
|
||||
import hashlib
|
||||
import importlib
|
||||
import importlib.util
|
||||
from importlib.machinery import (
|
||||
SourceFileLoader,
|
||||
PathFinder,
|
||||
ModuleSpec,
|
||||
)
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
import hashlib
|
||||
import re
|
||||
import ast
|
||||
from collections import namedtuple
|
||||
import types
|
||||
|
||||
VERBOSE_MK_FILE = False
|
||||
VERBOSE_NINJA_FILE = False
|
||||
|
||||
verbose = False
|
||||
quiet = False
|
||||
cwdStack = [""]
|
||||
targets = {}
|
||||
unmaterialisedTargets = {} # dict, not set, to get consistent ordering
|
||||
materialisingStack = []
|
||||
defaultGlobals = {}
|
||||
globalId = 1
|
||||
wordCache = {}
|
||||
outputTargets = set()
|
||||
|
||||
RE_FORMAT_SPEC = re.compile(
|
||||
r"(?:(?P<fill>[\s\S])?(?P<align>[<>=^]))?"
|
||||
@@ -52,6 +48,15 @@ sys.path += ["."]
|
||||
old_import = builtins.__import__
|
||||
|
||||
|
||||
class Environment(types.SimpleNamespace):
|
||||
def setdefault(self, name, value):
|
||||
if not hasattr(self, name):
|
||||
setattr(self, name, value)
|
||||
|
||||
|
||||
G = Environment()
|
||||
|
||||
|
||||
class PathFinderImpl(PathFinder):
|
||||
def find_spec(self, fullname, path, target=None):
|
||||
# The second test here is needed for Python 3.9.
|
||||
@@ -102,27 +107,88 @@ def error(message):
|
||||
raise ABException(message)
|
||||
|
||||
|
||||
def _undo_escaped_dollar(s, op):
|
||||
return s.replace(f"$${op}", f"${op}")
|
||||
|
||||
|
||||
class BracketedFormatter(string.Formatter):
|
||||
def parse(self, format_string):
|
||||
while format_string:
|
||||
left, *right = format_string.split("$[", 1)
|
||||
if not right:
|
||||
yield (left, None, None, None)
|
||||
m = re.search(f"(?:[^$]|^)()\\$\\[()", format_string)
|
||||
if not m:
|
||||
yield (
|
||||
_undo_escaped_dollar(format_string, "["),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
break
|
||||
right = right[0]
|
||||
left = format_string[: m.start(1)]
|
||||
right = format_string[m.end(2) :]
|
||||
|
||||
offset = len(right) + 1
|
||||
try:
|
||||
ast.parse(right)
|
||||
except SyntaxError as e:
|
||||
if not str(e).startswith("unmatched ']'"):
|
||||
if not str(e).startswith(f"unmatched ']'"):
|
||||
raise e
|
||||
offset = e.offset
|
||||
|
||||
expr = right[0 : offset - 1]
|
||||
format_string = right[offset:]
|
||||
|
||||
yield (left if left else None, expr, None, None)
|
||||
yield (
|
||||
_undo_escaped_dollar(left, "[") if left else None,
|
||||
expr,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
|
||||
|
||||
class GlobalFormatter(string.Formatter):
|
||||
def parse(self, format_string):
|
||||
while format_string:
|
||||
m = re.search(f"(?:[^$]|^)()\\$\\(([^)]*)\\)()", format_string)
|
||||
if not m:
|
||||
yield (
|
||||
format_string,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
break
|
||||
left = format_string[: m.start(1)]
|
||||
var = m[2]
|
||||
format_string = format_string[m.end(3) :]
|
||||
|
||||
yield (
|
||||
left if left else None,
|
||||
var,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
|
||||
def get_field(self, name, a1, a2):
|
||||
return (
|
||||
getattr(G, name),
|
||||
False,
|
||||
)
|
||||
|
||||
def format_field(self, value, format_spec):
|
||||
if not value:
|
||||
return ""
|
||||
return str(value)
|
||||
|
||||
|
||||
globalFormatter = GlobalFormatter()
|
||||
|
||||
|
||||
def substituteGlobalVariables(value):
|
||||
while True:
|
||||
oldValue = value
|
||||
value = globalFormatter.format(value)
|
||||
if value == oldValue:
|
||||
return _undo_escaped_dollar(value, "(")
|
||||
|
||||
|
||||
def Rule(func):
|
||||
@@ -187,12 +253,10 @@ def _isiterable(xs):
|
||||
|
||||
class Target:
|
||||
def __init__(self, cwd, name):
|
||||
if verbose:
|
||||
print("rule('%s', cwd='%s'" % (name, cwd))
|
||||
self.name = name
|
||||
self.localname = self.name.rsplit("+")[-1]
|
||||
self.traits = set()
|
||||
self.dir = join("$(OBJ)", name)
|
||||
self.dir = join(G.OBJ, name)
|
||||
self.ins = []
|
||||
self.outs = []
|
||||
self.deps = []
|
||||
@@ -232,7 +296,8 @@ class Target:
|
||||
[selfi.templateexpand(f) for f in filenamesof(value)]
|
||||
)
|
||||
|
||||
return Formatter().format(s)
|
||||
s = Formatter().format(s)
|
||||
return substituteGlobalVariables(s)
|
||||
|
||||
def materialise(self, replacing=False):
|
||||
if self not in unmaterialisedTargets:
|
||||
@@ -341,10 +406,10 @@ def targetof(value, cwd=None):
|
||||
elif value.startswith("./"):
|
||||
value = normpath(join(cwd, value))
|
||||
# Explicit directories are always raw files.
|
||||
elif value.endswith("/"):
|
||||
if value.endswith("/"):
|
||||
return _filetarget(value, cwd)
|
||||
# Anything starting with a variable expansion is always a raw file.
|
||||
elif value.startswith("$"):
|
||||
# Anything in .obj is a raw file.
|
||||
elif value.startswith(outputdir) or value.startswith(G.OBJ):
|
||||
return _filetarget(value, cwd)
|
||||
|
||||
# If this is not a rule lookup...
|
||||
@@ -467,78 +532,71 @@ def emit(*args, into=None):
|
||||
if into is not None:
|
||||
into += [s]
|
||||
else:
|
||||
outputFp.write(s)
|
||||
ninjaFp.write(s)
|
||||
|
||||
|
||||
def shell(*args):
|
||||
s = "".join(args) + "\n"
|
||||
shellFp.write(s)
|
||||
|
||||
|
||||
def emit_rule(self, ins, outs, cmds=[], label=None):
|
||||
name = self.name
|
||||
fins_list = filenamesof(ins)
|
||||
fins = set(fins_list)
|
||||
fouts = filenamesof(outs)
|
||||
nonobjs = [f for f in fouts if not f.startswith("$(OBJ)")]
|
||||
fins = [self.templateexpand(f) for f in set(filenamesof(ins))]
|
||||
fouts = [self.templateexpand(f) for f in filenamesof(outs)]
|
||||
|
||||
global outputTargets
|
||||
outputTargets.update(fouts)
|
||||
outputTargets.add(name)
|
||||
|
||||
emit("")
|
||||
if VERBOSE_MK_FILE:
|
||||
if VERBOSE_NINJA_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:
|
||||
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})", into=lines)
|
||||
emit(hashfile, ":", into=lines)
|
||||
emit(f"\t@mkdir -p {self.dir}", into=lines)
|
||||
emit(f"\t@touch {hashfile}", into=lines)
|
||||
emit(
|
||||
f"$(OUTS_{outsn})",
|
||||
"&:" if len(fouts) > 1 else ":",
|
||||
f"$(INS_{insn})",
|
||||
hashfile,
|
||||
into=lines,
|
||||
)
|
||||
|
||||
if label:
|
||||
emit("\t$(hide)", "$(ECHO) $(PROGRESSINFO)" + label, into=lines)
|
||||
os.makedirs(self.dir, exist_ok=True)
|
||||
rule = []
|
||||
|
||||
sandbox = join(self.dir, "sandbox")
|
||||
emit("\t$(hide)", f"rm -rf {sandbox}", into=lines)
|
||||
emit(f"rm -rf {sandbox}", into=rule)
|
||||
emit(
|
||||
"\t$(hide)",
|
||||
"$(PYTHON) build/_sandbox.py --link -s",
|
||||
sandbox,
|
||||
f"$(INS_{insn})",
|
||||
into=lines,
|
||||
f"{G.PYTHON} build/_sandbox.py --link -s", sandbox, *fins, into=rule
|
||||
)
|
||||
for c in cmds:
|
||||
emit(f"\t$(hide) cd {sandbox} && (", c, ")", into=lines)
|
||||
emit(f"(cd {sandbox} &&", c, ")", into=rule)
|
||||
emit(
|
||||
"\t$(hide)",
|
||||
"$(PYTHON) build/_sandbox.py --export -s",
|
||||
f"{G.PYTHON} build/_sandbox.py --export -s",
|
||||
sandbox,
|
||||
f"$(OUTS_{outsn})",
|
||||
into=lines,
|
||||
*fouts,
|
||||
into=rule,
|
||||
)
|
||||
|
||||
ruletext = "".join(rule)
|
||||
if len(ruletext) > 7000:
|
||||
rulehash = hashlib.sha1(ruletext.encode()).hexdigest()
|
||||
|
||||
rulef = join(self.dir, f"rule-{rulehash}.sh")
|
||||
with open(rulef, "wt") as fp:
|
||||
fp.write("set -e\n")
|
||||
fp.write(ruletext)
|
||||
|
||||
emit("build", *fouts, ":rule", *fins, rulef)
|
||||
emit(" command=sh", rulef)
|
||||
else:
|
||||
emit("build", *fouts, ":rule", *fins)
|
||||
emit(
|
||||
" command=",
|
||||
"&&".join([s.strip() for s in rule]).replace("$", "$$"),
|
||||
)
|
||||
if label:
|
||||
emit(" description=", label)
|
||||
emit("build", name, ":phony", *fouts)
|
||||
|
||||
else:
|
||||
assert len(cmds) == 0, "rules with no outputs cannot have commands"
|
||||
emit(name, ":", *fins, into=lines)
|
||||
emit("build", name, ":phony", *fins)
|
||||
|
||||
outputFp.write("".join(lines))
|
||||
emit("")
|
||||
|
||||
|
||||
@@ -585,47 +643,65 @@ def export(self, name=None, items: TargetsMap = {}, deps: Targets = []):
|
||||
dest = self.targetof(dest)
|
||||
outs += [dest]
|
||||
|
||||
destf = filenameof(dest)
|
||||
destf = self.templateexpand(filenameof(dest))
|
||||
outputTargets.update([destf])
|
||||
|
||||
srcs = filenamesof([src])
|
||||
assert (
|
||||
len(srcs) == 1
|
||||
), "a dependency of an exported file must have exactly one output file"
|
||||
srcf = self.templateexpand(srcs[0])
|
||||
|
||||
subrule = simplerule(
|
||||
name=f"{self.localname}/{destf}",
|
||||
cwd=self.cwd,
|
||||
ins=[srcs[0]],
|
||||
outs=[destf],
|
||||
commands=["$(CP) -H %s %s" % (srcs[0], destf)],
|
||||
label="",
|
||||
commands=["$(CP) -H %s %s" % (srcf, destf)],
|
||||
label="EXPORT",
|
||||
)
|
||||
subrule.materialise()
|
||||
|
||||
self.ins = []
|
||||
self.outs = deps + outs
|
||||
outputTargets.add(name)
|
||||
|
||||
emit("")
|
||||
emit(".PHONY:", name)
|
||||
emit(name, ":", *filenamesof(outs + deps))
|
||||
emit(
|
||||
"build",
|
||||
name,
|
||||
":phony",
|
||||
*[self.templateexpand(f) for f in filenamesof(outs + deps)],
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-v", "--verbose", action="store_true")
|
||||
parser.add_argument("-q", "--quiet", action="store_true")
|
||||
parser.add_argument("-o", "--output")
|
||||
parser.add_argument("-v", "--varfile")
|
||||
parser.add_argument("-o", "--outputdir")
|
||||
parser.add_argument("-D", "--define", action="append", default=[])
|
||||
parser.add_argument("files", nargs="+")
|
||||
args = parser.parse_args()
|
||||
|
||||
global verbose
|
||||
verbose = args.verbose
|
||||
|
||||
global quiet
|
||||
quiet = args.quiet
|
||||
|
||||
global outputFp
|
||||
outputFp = open(args.output, "wt")
|
||||
vardefs = args.define
|
||||
if args.varfile:
|
||||
with open(args.varfile, "rt") as fp:
|
||||
vardefs = vardefs + list(fp)
|
||||
|
||||
for line in vardefs:
|
||||
if "=" in line:
|
||||
name, value = line.split("=", 1)
|
||||
G.setdefault(name.strip(), value.strip())
|
||||
|
||||
global ninjaFp, shellFp, outputdir
|
||||
outputdir = args.outputdir
|
||||
G.setdefault("OBJ", outputdir)
|
||||
ninjaFp = open(outputdir + "/build.ninja", "wt")
|
||||
ninjaFp.write(f"include build/ab.ninja\n")
|
||||
|
||||
for k in ["Rule"]:
|
||||
defaultGlobals[k] = globals()[k]
|
||||
@@ -640,7 +716,10 @@ def main():
|
||||
while unmaterialisedTargets:
|
||||
t = next(iter(unmaterialisedTargets))
|
||||
t.materialise()
|
||||
emit("AB_LOADED = 1\n")
|
||||
|
||||
with open(outputdir + "/build.targets", "wt") as fp:
|
||||
fp.write("ninja-targets =")
|
||||
fp.write(substituteGlobalVariables(" ".join(outputTargets)))
|
||||
|
||||
|
||||
main()
|
||||
|
||||
53
build/c.py
53
build/c.py
@@ -7,23 +7,22 @@ from build.ab import (
|
||||
flatten,
|
||||
simplerule,
|
||||
emit,
|
||||
G,
|
||||
)
|
||||
from build.utils import filenamesmatchingof, stripext, collectattrs
|
||||
from build.utils import stripext, collectattrs
|
||||
from build.toolchain import Toolchain, HostToolchain
|
||||
from os.path import *
|
||||
|
||||
emit(
|
||||
"""
|
||||
ifeq ($(OSX),no)
|
||||
STARTGROUP ?= -Wl,--start-group
|
||||
ENDGROUP ?= -Wl,--end-group
|
||||
endif
|
||||
"""
|
||||
)
|
||||
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]] $(CFLAGS) $[cflags]"]
|
||||
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 = [
|
||||
@@ -70,13 +69,9 @@ def _toolchain_find_header_targets(deps, initial=[]):
|
||||
Toolchain.find_c_header_targets = _toolchain_find_header_targets
|
||||
|
||||
|
||||
HostToolchain.CC = [
|
||||
"$(HOSTCC) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]"
|
||||
]
|
||||
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.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 = [
|
||||
@@ -102,9 +97,7 @@ def _indirect(deps, name):
|
||||
return r
|
||||
|
||||
|
||||
def cfileimpl(
|
||||
self, name, srcs, deps, suffix, commands, label, toolchain, cflags
|
||||
):
|
||||
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)
|
||||
@@ -114,9 +107,7 @@ def cfileimpl(
|
||||
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
|
||||
)
|
||||
cflags = collectattrs(targets=hdr_deps, name="caller_cflags", initial=cflags)
|
||||
|
||||
t = simplerule(
|
||||
replaces=self,
|
||||
@@ -194,7 +185,7 @@ def findsources(self, srcs, deps, cflags, filerule, toolchain, cwd):
|
||||
for s in flatten(srcs):
|
||||
objs += [
|
||||
filerule(
|
||||
name=join(self.localname, _removeprefix(f, "$(OBJ)/")),
|
||||
name=join(self.localname, _removeprefix(f, G.OBJ + "/")),
|
||||
srcs=[f],
|
||||
deps=deps,
|
||||
cflags=sorted(set(cflags)),
|
||||
@@ -239,9 +230,7 @@ def libraryimpl(
|
||||
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"
|
||||
assert len(s) == 1, "the target of a header must return exactly one file"
|
||||
|
||||
cs += [f"$(CP) $[ins[{i}]] $[outs[{i}]]"]
|
||||
outs += ["=" + dest]
|
||||
@@ -431,15 +420,11 @@ def programimpl(
|
||||
label,
|
||||
filerule,
|
||||
):
|
||||
cfiles = findsources(
|
||||
self, srcs, deps, cflags, filerule, toolchain, self.cwd
|
||||
)
|
||||
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
|
||||
)
|
||||
ldflags = collectattrs(targets=lib_deps, name="caller_ldflags", initial=ldflags)
|
||||
|
||||
simplerule(
|
||||
replaces=self,
|
||||
@@ -558,9 +543,7 @@ def hostcxxprogram(
|
||||
|
||||
def _cppfileimpl(self, name, srcs, deps, cflags, toolchain):
|
||||
hdr_deps = _indirect(deps, "cheader_deps")
|
||||
cflags = collectattrs(
|
||||
targets=hdr_deps, name="caller_cflags", initial=cflags
|
||||
)
|
||||
cflags = collectattrs(targets=hdr_deps, name="caller_cflags", initial=cflags)
|
||||
|
||||
simplerule(
|
||||
replaces=self,
|
||||
|
||||
10
build/pkg.py
10
build/pkg.py
@@ -1,4 +1,4 @@
|
||||
from build.ab import Rule, Target
|
||||
from build.ab import Rule, Target, G
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -31,8 +31,8 @@ class _PkgConfig:
|
||||
return self.package_properties[p]
|
||||
|
||||
|
||||
TargetPkgConfig = _PkgConfig(os.getenv("PKG_CONFIG"))
|
||||
HostPkgConfig = _PkgConfig(os.getenv("HOST_PKG_CONFIG"))
|
||||
TargetPkgConfig = _PkgConfig(G.PKG_CONFIG)
|
||||
HostPkgConfig = _PkgConfig(G.HOST_PKG_CONFIG)
|
||||
|
||||
|
||||
def _package(self, name, package, fallback, pkgconfig):
|
||||
@@ -49,9 +49,7 @@ def _package(self, name, package, fallback, pkgconfig):
|
||||
self.traits.update({"clibrary", "cxxlibrary"})
|
||||
return
|
||||
|
||||
assert (
|
||||
fallback
|
||||
), f"Required package '{package}' not installed when materialising target '$[name]'"
|
||||
assert fallback, f"Required package '{package}' not installed"
|
||||
|
||||
if "cheader_deps" in fallback.args:
|
||||
self.args["cheader_deps"] = fallback.args["cheader_deps"]
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
from build.ab import Rule, Targets, emit, simplerule, filenamesof
|
||||
from build.ab import Rule, Targets, emit, simplerule, filenamesof, G
|
||||
from build.utils import filenamesmatchingof, collectattrs
|
||||
from os.path import join, abspath, dirname, relpath
|
||||
from build.pkg import has_package
|
||||
|
||||
emit(
|
||||
"""
|
||||
PROTOC ?= protoc
|
||||
HOSTPROTOC ?= protoc
|
||||
"""
|
||||
)
|
||||
G.setdefault("PROTOC", "protoc")
|
||||
G.setdefault("HOSTPROTOC", "hostprotoc")
|
||||
|
||||
assert has_package("protobuf"), "required package 'protobuf' not installed"
|
||||
|
||||
|
||||
@@ -7,10 +7,13 @@ from build.ab import (
|
||||
cwdStack,
|
||||
error,
|
||||
simplerule,
|
||||
G
|
||||
)
|
||||
from os.path import relpath, splitext, join, basename, isfile
|
||||
from glob import iglob
|
||||
import fnmatch
|
||||
import subprocess
|
||||
import shutil
|
||||
|
||||
|
||||
def filenamesmatchingof(xs, pattern):
|
||||
@@ -51,6 +54,16 @@ def itemsof(pattern, root=None, cwd=None):
|
||||
return result
|
||||
|
||||
|
||||
def does_command_exist(cmd):
|
||||
basecmd = cmd.strip().split()[0]
|
||||
return shutil.which(basecmd)
|
||||
|
||||
|
||||
def shell(cmd):
|
||||
r = subprocess.check_output([G.SHELL, "-c", cmd])
|
||||
return r.decode("utf-8").strip()
|
||||
|
||||
|
||||
@Rule
|
||||
def objectify(self, name, src: Target, symbol):
|
||||
simplerule(
|
||||
|
||||
@@ -7,9 +7,7 @@ from build.ab import (
|
||||
|
||||
|
||||
@Rule
|
||||
def zip(
|
||||
self, name, flags="", items: TargetsMap = {}, extension="zip", label="ZIP"
|
||||
):
|
||||
def zip(self, name, flags="", items: TargetsMap = {}, extension="zip", label="ZIP"):
|
||||
cs = ["$(PYTHON) build/_zip.py -z $[outs]"]
|
||||
|
||||
ins = []
|
||||
|
||||
@@ -35,7 +35,7 @@ clibrary(
|
||||
"./config.h",
|
||||
"./src/adflib.h",
|
||||
],
|
||||
cflags=["-Idep/adflib", "-Idep/adflib/src"],
|
||||
cflags=["-Wno-stringop-overflow"],
|
||||
hdrs={
|
||||
"adf_blk.h": "./src/adf_blk.h",
|
||||
"adf_defs.h": "./src/adf_defs.h",
|
||||
|
||||
@@ -204,18 +204,18 @@ install some support packages.
|
||||
- For Linux with Ubuntu/Debian:
|
||||
`libusb-1.0-0-dev`, `libsqlite3-dev`, `zlib1g-dev`,
|
||||
`libudev-dev`, `protobuf-compiler`, `libwxgtk3.0-gtk3-dev`,
|
||||
`libfmt-dev`, `python3`.
|
||||
`libfmt-dev`, `python3`. `ninja-build`
|
||||
- For Linux with Fedora/Red Hat:
|
||||
`git`, `make`, `gcc`, `gcc-c++`, `xxd`, `protobuf-compiler`,
|
||||
`protobuf-devel`, `fmt-devel`, `systemd-devel`, `wxGTK3-devel`,
|
||||
`libsqlite3x-devel`
|
||||
`libsqlite3x-devel`, `ninja-build`
|
||||
- For OSX with Homebrew: `libusb`, `pkg-config`, `sqlite`,
|
||||
`protobuf`, `truncate`, `wxwidgets`, `fmt`.
|
||||
`protobuf`, `truncate`, `wxwidgets`, `fmt`. `ninja`
|
||||
- For Windows with WSL: `protobuf-c-compiler` `protobuf-devel` `fmt-devel`
|
||||
`systemd-devel` `sqlite-devel` `wxGTK-devel` `mingw32-gcc` `mingw32-gcc-c++`
|
||||
`mingw32-zlib-static` `mingw32-protobuf-static` `mingw32-sqlite-static`
|
||||
`mingw32-wxWidgets3-static` `mingw32-libpng-static` `mingw32-libjpeg-static`
|
||||
`mingw32-libtiff-static` `mingw32-nsis png2ico`
|
||||
`mingw32-libtiff-static` `mingw32-nsis png2ico` `ninja-build`
|
||||
|
||||
These lists are not necessarily exhaustive --- please [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new) if I've missed
|
||||
|
||||
@@ -4,6 +4,7 @@ from build.c import clibrary
|
||||
from build.zip import zip
|
||||
from glob import glob
|
||||
from os.path import *
|
||||
import config
|
||||
|
||||
icons = ["fluxfile", "hardware", "icon", "imagefile"]
|
||||
|
||||
@@ -17,37 +18,37 @@ clibrary(
|
||||
},
|
||||
)
|
||||
|
||||
simplerule(
|
||||
name="fluxengine_icns",
|
||||
ins=["./icon.png"],
|
||||
outs=["=fluxengine.icns"],
|
||||
commands=[
|
||||
"mkdir -p fluxengine.iconset",
|
||||
"sips -z 64 64 $[ins[0]] --out fluxengine.iconset/icon_32x32@2x.png > /dev/null",
|
||||
"iconutil -c icns -o $[outs[0]] fluxengine.iconset",
|
||||
],
|
||||
label="ICONSET",
|
||||
)
|
||||
|
||||
simplerule(
|
||||
name="fluxengine_ico",
|
||||
ins=["./icon.png"],
|
||||
outs=["=fluxengine.ico"],
|
||||
commands=["png2ico $[outs[0]] $[ins[0]]"],
|
||||
label="MAKEICON",
|
||||
)
|
||||
|
||||
template_files = [
|
||||
f
|
||||
for f in glob(
|
||||
"**", recursive=True, root_dir="extras/FluxEngine.app.template"
|
||||
if config.osx:
|
||||
simplerule(
|
||||
name="fluxengine_icns",
|
||||
ins=["./icon.png"],
|
||||
outs=["=fluxengine.icns"],
|
||||
commands=[
|
||||
"mkdir -p fluxengine.iconset",
|
||||
"sips -z 64 64 $[ins[0]] --out fluxengine.iconset/icon_32x32@2x.png > /dev/null",
|
||||
"iconutil -c icns -o $[outs[0]] fluxengine.iconset",
|
||||
],
|
||||
label="ICONSET",
|
||||
)
|
||||
|
||||
template_files = [
|
||||
f
|
||||
for f in glob("**", recursive=True, root_dir="extras/FluxEngine.app.template")
|
||||
if isfile(join("extras/FluxEngine.app.template", f))
|
||||
]
|
||||
zip(
|
||||
name="fluxengine_template",
|
||||
items={
|
||||
join("FluxEngine.app", k): join("extras/FluxEngine.app.template", k)
|
||||
for k in template_files
|
||||
},
|
||||
)
|
||||
|
||||
if config.windows:
|
||||
simplerule(
|
||||
name="fluxengine_ico",
|
||||
ins=["./icon.png"],
|
||||
outs=["=fluxengine.ico"],
|
||||
commands=["png2ico $[outs[0]] $[ins[0]]"],
|
||||
label="MAKEICON",
|
||||
)
|
||||
if isfile(join("extras/FluxEngine.app.template", f))
|
||||
]
|
||||
zip(
|
||||
name="fluxengine_template",
|
||||
items={
|
||||
join("FluxEngine.app", k): join("extras/FluxEngine.app.template", k)
|
||||
for k in template_files
|
||||
},
|
||||
)
|
||||
|
||||
@@ -4,11 +4,72 @@
|
||||
#include <fstream>
|
||||
#include "fmt/format.h"
|
||||
#include "lib/core/globals.h"
|
||||
#include "lib/core/logger.h"
|
||||
#include "tests/testproto.pb.h"
|
||||
#include "lib/config/config.pb.h"
|
||||
#include <sstream>
|
||||
#include <locale>
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const BeginSpeedOperationLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const EndSpeedOperationLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const BeginWriteOperationLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const EndWriteOperationLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const BeginReadOperationLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const EndReadOperationLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const TrackReadLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const DiskReadLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const BeginOperationLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const EndOperationLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const OperationProgressLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
void renderLogMessage(
|
||||
LogRenderer& r, std::shared_ptr<const OptionLogMessage> m)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string protoname = STRINGIFY(PROTO);
|
||||
|
||||
static uint32_t readu8(std::string::iterator& it, std::string::iterator end)
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
from build.ab import emit, simplerule
|
||||
from build.ab import simplerule, G
|
||||
from build.c import cxxprogram
|
||||
from build.utils import shell, does_command_exist
|
||||
from glob import glob
|
||||
import config
|
||||
|
||||
emit(
|
||||
"""
|
||||
WX_CONFIG ?= wx-config
|
||||
ifneq ($(strip $(shell command -v $(WX_CONFIG) >/dev/null 2>&1; echo $$?)),0)
|
||||
WX_CFLAGS = $(error Required binary 'wx-config' not found.)
|
||||
WX_LDFLAGS = $(error Required binary 'wx-config' not found.)
|
||||
else
|
||||
WX_CFLAGS := $(shell $(WX_CONFIG) --cxxflags base adv aui richtext core)
|
||||
WX_LDFLAGS := $(shell $(WX_CONFIG) --libs base adv aui richtext core)
|
||||
endif
|
||||
"""
|
||||
G.setdefault("WX_CONFIG", "wx-config")
|
||||
assert does_command_exist(G.WX_CONFIG), "Required binary 'wx-config' not found"
|
||||
|
||||
G.setdefault(
|
||||
"WX_CFLAGS",
|
||||
shell(f"{G.WX_CONFIG} --cxxflags base adv aui richtext core"),
|
||||
)
|
||||
G.setdefault(
|
||||
"WX_LDFLAGS",
|
||||
shell(f"{G.WX_CONFIG} --libs base adv aui richtext core"),
|
||||
)
|
||||
|
||||
extrasrcs = ["./layout.cpp"]
|
||||
|
||||
@@ -64,11 +64,14 @@ export(
|
||||
"+protobuf_lib",
|
||||
"+protocol",
|
||||
".+test_proto_lib",
|
||||
"dep/alphanum",
|
||||
"dep/snowhouse",
|
||||
"lib/algorithms",
|
||||
"lib/config",
|
||||
"lib/core",
|
||||
"lib/data",
|
||||
"lib/fluxsource+proto_lib",
|
||||
"dep/alphanum",
|
||||
"src/formats",
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user