blob: 8538a7d9c0549ca008692f1823d1e5dda8a0fa5e (
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
|
# Some of this is a little strange for this project,
# but this is just my default Makefile that I use.
#
# Largely inspired by this tutorial
# https://makefiletutorial.com/#top
CC := gcc
CFLAGS := -Wall -Wextra -Werror -std=c99 -pedantic
CFLAGS += -O2
# -DDEBUG is nice, I like 'printf debugging'. Makes it easy.
DEBUG_FLAGS := -g -O0 -DDEBUG -fsanitize=address,undefined \
-fno-omit-frame-pointer
LDFLAGS :=
DEBUG_LDFLAGS := -g -fsanitize=address,undefined
# Many of these variables are redundant for this project, but I prefer
# keeping the Makefile in the project root and separating artifacts into
# 'build' and 'target' directories alongside the 'src' directory.
SRC_DIR := .
BIN_DIR := .
OBJ_DIR := build
# Auto-generated dependency files
DEP_DIR := $(OBJ_DIR)/.deps
# Automatically find all C source files
SOURCES := $(wildcard $(SRC_DIR)/*.c)
# Map source files to object files:
# ./main.c -> build/main.o
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
# Map object files to dependency files:
# build/main.o -> build/.deps/main.d
DEPS := $(OBJECTS:$(OBJ_DIR)/%.o=$(DEP_DIR)/%.d)
# Target executable
TARGET := $(BIN_DIR)/detectCycles
.PHONY: all clean debug release help docs
all: $(TARGET)
# Build executable
$(TARGET): $(OBJECTS)
@mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
@echo "Build complete: $@"
# Compile object files
# -MMD :: generate dependency info (exclude system headers)
# -MP :: add phony targets for headers (prevents build errors)
# -MF :: write dependencies to a '.d' file
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(OBJ_DIR) $(DEP_DIR)
$(CC) $(CFLAGS) -MMD -MP \
-MF $(DEP_DIR)/$*.d -c $< -o $@
# Include auto-generated dependency files.
# The leading '-' suppresses errors if the .d files
# do not exist yet e.g. on a clean build.
-include $(DEPS)
# Debug build
debug: CFLAGS := $(filter-out -O2,$(CFLAGS)) $(DEBUG_FLAGS)
debug: LDFLAGS := $(LDFLAGS) $(DEBUG_LDFLAGS)
debug: clean $(TARGET)
@echo "Debug build complete"
# Release build
release: CFLAGS := $(CFLAGS) -DNDEBUG
release: clean $(TARGET)
@echo "Release build complete"
# Generate Doxygen documentation
docs:
@if command -v doxygen >/dev/null 2>&1; then \
doxygen Doxyfile; \
echo "Documentation generated"; \
else \
echo "Error: doxygen not found. Install it and try again."; \
exit 1; \
fi
# Clean build artifacts
clean:
rm -rf $(OBJ_DIR) $(TARGET)
@echo "Clean complete"
# Clean documentation
clean-docs:
rm -rf $(DOC_DIR)
@echo "Documentation cleaned"
# Help message
help:
@echo "Available targets:"
@echo " all - Build the project (default)"
@echo " debug - Build with debug symbols and no optimization"
@echo " release - Build optimized release version"
@echo " docs - Generate Doxygen documentation"
@echo " clean - Remove all build artifacts"
@echo " clean-docs - Remove generated documentation"
@echo " help - Display this help message"
|