Skip to content

Commit 50c04c0

Browse files
authored
The second revision (#8)
1 parent ac54a58 commit 50c04c0

18 files changed

+2080
-554
lines changed

.editorconfig

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ max_line_length = 100
2121
max_line_length = 120
2222
trim_trailing_whitespace = false # Don't remove trailing whitespace in Markdown files
2323
24-
# Bash scripts
25-
[*.sh]
26-
indent_size = 2
27-
2824
# YAML files
2925
[*.{yml,yaml}]
3026
indent_size = 2
3127
28+
# Bash files
29+
[*.{sh,bash}]
30+
indent_size = 2
31+
indent_style = tab
32+
max_line_length = 100
3233

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ temp/
137137
poetry.lock
138138

139139
# Additional files and directories to ignore (put below)
140-
doc/html
140+
doc
141141
target
142142
*.log\.*
143+
profile_report.txt
144+
perf.data
145+
*.old
146+
*.folded
147+
*.perf

Doxyfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ INPUT = .
1515
FILE_PATTERNS = *.c *.h *.cpp *.hpp
1616
RECURSIVE = YES
1717
EXTRACT_ALL = YES
18+
EXCLUDE_PATTERNS = tmp
1819

1920
#---------------------------------------------------------------------------
2021
# Output formats

Makefile

Lines changed: 113 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,84 @@
1+
# General Variables
2+
SHELL := bash
3+
14
# Build configuration
25
CC ?= clang
36
ENABLE_ASAN ?= 0
47
BUILD_TYPE ?= debug
5-
CFLAGS := -Wall -Wextra -pedantic -std=c11 -Iinclude
6-
LDFLAGS :=
7-
LIBS :=
88

99
# Directories
10-
BIN_DIR := bin
11-
TEST_DIR := test
12-
INC_DIR := include
13-
DOC_DIR := doc
10+
BIN_DIR := bin
11+
TEST_DIR := test
12+
INC_DIR := include
13+
DOC_DIR := doc
14+
ASSET_DIR := assets
15+
16+
# Flags
17+
CFLAGS_BASE := -Wall -Wextra -pedantic -std=c11 -I$(INC_DIR)
18+
LDFLAGS :=
19+
LIBS :=
1420

1521
# Sanitizer configuration
1622
ifeq ($(ENABLE_ASAN),1)
17-
CFLAGS += -fsanitize=address
18-
LDFLAGS += -fsanitize=address
23+
CFLAGS_SAN := -fsanitize=address
24+
LDFLAGS += -fsanitize=address
1925
export ASAN_OPTIONS=verbosity=0:detect_leaks=1:log_path=asan.log
2026
endif
2127

2228
# Build type configuration
2329
ifeq ($(BUILD_TYPE),release)
24-
CFLAGS += -O2 -DNDEBUG
30+
CFLAGS_TYPE := -O2 -DNDEBUG
2531
else
26-
CFLAGS += -g -O0
32+
CFLAGS_TYPE := -g -O0
2733
endif
2834

29-
# Test and benchmark binaries
30-
TEST_BINARY := $(BIN_DIR)/test_bptree
31-
BENCH_BINARY := $(BIN_DIR)/bench_bptree
35+
# Combine flags
36+
CFLAGS := $(CFLAGS_BASE) $(CFLAGS_SAN) $(CFLAGS_TYPE)
37+
38+
# Binary names
39+
TEST_BINARY := $(BIN_DIR)/test_bptree
40+
BENCH_BINARY := $(BIN_DIR)/bench_bptree
3241
EXAMPLE_BINARY := $(BIN_DIR)/example
3342

43+
# Default target
3444
.DEFAULT_GOAL := help
3545

3646
.PHONY: help
37-
help: ## Show the targets and their descriptions
38-
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; \
39-
{printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
47+
help: ## Show available targets
48+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
49+
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
4050

4151
$(BIN_DIR):
4252
mkdir -p $(BIN_DIR)
4353

54+
##############################################################################################################
55+
## Pattern Rule for Building Binaries
56+
##############################################################################################################
57+
# This rule compiles a C file in the TEST_DIR into a binary in BIN_DIR
58+
$(BIN_DIR)/%: $(TEST_DIR)/%.c | $(BIN_DIR)
59+
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
60+
61+
##############################################################################################################
62+
## Conventional Targets
63+
##############################################################################################################
64+
4465
.PHONY: all
45-
all: clean doc test bench example ## Build all targets and run tests and benchmarks
66+
all: clean test bench example doc ## Build everything, run tests, benchmarks, and generate docs
4667

4768
.PHONY: test
4869
test: $(TEST_BINARY) ## Build and run tests
4970
@echo "Running tests..."
5071
./$(TEST_BINARY)
5172

52-
$(TEST_BINARY): $(TEST_DIR)/test_bptree.c $(INC_DIR)/bptree.h | $(BIN_DIR)
53-
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
54-
5573
.PHONY: bench
5674
bench: $(BENCH_BINARY) ## Build and run benchmarks
5775
@echo "Running benchmarks..."
5876
./$(BENCH_BINARY)
5977

60-
$(BENCH_BINARY): $(TEST_DIR)/bench_bptree.c $(INC_DIR)/bptree.h | $(BIN_DIR)
61-
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
78+
.PHONY: example
79+
example: $(EXAMPLE_BINARY) ## Run example program
80+
@echo "Running the example..."
81+
./$(EXAMPLE_BINARY)
6282

6383
.PHONY: clean
6484
clean: ## Remove build artifacts
@@ -68,7 +88,7 @@ clean: ## Remove build artifacts
6888
.PHONY: format
6989
format: ## Format source code
7090
@echo "Formatting source code..."
71-
@command -v clang-format >/dev/null 2>&1 || { echo >&2 "clang-format not found."; exit 1; }
91+
@command -v clang-format >/dev/null 2>&1 || { echo "clang-format not found."; exit 1; }
7292
clang-format -i $(TEST_DIR)/*.c $(INC_DIR)/*.h
7393

7494
.PHONY: lint
@@ -77,8 +97,8 @@ lint: ## Run linter checks
7797
cppcheck --enable=all --inconclusive --quiet --std=c11 -I$(INC_DIR) $(TEST_DIR)
7898

7999
.PHONY: install
80-
install: ## Install header file
81-
@echo "Installing bptree.h system-wide..."
100+
install: ## Install header file system-wide
101+
@echo "Installing bptree.h..."
82102
install -d /usr/local/include
83103
install -m 0644 $(INC_DIR)/bptree.h /usr/local/include/
84104

@@ -88,10 +108,11 @@ uninstall: ## Remove installed header file
88108
rm -f /usr/local/include/bptree.h
89109

90110
.PHONY: install-deps
91-
install-deps: ## Install development dependencies (for Debian-based systems)
111+
install-deps: ## Install development dependencies (Debian-based)
92112
@echo "Installing development dependencies..."
93113
sudo apt-get update && sudo apt-get install -y \
94-
gcc gdb clang clang-format cppcheck valgrind
114+
gcc gdb clang clang-format clang-tools cppcheck valgrind graphviz \
115+
kcachegrind graphviz linux-tools-common linux-tools-generic linux-tools-$(shell uname -r)
95116

96117
.PHONY: coverage
97118
coverage: CFLAGS += -fprofile-arcs -ftest-coverage
@@ -103,33 +124,76 @@ coverage: clean $(TEST_BINARY) ## Generate code coverage report
103124
gcov -o $(BIN_DIR) $(TEST_DIR)/test_bptree.c
104125
@echo "Coverage report generated"
105126

106-
.PHONY: memcheck
107-
memcheck: $(EXAMPLE_BINARY) $(TEST_BINARY) $(BENCH_BINARY) ## Run memory checks with Valgrind
108-
@echo "Running memory checks..."
109-
@echo "Running example with Valgrind..."
110-
valgrind --leak-check=full --show-leak-kinds=all ./$(EXAMPLE_BINARY)
111-
@echo "Running tests with Valgrind..."
112-
valgrind --leak-check=full --show-leak-kinds=all ./$(TEST_BINARY)
113-
@echo "Running benchmarks with Valgrind..."
114-
valgrind --leak-check=full --show-leak-kinds=all ./$(BENCH_BINARY)
115-
@echo "Valgrind checks completed"
116-
117127
.PHONY: doc
118-
doc: ## Generate documentation
128+
doc: ## Generate documentation using Doxygen
119129
@echo "Generating documentation..."
120130
@test -f Doxyfile || { echo "Error: Doxyfile not found."; exit 1; }
121131
doxygen Doxyfile
122132

123-
.PHONY: example
124-
example: $(EXAMPLE_BINARY) ## Run examples
125-
@echo "Running the example..."
126-
./$(EXAMPLE_BINARY)
133+
.PHONY: figure
134+
figure: ## Generate figures using Graphviz
135+
@echo "Generating figures..."
136+
@$(SHELL) $(ASSET_DIR)/make_figures.sh $(ASSET_DIR)
127137

128-
$(EXAMPLE_BINARY): $(TEST_DIR)/example.c $(INC_DIR)/bptree.h | $(BIN_DIR)
129-
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
138+
##############################################################################################################
139+
## Release and Debugging Targets
140+
##############################################################################################################
130141

131142
.PHONY: release
132143
release: BUILD_TYPE=release
133-
release: all ## Build everything in release mode (optimized)
134-
@echo "Building in release mode..."
135-
@$(MAKE) all
144+
release: all ## Like 'all', but builds with code optimizations
145+
@echo "Built in release mode."
146+
147+
.PHONY: memcheck
148+
memcheck: $(EXAMPLE_BINARY) $(TEST_BINARY) $(BENCH_BINARY) ## Run Valgrind memory checks
149+
@echo "Running Valgrind memory checks..."
150+
valgrind --leak-check=full --show-leak-kinds=all ./$(EXAMPLE_BINARY)
151+
valgrind --leak-check=full --show-leak-kinds=all ./$(TEST_BINARY)
152+
valgrind --leak-check=full --show-leak-kinds=all ./$(BENCH_BINARY)
153+
@echo "Valgrind checks completed"
154+
155+
.PHONY: profile
156+
profile: CFLAGS += -pg
157+
profile: LDFLAGS += -pg
158+
profile: clean $(BENCH_BINARY) ## Build and run with gprof profiling
159+
@echo "Running profiling (gprof)..."
160+
./$(BENCH_BINARY)
161+
gprof $(BENCH_BINARY) gmon.out > profile_report.txt
162+
@echo "Profile report saved as profile_report.txt"
163+
164+
.PHONY: ubsan
165+
ubsan: CFLAGS += -fsanitize=undefined
166+
ubsan: LDFLAGS += -fsanitize=undefined
167+
ubsan: clean $(TEST_BINARY) ## Run tests with UndefinedBehaviorSanitizer
168+
@echo "Running UBSan tests..."
169+
UBSAN_OPTIONS=print_stacktrace=1 ./$(TEST_BINARY)
170+
171+
.PHONY: analyze
172+
analyze: ## Run Clang Static Analyzer
173+
@echo "Running Clang Static Analyzer..."
174+
scan-build --status-bugs $(MAKE) clean all
175+
176+
.PHONY: perf
177+
perf: $(BENCH_BINARY) ## Profile using Linux perf
178+
@echo "Recording perf data..."
179+
@echo "If necessary, run: sudo sh -c 'echo 1 > /proc/sys/kernel/perf_event_paranoid'"
180+
perf record -g ./$(BENCH_BINARY)
181+
@echo "Launching perf report..."
182+
perf report
183+
184+
.PHONY: callgrind
185+
callgrind: $(BENCH_BINARY) ## Profile using Valgrind's callgrind
186+
valgrind --tool=callgrind --callgrind-out-file=callgrind.out ./$(BENCH_BINARY)
187+
@echo "Callgrind output saved to callgrind.out"
188+
@echo "Use 'kcachegrind callgrind.out' to visualize"
189+
190+
.PHONY: cachegrind
191+
cachegrind: $(BENCH_BINARY) ## Profile CPU cache usage using Valgrind's cachegrind
192+
valgrind --tool=cachegrind --cachegrind-out-file=cachegrind.out ./$(BENCH_BINARY)
193+
@echo "Cachegrind output saved to cachegrind.out"
194+
@echo "Use 'cg_annotate cachegrind.out' to read the report"
195+
196+
.PHONY: trace
197+
trace: $(BENCH_BINARY) ## Trace syscalls using strace
198+
strace -o trace.log -T -tt ./$(BENCH_BINARY)
199+
@echo "Syscall trace saved to trace.log"

0 commit comments

Comments
 (0)