Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
158 lines (143 loc) · 8.32 KB
/
Copy pathMakefile
File metadata and controls
158 lines (143 loc) · 8.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# sqlite-multiwriter: multi-writer SQLite as a wrapper VFS.
# make build the engine objects and the test programs
# make test run the test suite
# make bench build the benchmark (dist/mw_bench)
# make extension [PLATFORM=..] [ARCH=..] the loadable extension (dist/multiwriter.so|dylib|dll): see mk/extension.mk, `make help`
# SQLite (the amalgamation) is vendored in third_party/sqlite; nothing else is needed to build and test. The engine registers its VFS from inside sqlite3_initialize()
# through the compile option SQLITE_EXTRA_INIT (sqlite3.c itself is not modified).
CC ?= cc
SQLITE_DIR := third_party/sqlite
SRC_DIR := src
BUILD := build
DIST := dist
ifdef EXPERIMENTS
CFLAGS += -DMW_EXPERIMENTS # (make EXPERIMENTS=1: the knobs of measurement)
endif
CFLAGS += -O2 -g -Wall -Wno-unused-function -I$(SRC_DIR) -I$(SQLITE_DIR) -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
SQLITE_FLAGS := -DSQLITE_EXTRA_INIT=mw_extra_init -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE -DSQLITE_CORE
include mk/platform.mk
LDFLAGS += $(if $(filter android,$(PLATFORM)),,-lpthread) -lm
ifeq ($(PLATFORM),linux)
CFLAGS += -D_GNU_SOURCE
LDFLAGS += -ldl
endif
ifeq ($(PLATFORM),android)
CFLAGS += -D_GNU_SOURCE # (tests for a device or an emulator: make all PLATFORM=android CC=<ndk>/aarch64-linux-android26-clang)
LDFLAGS += -ldl
endif
ifeq ($(PLATFORM),linux-musl)
CFLAGS += -D_GNU_SOURCE
endif
ifeq ($(PLATFORM),windows)
LDFLAGS += -static # (no DLL of MinGW next to the programs)
endif
ENGINE_SRC := $(wildcard $(SRC_DIR)/*.c)
ENGINE_OBJ := $(patsubst $(SRC_DIR)/%.c,$(BUILD)/%.o,$(ENGINE_SRC))
HEADERS := $(wildcard $(SRC_DIR)/*.h)
LIB_OBJ := $(ENGINE_OBJ) $(BUILD)/sqlite3.o
TEST_SRC := $(wildcard test/mw_*.c)
ifeq ($(PLATFORM),windows)
# the tests that fork, wait for processes, map files or set the environment of a child are not for Windows (docs/windows.md)
TEST_SRC := $(filter-out $(filter-out $(shell grep -l MW_PORTABLE_TEST $(TEST_SRC)),$(shell grep -lE 'sys/wait.h|sys/mman.h|fork|setenv' $(TEST_SRC))) test/mw_relocprep.c test/mw_walstatfail.c,$(TEST_SRC)) # (mw_walstatfail: it replaces stat() and includes multiwriter_lane.c, POSIX only)
endif
TEST_BIN := $(patsubst test/%.c,$(DIST)/%$(EXE),$(TEST_SRC))
IO_TESTS := $(DIST)/mw_ioerr$(EXE) $(DIST)/mw_diskfull$(EXE) # (minutes: make test-io)
FAST_BIN := $(filter-out $(IO_TESTS),$(TEST_BIN))
.PHONY: all test bench clean test-mp test-io
all: $(TEST_BIN)
$(BUILD)/sqlite3.o: $(SQLITE_DIR)/sqlite3.c
@mkdir -p $(BUILD)
$(CC) $(CFLAGS) $(SQLITE_FLAGS) -w -c $< -o $@
$(BUILD)/%.o: $(SRC_DIR)/%.c $(HEADERS)
@mkdir -p $(BUILD)
$(CC) $(CFLAGS) -c $< -o $@
$(BUILD)/t_%.o: test/%.c $(HEADERS) test/mw_test.h
@mkdir -p $(BUILD)
$(CC) $(CFLAGS) -c $< -o $@
$(DIST)/mw_%$(EXE): $(BUILD)/t_mw_%.o $(LIB_OBJ)
@mkdir -p $(DIST)
$(CC) $^ -o $@ $(LDFLAGS)
# Deterministic fault injection, confined to the translation unit under test.
$(BUILD)/inject_log.o: $(SRC_DIR)/multiwriter_log.c $(HEADERS)
@mkdir -p $(BUILD)
$(CC) $(CFLAGS) -Dpwritev=inject_pwritev -c $< -o $@
$(BUILD)/inject_rowdiff.o: $(SRC_DIR)/multiwriter_rowdiff.c $(HEADERS)
@mkdir -p $(BUILD)
$(CC) $(CFLAGS) -Dmalloc=inject_malloc -Dcalloc=inject_calloc -Drealloc=inject_realloc -c $< -o $@
$(BUILD)/inject_autoext.o: $(SRC_DIR)/multiwriter_vfs.c $(HEADERS)
@mkdir -p $(BUILD)
$(CC) $(CFLAGS) -Dsqlite3_auto_extension=inject_auto_extension -c $< -o $@
$(BUILD)/inject_fsync.o: $(SRC_DIR)/multiwriter_log.c $(HEADERS)
@mkdir -p $(BUILD)
$(CC) $(CFLAGS) -Dfsync=inject_fsync -c $< -o $@
$(DIST)/mw_autoextfail$(EXE): $(BUILD)/t_mw_autoextfail.o $(filter-out $(BUILD)/multiwriter_vfs.o,$(LIB_OBJ)) $(BUILD)/inject_autoext.o
@mkdir -p $(DIST)
$(CC) $^ -o $@ $(LDFLAGS)
$(BUILD)/t_mw_walstatfail.o: $(SRC_DIR)/multiwriter_lane.c # (the test includes it)
$(DIST)/mw_walstatfail$(EXE): $(BUILD)/t_mw_walstatfail.o $(filter-out $(BUILD)/multiwriter_lane.o,$(LIB_OBJ))
@mkdir -p $(DIST)
$(CC) $^ -o $@ $(LDFLAGS)
$(BUILD)/t_mw_admitcap.o: $(SRC_DIR)/multiwriter_pages.c # (the test includes it)
$(DIST)/mw_admitcap$(EXE): $(BUILD)/t_mw_admitcap.o $(filter-out $(BUILD)/multiwriter_pages.o,$(LIB_OBJ))
@mkdir -p $(DIST)
$(CC) $^ -o $@ $(LDFLAGS)
$(DIST)/mw_holesync$(EXE): $(BUILD)/t_mw_holesync.o $(filter-out $(BUILD)/multiwriter_log.o,$(LIB_OBJ)) $(BUILD)/inject_fsync.o
@mkdir -p $(DIST)
$(CC) $^ -o $@ $(LDFLAGS)
$(DIST)/mw_stagednormal$(EXE): $(BUILD)/t_mw_stagednormal.o $(filter-out $(BUILD)/multiwriter_log.o,$(LIB_OBJ)) $(BUILD)/inject_log.o
@mkdir -p $(DIST)
$(CC) $^ -o $@ $(LDFLAGS)
$(DIST)/mw_rowdiffoom$(EXE): $(BUILD)/t_mw_rowdiffoom.o $(filter-out $(BUILD)/multiwriter_rowdiff.o,$(LIB_OBJ)) $(BUILD)/inject_rowdiff.o
@mkdir -p $(DIST)
$(CC) $^ -o $@ $(LDFLAGS)
.PRECIOUS: $(BUILD)/t_%.o
# the exit status of a failing test must survive the sanitizer runner (test/sanitize.sh); not for Windows, where the runner is not used
.PHONY: test-sanitize-runner
test-sanitize-runner:
ifeq ($(PLATFORM),windows)
@echo "sanitizer runner regression skipped (Windows)"
else
@if command -v bash >/dev/null 2>&1; then bash test/sanitize_exit.sh; else echo "sanitizer runner regression skipped (bash unavailable)"; fi
endif
test: $(FAST_BIN) test-sanitize-runner
@set -e; for t in $(FAST_BIN); do echo "== $$t"; ./$$t; done; echo "== mw_rebase (a WITHOUT ROWID table)"; MW_TEST_WR=1 ./$(DIST)/mw_rebase$(EXE)
# the suite of the CI legs that run it on shared machines: without mw_serial (about a minute and a half of stress, which has a threshold of events that a loaded machine can miss); `make test` runs everything
CI_BIN := $(filter-out $(DIST)/mw_serial$(EXE),$(FAST_BIN))
# ThreadSanitizer (test/sanitize.sh tsan; CC=clang in the CI): every test but the long ones (mw_serial mw_bigdb mw_ioerr mw_diskfull). A race that it reports inside SQLite itself is
# suppressed for the two tests that meet it (test/tsan.supp); the tests that fork need die_after_fork=0, which the script sets.
TSAN_TESTS := mw_admitcap mw_appendfail mw_attachsync mw_autoextfail mw_closestall mw_compact mw_compactdeath mw_compactruns mw_compactsync mw_compat mw_ddl mw_durability \
mw_fastcommit mw_format mw_fullfsync mw_gc mw_holesync mw_identity mw_lanes mw_lanetrim mw_logopen mw_logrewrite mw_logswap mw_mapfail mw_mpstale mw_multiproc \
mw_multiproc_crash mw_multiproc_liveness mw_openfail mw_openflags mw_openlocks mw_openrace mw_openrepair mw_oslayer mw_ownepoch mw_procs mw_profile mw_readdeps \
mw_rebase mw_rebasecases mw_rebasefk mw_rebasefkstress mw_rebaseneg mw_rebasenoop mw_rebasepolicy mw_rebaseskew mw_rebasewr mw_recoverread mw_reloc mw_relocprep \
mw_repairinstall mw_rollback mw_rollbackrace mw_routes mw_rowdiffoom mw_rowid mw_selfcommit mw_shared mw_sharedwindow mw_shidx mw_sizering mw_slotstuck mw_stacked \
mw_stagedlog mw_stagednormal mw_stalewal mw_store mw_strictany mw_structural mw_syfail mw_syncpragma mw_syncwindow mw_tailscan mw_tempbarrier mw_tempddl mw_ticketring \
mw_trimfail mw_vfs_trace mw_walstatfail mw_warm mw_writeskew
.PHONY: test-tsan
test-tsan:
bash test/sanitize.sh tsan $(TSAN_TESTS)
.PHONY: test-ci
test-ci: $(CI_BIN) test-sanitize-runner
@set -e; for t in $(CI_BIN); do echo "== $$t"; ./$$t; done; echo "== mw_rebase (a WITHOUT ROWID table)"; MW_TEST_WR=1 ./$(DIST)/mw_rebase$(EXE)
# errors of the file system: a fault at every n-th file call of a workload, and a real full disk (a small disk image)
.PHONY: test-io
test-io: $(IO_TESTS)
@set -e; for t in $(IO_TESTS); do echo "== $$t"; ./$$t; done
bench: $(DIST)/mw_bench$(EXE)
$(BUILD)/b_mw_bench.o: bench/mw_bench.c $(HEADERS)
@mkdir -p $(BUILD)
$(CC) $(CFLAGS) -c $< -o $@
$(DIST)/mw_bench$(EXE): $(BUILD)/b_mw_bench.o $(LIB_OBJ)
@mkdir -p $(DIST)
$(CC) $^ -o $@ $(LDFLAGS)
include mk/extension.mk
include mk/package.mk
clean:
rm -rf $(BUILD) $(DIST)
# the transaction tests with the shared multi-process mode (mw_mp=1) in place of the thread mode
MP_TESTS := mw_strictany mw_rebasepolicy mw_rebase mw_rebasefk mw_rebasefkstress mw_rebasenoop mw_rebaseskew mw_rebasewr mw_serial mw_relocprep mw_shared
ifeq ($(PLATFORM),windows)
MP_TESTS := mw_strictany mw_rebasepolicy mw_rebase mw_rebasefk mw_rebasefkstress mw_rebasenoop mw_rebaseskew mw_rebasewr mw_serial # (the others fork)
endif
.PHONY: test-mp
test-mp: $(addsuffix $(EXE),$(addprefix $(DIST)/,$(MP_TESTS)))
@set -e; for t in $(MP_TESTS); do echo "== $$t (mw_mp=1)"; MW_TEST_MP=1 ./$(DIST)/$$t; done