CC = gcc CFLAGS = -std=c17 \ -pedantic \ -pedantic-errors \ -Werror \ -Wall \ -Wextra \ -Wshadow \ -Wstrict-prototypes \ -Wmissing-prototypes \ -Wold-style-definition \ -Wformat=2 \ -Wcast-qual \ -Wwrite-strings \ -Winit-self \ -Wnull-dereference \ -Wdouble-promotion \ -Wconversion \ -Wsign-conversion \ -Wsign-compare \ -Wtype-limits \ -Wunreachable-code \ -Wswitch-enum \ -Wswitch-default \ -Wundef \ -Wendif-labels \ -Wpointer-arith \ -Wredundant-decls \ -Wbad-function-cast \ -Wmissing-noreturn \ -Wnested-externs \ -Wlogical-op \ -Wclobbered \ -Wfloat-equal \ -Wrestrict \ -Wsequence-point \ -Waddress \ -Wvla \ -Wduplicated-cond \ -Wduplicated-branches \ -fno-common \ -ftrapv \ -fstack-protector-strong DEBUG_FLAGS = -g3 -O0 -fsanitize=undefined -fno-omit-frame-pointer RELEASE_FLAGS = -O2 -D NDEBUG TEST_FLAGS = -g PROJECT_NAME != basename "$$(pwd)" VERSION != cat config/version 2>/dev/null SOURCE_FILES != cat config/source_code_list 2>/dev/null INCLUDES != cat config/header_list 2>/dev/null # --- INCREMENTAL BUILD SETUP --- # Map source files (.c) to object files (.o) in isolated directories DEBUG_OBJ_FILES = $(patsubst %.c, output/obj_debug/%.o, $(SOURCE_FILES)) RELEASE_OBJ_FILES = $(patsubst %.c, output/obj_release/%.o, $(SOURCE_FILES)) # Map object files to dependency files (.d) generated by the compiler DEP_FILES = $(DEBUG_OBJ_FILES:.o=.d) $(RELEASE_OBJ_FILES:.o=.d) help: @echo "Please use: 'make init' 'make debug', 'make fast', 'make release', 'make synch', or 'make clean'" init: @mkdir -p output source_code includes config @touch config/source_code_list config/version config/header_list source_code/main.c @date +_%y.%j.%H.%M%S > config/version @echo source_code/main.c > config/source_code_list synch: @echo "Synchronizing source code files..." @find source_code -type f -name '*.c' | sort > config/source_code_list @echo "Synchronizing header files..." @find includes -type f -name '*.h' | sort > config/header_list @echo "Synchronization complete." clean: rm -rf output/obj_debug output/obj_release output/$(PROJECT_NAME)* @echo "Project Cleaned" debug: $(DEBUG_OBJ_FILES) $(CC) $(CFLAGS) $(DEBUG_FLAGS) -o output/$(PROJECT_NAME)$(VERSION) $(DEBUG_OBJ_FILES) fast: $(RELEASE_OBJ_FILES) $(CC) $(CFLAGS) $(RELEASE_FLAGS) -o output/$(PROJECT_NAME)$(VERSION) $(RELEASE_OBJ_FILES) release: $(RELEASE_OBJ_FILES) @echo "Project version updated from: $(VERSION)" @date +_%y.%j.%H.%M%S > config/version @echo "To: $$(cat config/version)" @echo "" $(CC) $(CFLAGS) $(RELEASE_FLAGS) -o output/$(PROJECT_NAME)$$(cat config/version) $(RELEASE_OBJ_FILES) # --- COMPILATION PATTERN RULES --- # Compile Debug Objects output/obj_debug/%.o: %.c @mkdir -p $(dir $@) $(CC) $(CFLAGS) $(DEBUG_FLAGS) -I includes -MMD -MP -c $< -o $@ # Compile Release/Fast Objects output/obj_release/%.o: %.c @mkdir -p $(dir $@) $(CC) $(CFLAGS) $(RELEASE_FLAGS) -I includes -MMD -MP -c $< -o $@ # Automatically pull in header dependencies -include $(DEP_FILES) .PHONY: help synch clean debug fast release