summaryrefslogtreecommitdiff
path: root/Makefile
blob: ee8097533eb23dfb2ef726ed3c05cd203d10f587 (plain)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
BIN = chat-server
SRCS = $(wildcard src/*.cpp)
HEADERS = $(wildcard src/*.hpp)

PREFIX ?= /usr
BINDIR ?= $(PREFIX)/bin
DATADIR ?= $(PREFIX)/share
BUILDDIR ?= build

OBJS = $(patsubst src/%, $(BUILDDIR)/%, $(SRCS:.cpp=.o))

CXXFLAGS += -std=c++26 -Oz -s -Wall -Wextra -flto -fPIC -Wpedantic
LDFLAGS += -Wl,--as-needed,-z,now,-z,pack-relative-relocs

# Debug flags
DEBUG_CXXFLAGS = -std=c++26 -g3 -O0 -Wall -Wextra -fno-lto -fPIC -DDEBUG -fsanitize=thread -fno-omit-frame-pointer -pthread
DEBUG_LDFLAGS = -Wl,--no-as-needed,-z,now,-z,pack-relative-relocs -fsanitize=thread -lpthread

# Address Sanitizer Debug flags (run with make asan)
ASAN_CXXFLAGS = -std=c++26 -g3 -O0 -Wall -Wextra -fno-lto -fPIC -DDEBUG -fsanitize=address -fno-omit-frame-pointer -pthread
ASAN_LDFLAGS = -Wl,--no-as-needed,-z,now,-z,pack-relative-relocs -fsanitize=address -lpthread

# Memory Sanitizer Debug flags (run with make msan)
MSAN_CXXFLAGS = -std=c++26 -g3 -O0 -Wall -Wextra -fno-lto -fPIC -DDEBUG -fsanitize=memory -fno-omit-frame-pointer -fsanitize-memory-track-origins=2 -pthread
MSAN_LDFLAGS = -Wl,--no-as-needed,-z,now,-z,pack-relative-relocs -fsanitize=memory -lpthread

# UB Sanitizer Debug flags (run with make ubsan)
UBSAN_CXXFLAGS = -std=c++26 -g3 -O0 -Wall -Wextra -fno-lto -fPIC -DDEBUG -fsanitize=undefined -fno-omit-frame-pointer -pthread
UBSAN_LDFLAGS = -Wl,--no-as-needed,-z,now,-z,pack-relative-relocs -fsanitize=undefined -lpthread

CXXFLAGS += $(shell pkg-config --cflags ftxui)
LDFLAGS += $(shell pkg-config --libs ftxui)
DEBUG_CXXFLAGS += $(shell pkg-config --cflags ftxui)
DEBUG_LDFLAGS += $(shell pkg-config --libs ftxui)

$(shell mkdir -p $(BUILDDIR))
JOB_COUNT := $(BIN) $(OBJS)
JOBS_DONE := $(shell ls -l $(JOB_COUNT) 2> /dev/null | wc -l)

NPROC := $(shell nproc 2>/dev/null || getconf NPROCESSORS_CONF || echo 2)
MAKEFLAGS += -j$(NPROC)

define progress
	$(eval JOBS_DONE := $(shell echo $$(($(JOBS_DONE) + 1))))
	@printf "[$(JOBS_DONE)/$(shell echo $(JOB_COUNT) | wc -w)] %s %s\n" $(1) $(2)
endef

all: $(BIN) 

install: $(all)
	@echo "Installing..."
	@install -D -t $(DESTDIR)$(BINDIR) $(BUILDDIR)/$(BIN)

clean:
	@echo "Cleaning up"
	-@rm $(OBJS)

clean-all: clean
	@echo "Cleaning up all"
	-@rm -rf $(BUILDDIR)/$(BIN)

$(BUILDDIR)/$(BIN): $(OBJS)
	$(call progress, Linking $@)
	@$(CXX) -o $@ \
	$(OBJS) \
	$(CXXFLAGS) \
	$(LDFLAGS)

$(BIN): $(BUILDDIR)/$(BIN)


$(BUILDDIR)/%.o: src/%.cpp
	$(call progress, Compiling $@)
	@$(CXX) -c $< -o $@ \
	$(CXXFLAGS)

clang-format:
	@echo "Formatting code..."
	@clang-format -i $(SRCS) $(HEADERS)

clang-tidy:
	@echo "Running clang-tidy..."
	@clang-tidy -fix-errors $(SRCS) -- $(CXXFLAGS)

.PHONY: all install clean clean-all $(BIN) debug asan msan ubsan helgrind valgrind drd threadcheck compile_commands dchecks dthread live_tsan llvm_libfuzzer stack_combo deadlock pgo-gen pgo-use perf-analysis clang-format clang-tidy

debug: CXXFLAGS = $(DEBUG_CXXFLAGS)
debug: LDFLAGS = $(DEBUG_LDFLAGS)
# debug: CC = afl-g++
# debug: CXX = afl-g++
# debug: export AFL_USE_ASAN = 1
debug: $(BIN)
	@echo "Debug build complete (Thread Sanitizer enabled)"

asan: CXXFLAGS = $(ASAN_CXXFLAGS)
asan: LDFLAGS = $(ASAN_LDFLAGS)
asan: $(BIN)
	@echo "Debug build complete (Address Sanitizer enabled)"

msan: CXXFLAGS = $(MSAN_CXXFLAGS)
msan: LDFLAGS = $(MSAN_LDFLAGS)
msan: $(BIN)
	@echo "Debug build complete (Memory Sanitizer enabled)"

ubsan: CXXFLAGS = $(UBSAN_CXXFLAGS)
ubsan: LDFLAGS = $(UBSAN_LDFLAGS)
ubsan: $(BIN)
	@echo "Debug build complete (Undefined Behavior Sanitizer enabled)"

dthread: CXXFLAGS = $(DEBUG_CXXFLAGS)
dthread: LDFLAGS = $(DEBUG_LDFLAGS)
dthread: $(BIN)
	@echo "Debug build complete (Enhanced Thread Sanitizer enabled)"
	TSAN_OPTIONS="history_size=10 report_thread_leaks=1 report_signal_unsafe=1 halt_on_error=1 second_deadlock_stack=1" $(BUILDDIR)/$(BIN) $(ARGS)

helgrind: debug
	@echo "Running with Valgrind Helgrind thread checker"
	valgrind --tool=helgrind --read-var-info=yes --track-lockorders=yes $(BUILDDIR)/$(BIN) $(ARGS)

valgrind: debug
	@echo "Running with Valgrind memory checker"
	valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes $(BUILDDIR)/$(BIN) $(ARGS)

drd: debug
	@echo "Running with Valgrind DRD (Data Race Detector)"
	valgrind --tool=drd --check-stack-var=yes --first-race-only=yes $(BUILDDIR)/$(BIN) $(ARGS)

dchecks: CXXFLAGS = -std=c++26 -g3 -O0 -Wall -Wextra -fno-lto -fPIC -DDEBUG -fsanitize=thread,undefined -fno-omit-frame-pointer -pthread
dchecks: LDFLAGS = -Wl,--no-as-needed,-z,now,-z,pack-relative-relocs -fsanitize=thread,undefined -lpthread
dchecks: $(BIN)
	@echo "Debug build complete (Thread & UB Sanitizers enabled)"

threadcheck: debug
	@echo "Running with Thread Sanitizer"
	TSAN_OPTIONS="history_size=7 halt_on_error=1 second_deadlock_stack=1" $(BUILDDIR)/$(BIN) $(ARGS)

live_tsan: CXXFLAGS = $(DEBUG_CXXFLAGS)
live_tsan: LDFLAGS = $(DEBUG_LDFLAGS)
live_tsan: $(BIN)
	@echo "Running with live Thread Sanitizer (continues after errors)"
	TSAN_OPTIONS="history_size=15 report_thread_leaks=1 report_signal_unsafe=1 halt_on_error=0 second_deadlock_stack=1" $(BUILDDIR)/$(BIN) $(ARGS)

llvm_libfuzzer: CXXFLAGS = -std=c++26 -g -O1 -Wall -Wextra -fno-lto -fPIC -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=fuzzer,address -fno-omit-frame-pointer
llvm_libfuzzer: LDFLAGS = -Wl,--no-as-needed,-z,now,-z,pack-relative-relocs -fsanitize=fuzzer,address
llvm_libfuzzer: $(BIN)
	@echo "Fuzzer build complete (note: requires clang compiler)"

stack_combo: CXXFLAGS = -std=c++26 -g3 -O0 -Wall -Wextra -fno-lto -fPIC -DDEBUG -fsanitize=address,undefined -fno-omit-frame-pointer -pthread
stack_combo: LDFLAGS = -Wl,--no-as-needed,-z,now,-z,pack-relative-relocs -fsanitize=address,undefined -lpthread
stack_combo: $(BIN)
	@echo "Debug build complete (Combined ASan and UBSan)"
	ASAN_OPTIONS="detect_leaks=1:check_initialization_order=1:detect_stack_use_after_return=1" $(BUILDDIR)/$(BIN) $(ARGS)

compile_commands:
	compiledb -n make


deadlock: CXXFLAGS = $(DEBUG_CXXFLAGS) -DENABLE_DEADLOCK_DETECTION
deadlock: LDFLAGS = $(DEBUG_LDFLAGS)
deadlock: $(BIN)
	@echo "Debug build complete (with deadlock detection)"
	TSAN_OPTIONS="detect_deadlocks=1:second_deadlock_stack=1:report_thread_leaks=1:halt_on_error=0" $(BUILDDIR)/$(BIN) $(ARGS)

pgo-gen: CXXFLAGS = -std=c++26 -O2 -Wall -Wextra -fprofile-generate -fPIC
pgo-gen: LDFLAGS = -Wl,--as-needed,-z,now,-z,pack-relative-relocs -fprofile-generate
pgo-gen: $(BIN)
	@echo "Profile generation build complete (run app with typical workload)"

pgo-use: CXXFLAGS = -std=c++26 -Oz -Wall -Wextra -fprofile-use -fprofile-correction -fPIC
pgo-use: LDFLAGS = -Wl,--as-needed,-z,now,-z,pack-relative-relocs -fprofile-use
pgo-use: $(BIN)
	@echo "Optimized build using profile data complete"

perf-analysis: CXXFLAGS = -std=c++26 -g -O2 -Wall -Wextra -fno-lto -fno-omit-frame-pointer
perf-analysis: LDFLAGS = -Wl,--as-needed,-z,now,-z,pack-relative-relocs
perf-analysis: $(BIN)
	@echo "Performance analysis build complete"
	valgrind --tool=callgrind --callgrind-out-file=callgrind.out $(BUILDDIR)/$(BIN) $(ARGS)
	@echo "Run 'callgrind_annotate callgrind.out' to view results"