b97c3b67c9
So, avg seems like a poor way to merge throughput results, at least for bench_rbyd (avg create/delete throughputs were wildly different). To fix this, changed make benchmarks and friends to a two step calculation: 1. find max results: -fn='max(n)' -ft='float(bench_simtime)/1.0e9' 2. calculate throughput: -fthroughput='avg(float(n) / max(t, 1.0e-9))' As a plus, this is probably more robust toward accidentally introducing new by fields. Note this does require two csv.py calls. csv.py doesn't support exprs after folding as an intentional simplification (in theory it's always possible to chain multiple csv.py calls together). In make this can be a bit annoying since we need SHELL=/bin/bash for subprocess substitution (for benchmarks-diff specifically), but that's not the end of the world. -- Also changed -Si='min(enumerate())' -> -Si -Fi='min(enumerate())', in case users override SUMMARYFLAGS.
782 lines
19 KiB
Makefile
782 lines
19 KiB
Makefile
# overrideable build dir, default is in-place
|
|
BUILDDIR ?= .
|
|
# overrideable target, default to building a library
|
|
ifneq ($(wildcard test.c main.c),)
|
|
TARGET ?= $(BUILDDIR)/lfs3
|
|
else
|
|
TARGET ?= $(BUILDDIR)/liblfs3.a
|
|
endif
|
|
|
|
|
|
# find source files
|
|
SRC ?= $(filter-out %.t.c %.b.c %.a.c,$(wildcard *.c))
|
|
OBJ := $(SRC:%.c=$(BUILDDIR)/%.o)
|
|
DEP := $(SRC:%.c=$(BUILDDIR)/%.d)
|
|
ASM := $(SRC:%.c=$(BUILDDIR)/%.s)
|
|
CI := $(SRC:%.c=$(BUILDDIR)/%.ci)
|
|
GCDA := $(SRC:%.c=$(BUILDDIR)/%.t.a.gcda)
|
|
|
|
TESTS ?= $(wildcard tests/*.toml)
|
|
TEST_SRC ?= \
|
|
$(SRC) \
|
|
$(filter-out %.t.c %.b.c %.a.c,$(wildcard bd/*.c)) \
|
|
$(filter-out %.t.c %.b.c %.a.c,$(wildcard runners/test_*.c)) \
|
|
$(filter-out %.t.c %.b.c %.a.c,$(wildcard tests/*.c))
|
|
TEST_RUNNER ?= $(BUILDDIR)/runners/test_runner
|
|
TEST_C := \
|
|
$(TESTS:%.toml=$(BUILDDIR)/%.t.c) \
|
|
$(TEST_SRC:%.c=$(BUILDDIR)/%.t.c)
|
|
TEST_A := $(TEST_C:%.t.c=%.t.a.c)
|
|
TEST_OBJ := $(TEST_A:%.t.a.c=%.t.a.o)
|
|
TEST_DEP := $(TEST_A:%.t.a.c=%.t.a.d)
|
|
TEST_CI := $(TEST_A:%.t.a.c=%.t.a.ci)
|
|
TEST_GCNO := $(TEST_A:%.t.a.c=%.t.a.gcno)
|
|
TEST_GCDA := $(TEST_A:%.t.a.c=%.t.a.gcda)
|
|
TEST_PERF := $(TEST_RUNNER:%=%.perf)
|
|
TEST_TRACE := $(TEST_RUNNER:%=%.trace)
|
|
TEST_CSV := $(TEST_RUNNER:%=%.csv)
|
|
|
|
BENCHES ?= $(wildcard benches/*.toml)
|
|
BENCH_SRC ?= \
|
|
$(SRC) \
|
|
$(filter-out %.t.c %.b.c %.a.c,$(wildcard bd/*.c)) \
|
|
$(filter-out %.t.c %.b.c %.a.c,$(wildcard runners/bench_*.c)) \
|
|
$(filter-out %.t.c %.b.c %.a.c,$(wildcard benches/*.c))
|
|
BENCH_RUNNER ?= $(BUILDDIR)/runners/bench_runner
|
|
BENCH_C := \
|
|
$(BENCHES:%.toml=$(BUILDDIR)/%.b.c) \
|
|
$(BENCH_SRC:%.c=$(BUILDDIR)/%.b.c)
|
|
BENCH_A := $(BENCH_C:%.b.c=%.b.a.c)
|
|
BENCH_OBJ := $(BENCH_A:%.b.a.c=%.b.a.o)
|
|
BENCH_DEP := $(BENCH_A:%.b.a.c=%.b.a.d)
|
|
BENCH_CI := $(BENCH_A:%.b.a.c=%.b.a.ci)
|
|
BENCH_GCNO := $(BENCH_A:%.b.a.c=%.b.a.gcno)
|
|
BENCH_GCDA := $(BENCH_A:%.b.a.c=%.b.a.gcda)
|
|
BENCH_PERF := $(BENCH_RUNNER:%=%.perf)
|
|
BENCH_TRACE := $(BENCH_RUNNER:%=%.trace)
|
|
BENCH_CSV := $(BENCH_RUNNER:%=%.csv)
|
|
|
|
# overridable tools/flags
|
|
CC ?= gcc
|
|
AR ?= ar
|
|
SIZE ?= size
|
|
CTAGS ?= ctags
|
|
OBJDUMP ?= objdump
|
|
VALGRIND ?= valgrind
|
|
GDB ?= gdb
|
|
PERF ?= perf
|
|
PRETTYASSERTS ?= ./scripts/prettyasserts.py
|
|
|
|
CFLAGS += -fcallgraph-info=su
|
|
CFLAGS += -g3
|
|
CFLAGS += -I.
|
|
CFLAGS += -std=c99 -Wall -Wextra -pedantic
|
|
# labels are useful for debugging, in-function organization, etc
|
|
CFLAGS += -Wno-unused-label
|
|
# life's too short to not use this flag
|
|
CFLAGS += -Wno-unused-function
|
|
# compiler bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101854
|
|
CFLAGS += -Wno-stringop-overflow
|
|
CFLAGS += -ftrack-macro-expansion=0
|
|
ifdef DEBUG
|
|
CFLAGS += -O0
|
|
else
|
|
CFLAGS += -Os
|
|
endif
|
|
ifdef TRACE
|
|
CFLAGS += -DLFS3_YES_TRACE
|
|
endif
|
|
ifdef COVGEN
|
|
CFLAGS += --coverage
|
|
endif
|
|
ifdef PERFGEN
|
|
CFLAGS += -fno-omit-frame-pointer
|
|
endif
|
|
ifdef PERFBDGEN
|
|
CFLAGS += -fno-omit-frame-pointer
|
|
endif
|
|
|
|
# also forward all LFS3_* environment variables
|
|
CFLAGS += $(foreach d,$(filter LFS3_%,$(.VARIABLES)),-D$d=$($d))
|
|
|
|
TEST_CFLAGS += -Wno-unused-function
|
|
TEST_CFLAGS += -Wno-format-overflow
|
|
ifdef STACK
|
|
TEST_CFLAGS += -DTEST_YES_STACK
|
|
endif
|
|
ifdef HEAP
|
|
TEST_CFLAGS += -DTEST_YES_HEAP
|
|
TEST_CFLAGS += -Wl,--wrap=malloc
|
|
TEST_CFLAGS += -Wl,--wrap=free
|
|
TEST_CFLAGS += -Wl,--wrap=realloc
|
|
endif
|
|
|
|
BENCH_CFLAGS += -Wno-unused-function
|
|
BENCH_CFLAGS += -Wno-format-overflow
|
|
ifndef NO_STACK
|
|
BENCH_CFLAGS += -DBENCH_YES_STACK
|
|
endif
|
|
ifndef NO_HEAP
|
|
BENCH_CFLAGS += -DBENCH_YES_HEAP
|
|
BENCH_CFLAGS += -Wl,--wrap=malloc
|
|
BENCH_CFLAGS += -Wl,--wrap=free
|
|
BENCH_CFLAGS += -Wl,--wrap=realloc
|
|
endif
|
|
|
|
ifdef VERBOSE
|
|
CODEFLAGS += -v
|
|
DATAFLAGS += -v
|
|
STACKFLAGS += -v
|
|
CTXFLAGS += -v
|
|
STRUCTSFLAGS += -v
|
|
COVFLAGS += -v
|
|
PERFFLAGS += -v
|
|
PERFBDFLAGS += -v
|
|
endif
|
|
# forward -j flag
|
|
PERFFLAGS += $(filter -j%,$(MAKEFLAGS))
|
|
PERFBDFLAGS += $(filter -j%,$(MAKEFLAGS))
|
|
ifneq ($(OBJDUMP),objdump)
|
|
CODEFLAGS += --objdump-path="$(OBJDUMP)"
|
|
DATAFLAGS += --objdump-path="$(OBJDUMP)"
|
|
STACKFLAGS += --objdump-path="$(OBJDUMP)"
|
|
CTXFLAGS += --objdump-path="$(OBJDUMP)"
|
|
STRUCTSFLAGS += --objdump-path="$(OBJDUMP)"
|
|
PERFFLAGS += --objdump-path="$(OBJDUMP)"
|
|
PERFBDFLAGS += --objdump-path="$(OBJDUMP)"
|
|
endif
|
|
ifneq ($(PERF),perf)
|
|
PERFFLAGS += --perf-path="$(PERF)"
|
|
endif
|
|
|
|
TESTFLAGS += -b
|
|
BENCHFLAGS += -b
|
|
# forward -j flag
|
|
TESTFLAGS += $(filter -j%,$(MAKEFLAGS))
|
|
BENCHFLAGS += $(filter -j%,$(MAKEFLAGS))
|
|
ifdef PERFGEN
|
|
TESTFLAGS += -p$(TEST_PERF)
|
|
BENCHFLAGS += -p$(BENCH_PERF)
|
|
endif
|
|
ifdef PERFBDGEN
|
|
TESTFLAGS += -t$(TEST_TRACE) --trace-backtrace --trace-freq=100
|
|
BENCHFLAGS += -t$(BENCH_TRACE) --trace-backtrace --trace-freq=100
|
|
endif
|
|
ifdef TESTMARKS
|
|
TESTFLAGS += -o$(TEST_CSV)
|
|
endif
|
|
ifndef NO_BENCHMARKS
|
|
BENCHFLAGS += -o$(BENCH_CSV)
|
|
endif
|
|
ifdef VERBOSE
|
|
TESTFLAGS += -v
|
|
TESTCFLAGS += -v
|
|
BENCHFLAGS += -v
|
|
BENCHCFLAGS += -v
|
|
endif
|
|
ifdef EXEC
|
|
TESTFLAGS += --exec="$(EXEC)"
|
|
BENCHFLAGS += --exec="$(EXEC)"
|
|
endif
|
|
ifneq ($(GDB),gdb)
|
|
TESTFLAGS += --gdb-path="$(GDB)"
|
|
BENCHFLAGS += --gdb-path="$(GDB)"
|
|
endif
|
|
ifneq ($(VALGRIND),valgrind)
|
|
TESTFLAGS += --valgrind-path="$(VALGRIND)"
|
|
BENCHFLAGS += --valgrind-path="$(VALGRIND)"
|
|
endif
|
|
ifneq ($(PERF),perf)
|
|
TESTFLAGS += --perf-path="$(PERF)"
|
|
BENCHFLAGS += --perf-path="$(PERF)"
|
|
endif
|
|
|
|
# this is a bit of a hack, but we want to make sure the BUILDDIR
|
|
# directory structure is correct before we run any commands
|
|
ifneq ($(BUILDDIR),.)
|
|
$(if $(findstring n,$(MAKEFLAGS)),, $(shell mkdir -p \
|
|
$(BUILDDIR) \
|
|
$(addprefix $(BUILDDIR)/,$(dir \
|
|
$(SRC) \
|
|
$(TESTS) \
|
|
$(TEST_SRC) \
|
|
$(BENCHES) \
|
|
$(BENCH_SRC)))))
|
|
endif
|
|
|
|
|
|
# top-level commands
|
|
|
|
## Build littlefs
|
|
.PHONY: all build
|
|
all build: $(TARGET)
|
|
|
|
## Build assembly files
|
|
.PHONY: asm
|
|
asm: $(ASM)
|
|
|
|
## Find total section sizes
|
|
.PHONY: size
|
|
size: $(OBJ)
|
|
$(SIZE) -t $^
|
|
|
|
## Generate a ctags file
|
|
#
|
|
# run twice to only include prototypes in header files
|
|
.PHONY: tags ctags
|
|
tags ctags:
|
|
$(strip $(CTAGS) \
|
|
--totals --fields=+n --c-types=+p \
|
|
$(shell find -H -name '*.h'))
|
|
$(strip $(CTAGS) \
|
|
--totals --append --fields=+n \
|
|
$(SRC))
|
|
|
|
## Show this help text
|
|
.PHONY: help
|
|
help:
|
|
@$(strip awk '/^## / { \
|
|
sub(/^## /,""); \
|
|
getline rule; \
|
|
while (rule ~ /^(#|\.PHONY|ifdef|ifndef)/) getline rule; \
|
|
gsub(/:.*/, "", rule); \
|
|
if (length(rule) <= 21) { \
|
|
printf "%2s%-21s %s\n", "", rule, $$0; \
|
|
} else { \
|
|
printf "%2s%s\n", "", rule; \
|
|
printf "%24s%s\n", "", $$0; \
|
|
} \
|
|
}' $(MAKEFILE_LIST))
|
|
|
|
## Find the per-function code size
|
|
.PHONY: code
|
|
code: CODEFLAGS+=-S
|
|
code: $(OBJ)
|
|
./scripts/code.py $^ $(CODEFLAGS)
|
|
|
|
## Save the per-function code size
|
|
.PHONY: code-csv
|
|
code-csv: $(BUILDDIR)/lfs3.code.csv
|
|
|
|
## Compare per-function code size
|
|
.PHONY: code-diff
|
|
code-diff: $(OBJ)
|
|
./scripts/code.py $^ $(CODEFLAGS) -d $(BUILDDIR)/lfs3.code.csv
|
|
|
|
## Find the per-function data size
|
|
.PHONY: data
|
|
data: DATAFLAGS+=-S
|
|
data: $(OBJ)
|
|
./scripts/data.py $^ $(DATAFLAGS)
|
|
|
|
## Save the per-function data size
|
|
.PHONY: data-csv
|
|
data-csv: $(BUILDDIR)/lfs3.data.csv
|
|
|
|
## Compare per-function data size
|
|
.PHONY: data-diff
|
|
data-diff: $(OBJ)
|
|
./scripts/data.py $^ $(DATAFLAGS) -d $(BUILDDIR)/lfs3.data.csv
|
|
|
|
## Find the per-function stack usage
|
|
.PHONY: stack
|
|
stack: STACKFLAGS+=-S
|
|
stack: $(CI)
|
|
./scripts/stack.py $^ $(STACKFLAGS)
|
|
|
|
## Save the per-function stack usage
|
|
.PHONY: stack-csv
|
|
stack-csv: $(BUILDDIR)/lfs3.stack.csv
|
|
|
|
## Compare per-function stack usage
|
|
.PHONY: stack-diff
|
|
stack-diff: $(CI)
|
|
./scripts/stack.py $^ $(STACKFLAGS) -d $(BUILDDIR)/lfs3.stack.csv
|
|
|
|
## Find the per-function context
|
|
.PHONY: ctx
|
|
ctx: CTXFLAGS+=-S
|
|
ctx: $(OBJ)
|
|
./scripts/ctx.py $^ $(CTXFLAGS)
|
|
|
|
## Save the per-function context
|
|
.PHONY: ctx-csv
|
|
ctx-csv: $(BUILDDIR)/lfs3.ctx.csv
|
|
|
|
## Compare per-function context
|
|
.PHONY: ctx-diff
|
|
ctx-diff: $(CI)
|
|
./scripts/ctx.py $^ $(CTXFLAGS) -d $(BUILDDIR)/lfs3.ctx.csv
|
|
|
|
## Find function sizes
|
|
.PHONY: funcs
|
|
funcs: SUMMARYFLAGS+=-S
|
|
funcs: SHELL=/bin/bash
|
|
funcs: $(OBJ) $(CI)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/code.py $(OBJ) $(CODEFLAGS) -o-) \
|
|
<(./scripts/stack.py $(CI) $(STACKFLAGS) -o-) \
|
|
<(./scripts/ctx.py $(OBJ) $(CTXFLAGS) -o-) \
|
|
-bfunction \
|
|
-fcode=code_size \
|
|
-fstack='max(stack_limit)' \
|
|
-fctx='max(ctx_size)' \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Save function sizes
|
|
.PHONY: funcs-csv
|
|
funcs-csv: \
|
|
$(BUILDDIR)/lfs3.code.csv \
|
|
$(BUILDDIR)/lfs3.stack.csv \
|
|
$(BUILDDIR)/lfs3.ctx.csv
|
|
|
|
## Compare function sizes
|
|
.PHONY: funcs-diff
|
|
funcs-diff: SHELL=/bin/bash
|
|
funcs-diff: $(OBJ) $(CI)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/code.py $(OBJ) $(CODEFLAGS) -o-) \
|
|
<(./scripts/stack.py $(CI) $(STACKFLAGS) -o-) \
|
|
<(./scripts/ctx.py $(OBJ) $(CTXFLAGS) -o-) \
|
|
-bfunction \
|
|
-fcode=code_size \
|
|
-fstack='max(stack_limit)' \
|
|
-fctx='max(ctx_size)' \
|
|
-d <(./scripts/csv.py \
|
|
$(BUILDDIR)/lfs3.code.csv \
|
|
$(BUILDDIR)/lfs3.stack.csv \
|
|
$(BUILDDIR)/lfs3.ctx.csv \
|
|
-fcode_size=code_size \
|
|
-fstack_limit='max(stack_limit)' \
|
|
-fctx_size='max(ctx_size)' \
|
|
-o-) \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Find struct sizes
|
|
.PHONY: structs
|
|
structs: STRUCTSFLAGS+=-S
|
|
structs: $(OBJ)
|
|
./scripts/structs.py $^ $(STRUCTSFLAGS)
|
|
|
|
## Save struct sizes
|
|
.PHONY: structs-csv
|
|
structs-csv: $(BUILDDIR)/lfs3.structs.csv
|
|
|
|
## Compare struct sizes
|
|
.PHONY: structs-diff
|
|
structs-diff: $(OBJ)
|
|
./scripts/structs.py $^ $(STRUCTSFLAGS) -d $(BUILDDIR)/lfs3.structs.csv
|
|
|
|
## Find line/branch coverage after a test run with COVGEN
|
|
.PHONY: cov
|
|
cov: COVFLAGS+=-s
|
|
cov: $(GCDA)
|
|
$(strip ./scripts/cov.py $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(COVFLAGS))
|
|
|
|
## Save line/branch coverage
|
|
.PHONY: cov-csv
|
|
cov-csv: $(BUILDDIR)/lfs3.cov.csv
|
|
|
|
## Compare line/branch coverage
|
|
.PHONY: cov-diff
|
|
cov-diff: $(GCDA)
|
|
$(strip ./scripts/cov.py $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(COVFLAGS) -d $(BUILDDIR)/lfs3.cov.csv)
|
|
|
|
## Find perf results after bench run with PERFGEN
|
|
.PHONY: perf
|
|
perf: PERFFLAGS+=-S
|
|
perf: $(BENCH_PERF)
|
|
$(strip ./scripts/perf.py $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(PERFFLAGS))
|
|
|
|
## Save perf results
|
|
.PHONY: perf-csv
|
|
perf-csv: $(BUILDDIR)/lfs3.perf.csv
|
|
|
|
## Compare perf results
|
|
.PHONY: perf-diff
|
|
perf-diff: $(BENCH_PERF)
|
|
$(strip ./scripts/perf.py $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(PERFFLAGS) -d $(BUILDDIR)/lfs3.perf.csv)
|
|
|
|
## Find perfbd results after a bench run with PERFBDGEN
|
|
.PHONY: perfbd
|
|
perfbd: PERFBDFLAGS+=-S
|
|
perfbd: $(BENCH_TRACE)
|
|
$(strip ./scripts/perfbd.py $(BENCH_RUNNER) $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(PERFBDFLAGS))
|
|
|
|
## Save perfbd results
|
|
.PHONY: perfbd-csv
|
|
perfbd-csv: $(BUILDDIR)/lfs3.perfbd.csv
|
|
|
|
## Compare perfbd results
|
|
.PHONY: perfbd-diff
|
|
perfbd-diff: $(BENCH_TRACE)
|
|
$(strip ./scripts/perfbd.py $(BENCH_RUNNER) $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(PERFBDFLAGS) -d $(BUILDDIR)/lfs3.perfbd.csv)
|
|
|
|
## Find a summary of compile-time sizes
|
|
.PHONY: summary sizes
|
|
summary sizes: SHELL=/bin/bash
|
|
summary sizes: $(OBJ) $(CI)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/code.py $(OBJ) $(CODEFLAGS) -o-) \
|
|
<(./scripts/data.py $(OBJ) $(DATAFLAGS) -o-) \
|
|
<(./scripts/stack.py $(CI) $(STACKFLAGS) -o-) \
|
|
<(./scripts/ctx.py $(OBJ) $(CTXFLAGS) -o-) \
|
|
-bfunction \
|
|
-fcode=code_size \
|
|
-fdata=data_size \
|
|
-fstack='max(stack_limit)' \
|
|
-fctx='max(ctx_size)' \
|
|
-Y $(SUMMARYFLAGS))
|
|
|
|
## Save compile-time sizes
|
|
.PHONY: summary-csv sizes-csv
|
|
summary-csv sizes-csv: \
|
|
$(BUILDDIR)/lfs3.code.csv \
|
|
$(BUILDDIR)/lfs3.data.csv \
|
|
$(BUILDDIR)/lfs3.stack.csv \
|
|
$(BUILDDIR)/lfs3.ctx.csv
|
|
|
|
## Compare compile-time sizes
|
|
.PHONY: summary-diff sizes-diff
|
|
summary-diff sizes-diff: SHELL=/bin/bash
|
|
summary-diff sizes-diff: $(OBJ) $(CI)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/csv.py \
|
|
<(./scripts/code.py $(OBJ) $(CODEFLAGS) -o-) \
|
|
<(./scripts/data.py $(OBJ) $(DATAFLAGS) -o-) \
|
|
<(./scripts/stack.py $(CI) $(STACKFLAGS) -o-) \
|
|
<(./scripts/ctx.py $(OBJ) $(CTXFLAGS) -o-) \
|
|
-bbuild=AFTER \
|
|
-fcode=code_size \
|
|
-fdata=data_size \
|
|
-fstack='max(stack_limit)' \
|
|
-fctx='max(ctx_size)' \
|
|
-o-) \
|
|
<(./scripts/csv.py \
|
|
$(BUILDDIR)/lfs3.code.csv \
|
|
$(BUILDDIR)/lfs3.data.csv \
|
|
$(BUILDDIR)/lfs3.stack.csv \
|
|
$(BUILDDIR)/lfs3.ctx.csv \
|
|
-bbuild=BEFORE \
|
|
-fcode=code_size \
|
|
-fdata=data_size \
|
|
-fstack='max(stack_limit)' \
|
|
-fctx='max(ctx_size)' \
|
|
-o-) \
|
|
-bbuild -cBEFORE -Q $(SUMMARYFLAGS))
|
|
|
|
|
|
## Generate a codemap svg
|
|
.PHONY: codemap
|
|
codemap: CODEMAPFLAGS+=-W1125 -H525 --dark
|
|
codemap: $(BUILDDIR)/lfs3.codemap.svg
|
|
|
|
## Generate a tiny codemap, where 1 pixel ~= 1 byte
|
|
.PHONY: codemap-tiny
|
|
codemap-tiny: CODEMAPFLAGS+=--dark
|
|
codemap-tiny: $(BUILDDIR)/lfs3.codemap_tiny.svg
|
|
|
|
|
|
## Build the test-runner
|
|
.PHONY: test-runner build-tests
|
|
test-runner build-tests: CFLAGS+=$(TEST_CFLAGS)
|
|
# note we remove some binary dependent files during compilation,
|
|
# otherwise it's way to easy to end up with outdated results
|
|
test-runner build-tests: $(TEST_RUNNER)
|
|
ifdef COVGEN
|
|
rm -f $(TEST_GCDA)
|
|
endif
|
|
ifdef PERFGEN
|
|
rm -f $(TEST_PERF)
|
|
endif
|
|
ifdef PERFBDGEN
|
|
rm -f $(TEST_TRACE)
|
|
endif
|
|
|
|
## Run the tests, -j enables parallel tests
|
|
.PHONY: test
|
|
test: test-runner
|
|
./scripts/test.py -R$(TEST_RUNNER) $(TESTFLAGS)
|
|
|
|
## List the tests
|
|
.PHONY: test-list list-tests
|
|
test-list list-tests: test-runner
|
|
./scripts/test.py -R$(TEST_RUNNER) $(TESTFLAGS) -l
|
|
|
|
## Summarize the test results
|
|
.PHONY: testmarks
|
|
testmarks: SUMMARYFLAGS+=-Si
|
|
testmarks: $(TEST_CSV)
|
|
$(strip ./scripts/csv.py $^ \
|
|
-bsuite \
|
|
-Fi='min(enumerate())' \
|
|
-fpassed=test_passed \
|
|
-fruntime=test_runtime \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Save the test results with TESTMARKS
|
|
.PHONY: testmarks-csv
|
|
testmarks-csv: $(BUILDDIR)/lfs3.test.csv
|
|
|
|
## Compare test results against a previous run
|
|
.PHONY: testmarks-diff
|
|
testmarks-diff: $(TEST_CSV)
|
|
$(strip ./scripts/csv.py $^ \
|
|
-bsuite \
|
|
-Fi='min(enumerate())' \
|
|
-fpassed=test_passed \
|
|
-fruntime=test_runtime \
|
|
$(SUMMARYFLAGS) -d $(BUILDDIR)/lfs3.test.csv)
|
|
|
|
## Show which tests took the most time
|
|
.PHONY: testmarks-bottlenecks
|
|
testmarks-bottlenecks: SUMMARYFLAGS+=-Sruntime
|
|
testmarks-bottlenecks: $(TEST_CSV)
|
|
$(strip ./scripts/csv.py $^ \
|
|
-bcase \
|
|
-Fi='min(enumerate())' \
|
|
-fpassed=test_passed \
|
|
-fruntime=test_runtime \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Build the bench-runner
|
|
.PHONY: bench-runner build-benches
|
|
bench-runner build-benches: CFLAGS+=$(BENCH_CFLAGS)
|
|
# note we remove some binary dependent files during compilation,
|
|
# otherwise it's way to easy to end up with outdated results
|
|
bench-runner build-benches: $(BENCH_RUNNER)
|
|
ifdef COVGEN
|
|
rm -f $(BENCH_GCDA)
|
|
endif
|
|
ifdef PERFGEN
|
|
rm -f $(BENCH_PERF)
|
|
endif
|
|
ifdef PERFBDGEN
|
|
rm -f $(BENCH_TRACE)
|
|
endif
|
|
|
|
## Run the benches, -j enables parallel benches
|
|
.PHONY: bench
|
|
bench: bench-runner
|
|
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS)
|
|
|
|
## List the benches
|
|
.PHONY: bench-list list-benches
|
|
bench-list list-benches: bench-runner
|
|
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) -l
|
|
|
|
## Summarize the bench results
|
|
.PHONY: benchmarks
|
|
benchmarks: SUMMARYFLAGS+=-Si
|
|
benchmarks: SHELL=/bin/bash
|
|
benchmarks: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/csv.py $^ \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-fn='max(n)' \
|
|
-ft='float(bench_simtime)/1.0e9' \
|
|
-o-) \
|
|
-bprobe \
|
|
-fn \
|
|
-ft \
|
|
-fthroughput='avg(float(n) / max(t, 1.0e-9))' \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Save the bench results
|
|
.PHONY: benchmarks-csv
|
|
benchmarks-csv: $(BUILDDIR)/lfs3.bench.csv
|
|
|
|
## Compare bench results against a previous run
|
|
.PHONY: benchmarks-diff
|
|
benchmarks-diff: SHELL=/bin/bash
|
|
benchmarks-diff: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/csv.py $^ \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-fn='max(n)' \
|
|
-ft='float(bench_simtime)/1.0e9' \
|
|
-o-) \
|
|
-d <(./scripts/csv.py $(BUILDDIR)/lfs3.bench.csv \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-fn='max(n)' \
|
|
-ft='float(bench_simtime)/1.0e9' \
|
|
-o-) \
|
|
-bprobe \
|
|
-fthroughput='avg(float(n) / max(t, 1.0e-9))' \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Show which tests took the most time
|
|
.PHONY: benchmarks-bottlenecks
|
|
benchmarks-bottlenecks: SUMMARYFLAGS+=-Sruntime
|
|
benchmarks-bottlenecks: SHELL=/bin/bash
|
|
benchmarks-bottlenecks: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/csv.py $^ \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-fn='max(n)' \
|
|
-ft='float(bench_simtime)/1.0e9' \
|
|
-fruntime='max(bench_runtime)' \
|
|
-o-) \
|
|
-bprobe \
|
|
-fn \
|
|
-ft \
|
|
-fruntime \
|
|
$(SUMMARYFLAGS))
|
|
|
|
|
|
|
|
# low-level rules
|
|
-include $(DEP)
|
|
-include $(TEST_DEP)
|
|
-include $(BENCH_DEP)
|
|
.SUFFIXES:
|
|
.SECONDARY:
|
|
|
|
$(BUILDDIR)/lfs3: $(OBJ)
|
|
$(CC) $(CFLAGS) $^ $(LFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/liblfs3.a: $(OBJ)
|
|
$(AR) rcs $@ $^
|
|
|
|
$(BUILDDIR)/lfs3.code.csv: $(OBJ)
|
|
./scripts/code.py $^ $(CODEFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/lfs3.data.csv: $(OBJ)
|
|
./scripts/data.py $^ $(DATAFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/lfs3.stack.csv: $(CI)
|
|
./scripts/stack.py $^ $(STACKFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/lfs3.ctx.csv: $(OBJ)
|
|
./scripts/ctx.py $^ $(CTXFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/lfs3.structs.csv: $(OBJ)
|
|
./scripts/structs.py $^ $(STRUCTSFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/lfs3.cov.csv: $(GCDA)
|
|
$(strip ./scripts/cov.py $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(COVFLAGS) -o$@)
|
|
|
|
$(BUILDDIR)/lfs3.perf.csv: $(BENCH_PERF)
|
|
$(strip ./scripts/perf.py $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(PERFFLAGS) -o$@)
|
|
|
|
$(BUILDDIR)/lfs3.perfbd.csv: $(BENCH_TRACE)
|
|
$(strip ./scripts/perfbd.py $(BENCH_RUNNER) $^ \
|
|
$(patsubst %,-F%,$(SRC)) \
|
|
$(PERFBDFLAGS) -o$@)
|
|
|
|
$(BUILDDIR)/lfs3.codemap.svg: $(OBJ) $(CI)
|
|
$(strip ./scripts/codemapsvg.py $^ $(CODEMAPFLAGS) -o$@ \
|
|
&& ./scripts/codemap.py $^ --no-header)
|
|
|
|
$(BUILDDIR)/lfs3.codemap_tiny.svg: $(OBJ) $(CI)
|
|
$(strip ./scripts/codemapsvg.py $^ --tiny $(CODEMAPFLAGS) -o$@ \
|
|
&& ./scripts/codemap.py $^ --no-header)
|
|
|
|
$(BUILDDIR)/lfs3.test.csv: $(TEST_CSV)
|
|
cp $^ $@
|
|
|
|
$(BUILDDIR)/lfs3.bench.csv: $(BENCH_CSV)
|
|
cp $^ $@
|
|
|
|
$(BUILDDIR)/runners/test_runner: $(TEST_OBJ)
|
|
$(CC) $(CFLAGS) $^ $(LFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/runners/bench_runner: $(BENCH_OBJ)
|
|
$(CC) $(CFLAGS) $^ $(LFLAGS) -o$@
|
|
|
|
# our main build rule generates .o, .d, and .ci files, the latter
|
|
# used for stack analysis
|
|
$(BUILDDIR)/%.o $(BUILDDIR)/%.ci: %.c
|
|
$(CC) -c -MMD $(CFLAGS) $< -o $(BUILDDIR)/$*.o
|
|
|
|
$(BUILDDIR)/%.o $(BUILDDIR)/%.ci: $(BUILDDIR)/%.c
|
|
$(CC) -c -MMD $(CFLAGS) $< -o $(BUILDDIR)/$*.o
|
|
|
|
$(BUILDDIR)/%.s: %.c
|
|
$(CC) -S $(CFLAGS) $< -o$@
|
|
|
|
$(BUILDDIR)/%.s: $(BUILDDIR)/%.c
|
|
$(CC) -S $(CFLAGS) $< -o$@
|
|
|
|
$(BUILDDIR)/%.a.c: %.c
|
|
$(PRETTYASSERTS) -Plfs3_ $< -o$@
|
|
|
|
$(BUILDDIR)/%.a.c: $(BUILDDIR)/%.c
|
|
$(PRETTYASSERTS) -Plfs3_ $< -o$@
|
|
|
|
$(BUILDDIR)/%.t.c: %.toml
|
|
./scripts/test.py -c $< $(TESTCFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/%.t.c: %.c $(TESTS)
|
|
./scripts/test.py -c $(TESTS) -s $< $(TESTCFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/%.b.c: %.toml
|
|
./scripts/bench.py -c $< $(BENCHCFLAGS) -o$@
|
|
|
|
$(BUILDDIR)/%.b.c: %.c $(BENCHES)
|
|
./scripts/bench.py -c $(BENCHES) -s $< $(BENCHCFLAGS) -o$@
|
|
|
|
## Clean everything
|
|
.PHONY: clean
|
|
clean:
|
|
rm -f $(BUILDDIR)/lfs3
|
|
rm -f $(BUILDDIR)/liblfs3.a
|
|
rm -f $(BUILDDIR)/lfs3.code.csv
|
|
rm -f $(BUILDDIR)/lfs3.data.csv
|
|
rm -f $(BUILDDIR)/lfs3.stack.csv
|
|
rm -f $(BUILDDIR)/lfs3.ctx.csv
|
|
rm -f $(BUILDDIR)/lfs3.structs.csv
|
|
rm -f $(BUILDDIR)/lfs3.cov.csv
|
|
rm -f $(BUILDDIR)/lfs3.perf.csv
|
|
rm -f $(BUILDDIR)/lfs3.perfbd.csv
|
|
rm -f $(BUILDDIR)/lfs3.codemap.svg
|
|
rm -f $(BUILDDIR)/lfs3.codemap_tiny.svg
|
|
rm -f $(BUILDDIR)/lfs3.test.csv
|
|
rm -f $(BUILDDIR)/lfs3.bench.csv
|
|
rm -f $(OBJ)
|
|
rm -f $(DEP)
|
|
rm -f $(ASM)
|
|
rm -f $(CI)
|
|
rm -f $(TEST_RUNNER)
|
|
rm -f $(TEST_A)
|
|
rm -f $(TEST_C)
|
|
rm -f $(TEST_OBJ)
|
|
rm -f $(TEST_DEP)
|
|
rm -f $(TEST_CI)
|
|
rm -f $(TEST_GCNO)
|
|
rm -f $(TEST_GCDA)
|
|
rm -f $(TEST_PERF)
|
|
rm -f $(TEST_TRACE)
|
|
rm -f $(TEST_CSV)
|
|
rm -f $(BENCH_RUNNER)
|
|
rm -f $(BENCH_A)
|
|
rm -f $(BENCH_C)
|
|
rm -f $(BENCH_OBJ)
|
|
rm -f $(BENCH_DEP)
|
|
rm -f $(BENCH_CI)
|
|
rm -f $(BENCH_GCNO)
|
|
rm -f $(BENCH_GCDA)
|
|
rm -f $(BENCH_PERF)
|
|
rm -f $(BENCH_TRACE)
|
|
rm -f $(BENCH_CSV)
|