|
5 | 5 | CC ?= cc |
6 | 6 | CPPFLAGS ?= |
7 | 7 | CFLAGS ?= -O3 -pipe -march=native -flto -DNDEBUG |
8 | | -WARNFLAGS ?= -Wall -Wextra -Wpedantic -Wno-sign-conversion |
9 | | -LDFLAGS ?= |
| 8 | +# Type-safety warning flags (strict mode) |
| 9 | +WARNFLAGS ?= -Wall -Wextra -Wpedantic \ |
| 10 | + -Wconversion -Wsign-conversion \ |
| 11 | + -Wcast-qual -Wformat=2 \ |
| 12 | + -Wstrict-overflow=5 -Wwrite-strings -Wundef \ |
| 13 | + -Wshadow -Wpointer-arith \ |
| 14 | + -Wcast-align -Wstrict-prototypes |
| 15 | +LDFLAGS ?= -lm |
10 | 16 |
|
11 | 17 | TARGET := mini-ccstatus |
12 | 18 | OBJ_DIR := obj |
13 | 19 | BIN_DIR := bin |
14 | | -OBJECTS := $(OBJ_DIR)/mini-ccstatus.o $(OBJ_DIR)/cJSON.o |
| 20 | +SRC_DIR := src |
| 21 | +LIB_DIR := lib |
| 22 | +TST_DIR := tests |
| 23 | +LOG_DIR := log |
| 24 | + |
| 25 | +# Source and object files |
| 26 | +SOURCES := main.c \ |
| 27 | + $(SRC_DIR)/cache.c \ |
| 28 | + $(SRC_DIR)/cli_parser.c \ |
| 29 | + $(SRC_DIR)/json_parser.c \ |
| 30 | + $(SRC_DIR)/token_calculator.c \ |
| 31 | + $(SRC_DIR)/display.c \ |
| 32 | + $(SRC_DIR)/safe_conv.c \ |
| 33 | + $(LIB_DIR)/cjson/cJSON.c |
| 34 | + |
| 35 | +# Release build configuration |
| 36 | +OBJ_DIR_RELEASE := $(OBJ_DIR)/release |
| 37 | +OBJECTS := $(addprefix $(OBJ_DIR_RELEASE)/, $(patsubst %.c,%.o,$(notdir $(SOURCES)))) |
| 38 | + |
| 39 | +# Common compilation settings |
| 40 | +COMPILE_FLAGS := $(CPPFLAGS) -I. -I$(LIB_DIR) |
| 41 | +COMMON_DEPS := $(SRC_DIR)/*.h $(LIB_DIR)/cjson/cJSON.h |
15 | 42 |
|
16 | 43 | # Debug build configuration (for valgrind and debugging) |
17 | | -CFLAGS_DEBUG := -g -O0 $(WARNFLAGS) |
18 | | -TARGET_DEBUG := mini-ccstatus-debug |
19 | | -OBJ_DIR_DEBUG := obj-debug |
20 | | -OBJECTS_DEBUG := $(OBJ_DIR_DEBUG)/mini-ccstatus.o $(OBJ_DIR_DEBUG)/cJSON.o |
| 44 | +CFLAGS_DEBUG_BASE := -g -O0 $(WARNFLAGS) |
| 45 | +CFLAGS_DEBUG := $(CFLAGS_DEBUG_BASE) -fanalyzer |
| 46 | +TARGET_DEBUG := mini-ccstatus-debug |
| 47 | +OBJ_DIR_DEBUG := $(OBJ_DIR)/debug |
| 48 | +OBJECTS_DEBUG := $(addprefix $(OBJ_DIR_DEBUG)/, $(patsubst %.c,%.o,$(notdir $(SOURCES)))) |
| 49 | + |
| 50 | +# Debug logging build configuration (debug + -DDEBUG for DEBUG_LOG macros) |
| 51 | +CFLAGS_DEBUG_LOG := $(CFLAGS_DEBUG_BASE) -DDEBUG |
| 52 | +TARGET_DEBUG_LOG := mini-ccstatus-debug-log |
| 53 | +OBJ_DIR_DEBUG_LOG := $(OBJ_DIR)/debug-log |
| 54 | +OBJECTS_DEBUG_LOG := $(addprefix $(OBJ_DIR_DEBUG_LOG)/, $(patsubst %.c,%.o,$(notdir $(SOURCES)))) |
21 | 55 |
|
22 | 56 | # Test scripts |
23 | | -DEMO_SCRIPT := tests/stdout.sh |
24 | | -TEST_SCRIPT := tests/coverage.sh |
25 | | -TEST_MEMORY := tests/memory.sh |
26 | | -TEST_VALGRIND := tests/valgrind.sh |
| 57 | +DEMO_QUIET_SCRIPT := $(TST_DIR)/stdout_quiet.sh |
| 58 | +DEMO_VERBOSE_SCRIPT := $(TST_DIR)/stdout_verbose.sh |
| 59 | +UNIT_TEST_SCRIPT := $(TST_DIR)/run_unit_tests.sh |
| 60 | +TEST_SCRIPT := $(TST_DIR)/coverage.sh |
| 61 | +TEST_MEMORY := $(TST_DIR)/memory.sh |
| 62 | +TEST_VALGRIND := $(TST_DIR)/valgrind.sh |
| 63 | + |
| 64 | +# Test fixtures |
27 | 65 | FIXTURES := fixtures/*.json |
28 | 66 |
|
29 | | -default: $(BIN_DIR)/$(TARGET) demo |
| 67 | +default: $(BIN_DIR)/$(TARGET) demo-simple |
30 | 68 |
|
31 | 69 | .PHONY: all |
32 | | -all: clean default test valgrind |
| 70 | +all: clean build-all demo-all test valgrind |
33 | 71 |
|
| 72 | +.PHONY: build-all |
| 73 | +build-all: $(BIN_DIR)/$(TARGET) $(BIN_DIR)/$(TARGET_DEBUG) $(BIN_DIR)/$(TARGET_DEBUG_LOG) |
| 74 | + |
| 75 | +.PHONY: demo-all |
| 76 | +demo-all: log-dir demo-simple demo-debug |
| 77 | + |
| 78 | +.PHONY: log-dir |
| 79 | +log-dir: |
| 80 | + @mkdir -p $(LOG_DIR) |
| 81 | + |
| 82 | +# Main target |
34 | 83 | $(BIN_DIR)/$(TARGET): $(OBJECTS) | $(BIN_DIR) |
35 | 84 | $(CC) $(OBJECTS) $(LDFLAGS) -o $@ |
36 | 85 |
|
37 | | -$(OBJ_DIR)/mini-ccstatus.o: mini-ccstatus.c lib/cjson/cJSON.h | $(OBJ_DIR) |
38 | | - $(CC) $(CPPFLAGS) $(CFLAGS) $(WARNFLAGS) -I. -Ilib -c $< -o $@ |
| 86 | +# Tell Make where to find source files |
| 87 | +vpath %.c . $(SRC_DIR) $(LIB_DIR)/cjson |
39 | 88 |
|
40 | | -$(OBJ_DIR)/cJSON.o: lib/cjson/cJSON.c lib/cjson/cJSON.h | $(OBJ_DIR) |
41 | | - $(CC) $(CPPFLAGS) $(CFLAGS) $(WARNFLAGS) -I. -Ilib -c $< -o $@ |
| 89 | +# Pattern rule for release build (VPATH handles source file lookup) |
| 90 | +$(OBJ_DIR_RELEASE)/%.o: %.c $(COMMON_DEPS) | $(OBJ_DIR_RELEASE) |
| 91 | + $(CC) $(COMPILE_FLAGS) $(CFLAGS) $(WARNFLAGS) -c $< -o $@ |
42 | 92 |
|
43 | | -$(OBJ_DIR) $(BIN_DIR): |
| 93 | +$(OBJ_DIR_RELEASE) $(OBJ_DIR_DEBUG) $(OBJ_DIR_DEBUG_LOG) $(BIN_DIR): |
44 | 94 | mkdir -p $@ |
45 | 95 |
|
46 | | -# Debug build targets |
| 96 | +# Debug build target |
47 | 97 | $(BIN_DIR)/$(TARGET_DEBUG): $(OBJECTS_DEBUG) | $(BIN_DIR) |
48 | 98 | $(CC) $(OBJECTS_DEBUG) $(LDFLAGS) -o $@ |
49 | 99 |
|
50 | | -$(OBJ_DIR_DEBUG)/mini-ccstatus.o: mini-ccstatus.c lib/cjson/cJSON.h | $(OBJ_DIR_DEBUG) |
51 | | - $(CC) $(CPPFLAGS) $(CFLAGS_DEBUG) -I. -Ilib -c $< -o $@ |
52 | | - |
53 | | -$(OBJ_DIR_DEBUG)/cJSON.o: lib/cjson/cJSON.c lib/cjson/cJSON.h | $(OBJ_DIR_DEBUG) |
54 | | - $(CC) $(CPPFLAGS) $(CFLAGS_DEBUG) -I. -Ilib -c $< -o $@ |
55 | | - |
56 | | -$(OBJ_DIR_DEBUG): |
57 | | - mkdir -p $@ |
| 100 | +# Pattern rule for debug build (VPATH handles source file lookup) |
| 101 | +$(OBJ_DIR_DEBUG)/%.o: %.c $(COMMON_DEPS) | $(OBJ_DIR_DEBUG) |
| 102 | + $(CC) $(COMPILE_FLAGS) $(CFLAGS_DEBUG) -c $< -o $@ |
58 | 103 |
|
59 | 104 | .PHONY: debug |
60 | 105 | debug: $(BIN_DIR)/$(TARGET_DEBUG) |
61 | 106 |
|
62 | | -.PHONY: test |
63 | | -test: $(BIN_DIR)/$(TARGET) $(TEST_SCRIPT) $(TEST_MEMORY) $(FIXTURES) |
64 | | - $(TEST_SCRIPT) |
65 | | - $(TEST_MEMORY) |
| 107 | +# Debug logging build target (with -DDEBUG for DEBUG_LOG macros) |
| 108 | +$(BIN_DIR)/$(TARGET_DEBUG_LOG): $(OBJECTS_DEBUG_LOG) | $(BIN_DIR) |
| 109 | + $(CC) $(OBJECTS_DEBUG_LOG) $(LDFLAGS) -o $@ |
| 110 | + |
| 111 | +# Pattern rule for debug-log build (VPATH handles source file lookup) |
| 112 | +$(OBJ_DIR_DEBUG_LOG)/%.o: %.c $(COMMON_DEPS) | $(OBJ_DIR_DEBUG_LOG) |
| 113 | + $(CC) $(COMPILE_FLAGS) $(CFLAGS_DEBUG_LOG) -c $< -o $@ |
66 | 114 |
|
67 | | -.PHONY: demo |
68 | | -demo: $(BIN_DIR)/$(TARGET) $(DEMO_SCRIPT) |
69 | | - $(DEMO_SCRIPT) |
70 | | - VERBOSE=true $(DEMO_SCRIPT) |
| 115 | +.PHONY: debug-log |
| 116 | +debug-log: $(BIN_DIR)/$(TARGET_DEBUG_LOG) |
| 117 | + |
| 118 | +.PHONY: test |
| 119 | +test: $(BIN_DIR)/$(TARGET) $(UNIT_TEST_SCRIPT) $(TEST_SCRIPT) $(TEST_MEMORY) $(FIXTURES) log-dir |
| 120 | + @echo "Running tests (logs: $(LOG_DIR)/test-*.log)..." |
| 121 | + $(UNIT_TEST_SCRIPT) 2>&1 | tee $(LOG_DIR)/test-unit.log |
| 122 | + $(TEST_SCRIPT) 2>&1 | tee $(LOG_DIR)/test-coverage.log |
| 123 | + $(TEST_MEMORY) 2>&1 | tee $(LOG_DIR)/test-memory.log |
| 124 | + |
| 125 | +.PHONY: demo-simple |
| 126 | +demo-simple: $(BIN_DIR)/$(TARGET) $(DEMO_QUIET_SCRIPT) $(DEMO_VERBOSE_SCRIPT) |
| 127 | + $(DEMO_QUIET_SCRIPT) |
| 128 | + $(DEMO_VERBOSE_SCRIPT) |
| 129 | + |
| 130 | +.PHONY: demo-debug |
| 131 | +demo-debug: $(BIN_DIR)/$(TARGET_DEBUG_LOG) log-dir |
| 132 | + @echo "Running with debug logging enabled..." |
| 133 | + @cat fixtures/status.json | $(BIN_DIR)/$(TARGET_DEBUG_LOG) > $(LOG_DIR)/demo-debug-basic.log 2>&1 |
| 134 | + @cat $(LOG_DIR)/demo-debug-basic.log |
| 135 | + @echo "" |
| 136 | + @echo "Running with --all flag and debug logging..." |
| 137 | + @cat fixtures/test_status_with_transcript.json | $(BIN_DIR)/$(TARGET_DEBUG_LOG) --all > $(LOG_DIR)/demo-debug-all.log 2>&1 |
| 138 | + @cat $(LOG_DIR)/demo-debug-all.log |
| 139 | + @echo "" |
| 140 | + @echo "Debug logs saved to $(LOG_DIR)/demo-debug-*.log" |
71 | 141 |
|
72 | 142 | .PHONY: valgrind |
73 | | -valgrind: $(TEST_VALGRIND) |
74 | | - $(TEST_VALGRIND) |
| 143 | +valgrind: $(TEST_VALGRIND) log-dir |
| 144 | + @echo "Running valgrind tests (logs: $(LOG_DIR)/test-valgrind.log)..." |
| 145 | + $(TEST_VALGRIND) 2>&1 | tee $(LOG_DIR)/test-valgrind.log |
| 146 | + |
| 147 | +# Static analysis targets |
| 148 | +.PHONY: lint |
| 149 | +lint: |
| 150 | + @echo "Running clang-tidy static analysis..." |
| 151 | + @clang-tidy $(SOURCES) -- -I. -I$(LIB_DIR) $(CPPFLAGS) $(WARNFLAGS) |
| 152 | + |
| 153 | +.PHONY: analyze |
| 154 | +analyze: debug |
| 155 | + @echo "Running GCC static analyzer..." |
| 156 | + @$(MAKE) clean |
| 157 | + @$(MAKE) debug 2>&1 | grep -E '(warning:|error:)' || echo "No analyzer warnings found" |
| 158 | + |
| 159 | +.PHONY: clang |
| 160 | +clang: |
| 161 | + @echo "Generating compile_commands.json for clangd..." |
| 162 | + -@bear -- $(MAKE) clean |
| 163 | + -@bear -- $(MAKE) |
| 164 | + @echo "compile_commands.json generated successfully" |
75 | 165 |
|
76 | 166 | .PHONY: clean |
77 | 167 | clean: |
78 | | - rm -rfv $(BIN_DIR) $(OBJ_DIR) $(OBJ_DIR_DEBUG) |
| 168 | + rm -rfv $(BIN_DIR) $(OBJ_DIR) $(OBJ_DIR_DEBUG) $(OBJ_DIR_DEBUG_LOG) $(LOG_DIR) compile_commands.json |
0 commit comments