# 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"