diff --git a/makefile b/makefile index 6d91953..c859e91 100644 --- a/makefile +++ b/makefile @@ -1,110 +1,99 @@ +.POSIX: + 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 \ + -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 +DEBUG_FLAGS = -g3 -O0 -fsanitize=undefined +RELEASE_FLAGS = -O2 -s -D NDEBUG -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) +all: help help: - @echo "Please use: 'make init' 'make debug', 'make fast', 'make release', 'make synch', or 'make clean'" + @echo "Please use: 'make init', 'make debug', 'make fast', 'make release', or 'make clean'" + @echo "Supports parallel builds (e.g., 'make -j8 debug')" 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." + @touch config/version source_code/main.c + @echo "_00.000.00.0000" > config/version + @echo "Project initialized." clean: - rm -rf output/obj_debug output/obj_release output/$(PROJECT_NAME)* + @rm -rf output/obj_debug output/obj_release config/*.mk + @rm -f output/* @echo "Project Cleaned" -debug: $(DEBUG_OBJ_FILES) - $(CC) $(CFLAGS) $(DEBUG_FLAGS) -o output/$(PROJECT_NAME)$(VERSION) $(DEBUG_OBJ_FILES) +# ------------------------------ +# Dynamic Build Graph Generators +debug: + @mkdir -p config output/obj_debug + @PROJ_NAME=$$(basename "$$(pwd)"); \ + VERS=$$(cat config/version 2>/dev/null || echo "_00.000.00.0000"); \ + OUT="output/$${PROJ_NAME}$${VERS}"; \ + MK="config/debug.mk"; \ + echo ".POSIX:" > $$MK; \ + HEADERS=$$(find includes -type f -name '*.h' | tr '\n' ' '); \ + OBJS=""; \ + for SRC in $$(find source_code -type f -name '*.c'); do \ + OBJ="output/obj_debug/$${SRC}.o"; \ + OBJS="$$OBJS $$OBJ"; \ + echo "$$OBJ: $$SRC $$HEADERS" >> $$MK; \ + echo " @mkdir -p $$(dirname $$OBJ)" >> $$MK; \ + echo " $(CC) $(CFLAGS) $(DEBUG_FLAGS) -I includes -c $$SRC -o $$OBJ" >> $$MK; \ + done; \ + echo "$$OUT: $$OBJS" >> $$MK; \ + echo " $(CC) $(CFLAGS) $(DEBUG_FLAGS) -o $$OUT $$OBJS" >> $$MK; \ + $(MAKE) -f $$MK "$$OUT" -fast: $(RELEASE_OBJ_FILES) - $(CC) $(CFLAGS) $(RELEASE_FLAGS) -o output/$(PROJECT_NAME)$(VERSION) $(RELEASE_OBJ_FILES) +fast: + @mkdir -p config output/obj_release + @PROJ_NAME=$$(basename "$$(pwd)"); \ + VERS=$$(cat config/version 2>/dev/null || echo "_00.000.00.0000"); \ + OUT="output/$${PROJ_NAME}$${VERS}"; \ + MK="config/fast.mk"; \ + echo ".POSIX:" > $$MK; \ + HEADERS=$$(find includes -type f -name '*.h' | tr '\n' ' '); \ + OBJS=""; \ + for SRC in $$(find source_code -type f -name '*.c'); do \ + OBJ="output/obj_release/$${SRC}.o"; \ + OBJS="$$OBJS $$OBJ"; \ + echo "$$OBJ: $$SRC $$HEADERS" >> $$MK; \ + echo " @mkdir -p $$(dirname $$OBJ)" >> $$MK; \ + echo " $(CC) $(CFLAGS) $(RELEASE_FLAGS) -I includes -c $$SRC -o $$OBJ" >> $$MK; \ + done; \ + echo "$$OUT: $$OBJS" >> $$MK; \ + echo " $(CC) $(CFLAGS) $(RELEASE_FLAGS) -o $$OUT $$OBJS" >> $$MK; \ + $(MAKE) -f $$MK "$$OUT" -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 +release: + @mkdir -p config output/obj_release + @DATE_STR=$$(date +_%y.%j.%H.%M%S); \ + echo "$$DATE_STR" > config/version; \ + echo "Project version updated to: $$DATE_STR" + @PROJ_NAME=$$(basename "$$(pwd)"); \ + VERS=$$(cat config/version 2>/dev/null); \ + OUT="output/$${PROJ_NAME}$${VERS}"; \ + MK="config/release.mk"; \ + echo ".POSIX:" > $$MK; \ + HEADERS=$$(find includes -type f -name '*.h' | tr '\n' ' '); \ + OBJS=""; \ + for SRC in $$(find source_code -type f -name '*.c'); do \ + OBJ="output/obj_release/$${SRC}.o"; \ + OBJS="$$OBJS $$OBJ"; \ + echo "$$OBJ: $$SRC $$HEADERS" >> $$MK; \ + echo " @mkdir -p $$(dirname $$OBJ)" >> $$MK; \ + echo " $(CC) $(CFLAGS) $(RELEASE_FLAGS) -I includes -c $$SRC -o $$OBJ" >> $$MK; \ + done; \ + echo "$$OUT: $$OBJS" >> $$MK; \ + echo " $(CC) $(CFLAGS) $(RELEASE_FLAGS) -o $$OUT $$OBJS" >> $$MK; \ + $(MAKE) -f $$MK "$$OUT"