440d303a6b
Based on some experience out-of-tree: - bench_rbyd - Simple rbyd attr/id litmus benchmark - bench_btree (new) - Simple btree id/name litmus benchmark - bench_file (new) - Simple file read/write litmus benchmark - bench_dir (new) - Simple dir read/write/stat litmus benchmark - bench_wt - Heavy-duty write-throughput benchmark - bench_rt (new) - Heavy-duty read-throughput benchmark Benches take a long time to run for useful results, so we probably don't want to go crazy with them like with the tests. Honestly, we may want to chop this down to just the write/read-throughput benches.
886 lines
22 KiB
Makefile
886 lines
22 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
|
|
# process substitution my beloved
|
|
SHELL := /bin/bash
|
|
|
|
|
|
# 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_STACK
|
|
TEST_CFLAGS += -Wl,--wrap=printf
|
|
TEST_CFLAGS += -Wl,--wrap=vprintf
|
|
endif
|
|
ifdef HEAP
|
|
TEST_CFLAGS += -DTEST_HEAP
|
|
TEST_CFLAGS += -Wl,--wrap=malloc
|
|
TEST_CFLAGS += -Wl,--wrap=free
|
|
TEST_CFLAGS += -Wl,--wrap=realloc
|
|
TEST_CFLAGS += -Wl,--wrap=printf
|
|
TEST_CFLAGS += -Wl,--wrap=vprintf
|
|
endif
|
|
|
|
BENCH_CFLAGS += -Wno-unused-function
|
|
BENCH_CFLAGS += -Wno-format-overflow
|
|
ifndef NO_STACK
|
|
BENCH_CFLAGS += -DBENCH_STACK
|
|
BENCH_CFLAGS += -Wl,--wrap=printf
|
|
BENCH_CFLAGS += -Wl,--wrap=vprintf
|
|
endif
|
|
ifndef NO_HEAP
|
|
BENCH_CFLAGS += -DBENCH_HEAP
|
|
BENCH_CFLAGS += -Wl,--wrap=malloc
|
|
BENCH_CFLAGS += -Wl,--wrap=free
|
|
BENCH_CFLAGS += -Wl,--wrap=realloc
|
|
BENCH_CFLAGS += -Wl,--wrap=printf
|
|
BENCH_CFLAGS += -Wl,--wrap=vprintf
|
|
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
|
|
|
|
# alternative bench geometries (defaults to NOR flash)
|
|
ifdef BENCH_NOR
|
|
BENCHFLAGS += -DDISK_GEOMETRY=0
|
|
endif
|
|
ifdef BENCH_NAND
|
|
BENCHFLAGS += -DDISK_GEOMETRY=1
|
|
endif
|
|
ifdef BENCH_PERBYTE
|
|
BENCHFLAGS += -DDISK_SIM=1
|
|
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: $(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: $(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: $(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: $(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: test-marks
|
|
test-marks: SUMMARYFLAGS+=-Si
|
|
test-marks: $(TEST_CSV)
|
|
$(strip ./scripts/csv.py $^ \
|
|
-bsuite \
|
|
-Fi='min(enumerate())' \
|
|
-fpassed=test_passed \
|
|
-fruntime=test_runtime \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Save the test results with TESTMARKS
|
|
.PHONY: test-marks-csv
|
|
test-marks-csv: $(BUILDDIR)/lfs3.test.csv
|
|
|
|
## Compare test results against a previous run
|
|
.PHONY: test-marks-diff
|
|
test-marks-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: test-bottlenecks
|
|
test-bottlenecks: SUMMARYFLAGS+=-Sruntime
|
|
test-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: bench-marks
|
|
bench-marks: SUMMARYFLAGS+=-Si
|
|
bench-marks: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/csv.py $^ \
|
|
-Dprobe=append,remove,create,delete,fetch,lookup,$\
|
|
commit,namelookup,$\
|
|
write,stat,read \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-fn='max(n)' \
|
|
-ft='max(float(bench_simtime)/1.0e9)' \
|
|
-o-) \
|
|
-bprobe \
|
|
-fn \
|
|
-ft \
|
|
-fthroughput='avg(float(n) / max(t, 1.0e-9))' \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Save the bench results
|
|
.PHONY: bench-marks-csv
|
|
bench-marks-csv: $(BUILDDIR)/lfs3.bench.csv
|
|
|
|
## Compare bench results against a previous run
|
|
.PHONY: bench-marks-diff
|
|
bench-marks-diff: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/csv.py $^ \
|
|
-Dprobe=append,remove,create,delete,fetch,lookup,$\
|
|
commit,namelookup,$\
|
|
write,stat,read \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-fn='max(n)' \
|
|
-ft='max(float(bench_simtime)/1.0e9)' \
|
|
-o-) \
|
|
-d <(./scripts/csv.py $(BUILDDIR)/lfs3.bench.csv \
|
|
-Dprobe=append,remove,create,delete,fetch,lookup,$\
|
|
commit,namelookup,$\
|
|
write,stat,read \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-fn='max(n)' \
|
|
-ft='max(float(bench_simtime)/1.0e9)' \
|
|
-o-) \
|
|
-bprobe \
|
|
-fthroughput='avg(float(n) / max(t, 1.0e-9))' \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Show which benches took the most time
|
|
.PHONY: bench-bottlenecks
|
|
bench-bottlenecks: SUMMARYFLAGS+=-Sruntime
|
|
bench-bottlenecks: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/csv.py $^ \
|
|
-Dprobe=append,remove,create,delete,fetch,lookup,$\
|
|
commit,namelookup,$\
|
|
write,stat,read \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-fn='max(n)' \
|
|
-ft='max(float(bench_simtime)/1.0e9)' \
|
|
-fruntime='max(bench_runtime)' \
|
|
-o-) \
|
|
-bprobe \
|
|
-fn \
|
|
-ft \
|
|
-fruntime \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Show the amount readed/progged/erased
|
|
.PHONY: bench-ops
|
|
bench-ops: SUMMARYFLAGS+=-Si
|
|
bench-ops: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py $^ \
|
|
-Dprobe=append,remove,create,delete,fetch,lookup,$\
|
|
commit,namelookup,$\
|
|
write,stat,read \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-freads='bench_reads' \
|
|
-fprogs='bench_progs' \
|
|
-ferases='bench_erases' \
|
|
-freaded='bench_readed' \
|
|
-fprogged='bench_progged' \
|
|
-ferased='bench_erased' \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Show average readed/progged/erased per width
|
|
.PHONY: bench-widths
|
|
bench-widths: SUMMARYFLAGS+=-Si
|
|
bench-widths: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py $^ \
|
|
-Dprobe=append,remove,create,delete,fetch,lookup,$\
|
|
commit,namelookup,$\
|
|
write,stat,read \
|
|
-bprobe='%(case)s+%(probe)s' \
|
|
-Fi='min(enumerate())' \
|
|
-freaded="avg(ffrac( \
|
|
float(bench_readed)/float(bench_reads), \
|
|
max(1, $$( \
|
|
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
|
|
--list-implicit-defines \
|
|
| sed -n 's/^READ_WIDTH=\(.*\)/\1/p'))))" \
|
|
-fprogged="avg(ffrac( \
|
|
float(bench_progged)/float(bench_progs), \
|
|
max(1, $$( \
|
|
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
|
|
--list-implicit-defines \
|
|
| sed -n 's/^PROG_WIDTH=\(.*\)/\1/p'))))" \
|
|
-ferased="avg(ffrac( \
|
|
float(bench_erased)/float(bench_erases), \
|
|
max(1, $$( \
|
|
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
|
|
--list-implicit-defines \
|
|
| sed -n 's/^ERASE_WIDTH=\(.*\)/\1/p'))))" \
|
|
$(SUMMARYFLAGS))
|
|
|
|
## Show heap/stack/disk usage
|
|
.PHONY: bench-usage
|
|
bench-usage: SUMMARYFLAGS+=-Si
|
|
bench-usage: $(BENCH_CSV)
|
|
$(strip ./scripts/csv.py \
|
|
<(./scripts/csv.py $^ \
|
|
-Dprobe=stack \
|
|
-bcase \
|
|
-Fi='min(enumerate())' \
|
|
-fstack='max(bench_simtime)' \
|
|
-o-) \
|
|
<(./scripts/csv.py $^ \
|
|
-Dprobe=heap \
|
|
-bcase \
|
|
-Fi='min(enumerate())' \
|
|
-fheap='max(bench_simtime)' \
|
|
-o-) \
|
|
<(./scripts/csv.py $^ \
|
|
-Dprobe=usage \
|
|
-bcase \
|
|
-Fi='min(enumerate())' \
|
|
-fdisk='max(bench_simtime)' \
|
|
-o-) \
|
|
-bcase \
|
|
-fstack \
|
|
-fheap \
|
|
-fdisk \
|
|
$(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)
|