From 0924650090c78ed07aa68af127c36c3bbec9a35b Mon Sep 17 00:00:00 2001 From: xavi Date: Tue, 23 Dec 2025 21:28:56 -0800 Subject: [PATCH] Added Makefile Logic to work with Submodules These changes allow for projects that were created and built using the same Makefile to be placed under the submodules directory. This Makefile will recursively build the submodules and link to the top project. The submodules will be built as a static library using ar rcs. --- c_projects/x_tfw4c/Makefile | 71 ++++++++++++++---- c_projects/x_tfw4c/src/x_tfw4c.c | 125 ------------------------------- 2 files changed, 55 insertions(+), 141 deletions(-) delete mode 100644 c_projects/x_tfw4c/src/x_tfw4c.c diff --git a/c_projects/x_tfw4c/Makefile b/c_projects/x_tfw4c/Makefile index b94a806..b2927be 100644 --- a/c_projects/x_tfw4c/Makefile +++ b/c_projects/x_tfw4c/Makefile @@ -11,8 +11,6 @@ # Change date file was created to today # run make dirs to create project hierarchy # Place headers in include and source files in src -# Delete this text - .POSIX: # DIRECTORIES @@ -20,48 +18,89 @@ SRC_DIR := src INCLUDE_DIR := include OBJ_DIR := obj TESTS_DIR := tests +SUBMODULES_DIR := submodules +# Final Binary Name +PROJECT_NAME := placeholder +PROJECT_OBJ := $(OBJ_DIR)/$(PROJECT_NAME).o + +# SUBMODULE VARS FOR GENERATING STATIC LIBS +SUBMODULES := $(wildcard $(SUBMODULES_DIR)/*) +SUBBARE := $(SUBMODULES:$(SUBMODULES_DIR)/%=%) +SUBMODULE_SLIB := $(foreach m,$(SUBBARE),$(SUBMODULES_DIR)/$(m)/$(m).a) + + +STATIC_LIBS = $(shell find ./ -name "*.a") # C compiler settings CC := gcc -CFLAGS := -ggdb -I$(INCLUDE_DIR) -Wall -Wextra -MMD -MP +INCLUDE_LIST := $(foreach m,$(SUBMODULES),$(m)/$(INCLUDE_DIR)) $(INCLUDE_DIR) +INCLUDES := $(addprefix -I,$(INCLUDE_LIST)) +CFLAGS := -ggdb $(INCLUDES) -Wall -Wextra -MMD -MP DFLAGS := +# Main Executable Filename +MAIN := main.c + # Files -SRC := $(wildcard $(SRC_DIR)/*.c) +SRC := $(filter-out $(SRC_DIR)/$(MAIN), $(wildcard $(SRC_DIR)/*.c)) OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) TESTS := $(wildcard $(TESTS_DIR)/*.c) # Get Dependencies from gcc using -MMD and -MP DEPENDENCIES := $(OBJ:%.o=%.d) -# Final Binary Name -PROJECT_NAME := placeholder - - all: $(PROJECT_NAME) +# CREATE STATIC LIBRARY OF MODULE +$(PROJECT_NAME).a: $(PROJECT_OBJ) check_submods + ar rcs $(@) $(<) -$(TESTS:$(TESTS_DIR)/%.c=%): $(OBJ) - $(CC) $(CFLAGS) $(DFLAGS) -o $(@) $(^) +# CREATE TEST EXECUTABLES +$(TESTS:$(TESTS_DIR)/%.c=%): %: $(OBJ_DIR)/%.o $(OBJ) check_submods + $(CC) $(CFLAGS) $(DFLAGS) -o $(@) $(<) $(OBJ) $(STATIC_LIBS) +# CREATE TEST OBJS +$(OBJ_DIR)/%.o: $(TESTS_DIR)/%.c $(OBJ) + $(CC) $(CFLAGS) $(DFLAGS) -c -o $(@) $(^) -$(PROJECT_NAME): $(OBJ) - $(CC) $(CFLAGS) $(DFLAGS) -o $(@) $(^) +# CREATE MAIN OBJ +$(PROJECT_NAME): $(MAIN:%.c=$(OBJ_DIR)/%.o) $(OBJ) check_submods + $(CC) $(CFLAGS) $(DFLAGS) -o $(@) $(<) $(OBJ) $(STATIC_LIBS) +# CREATE OBJS $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(CC) $(CFLAGS) $(DFLAGS) -c -o $(@) $(<) +# RECURSE THROUGH SUBMODULES AND RUN MAKE *.a +$(SUBMODULE_SLIB): + $(MAKE) -C $(dir $(@)) $(notdir $(@)) + +check_submods: $(SUBMODULE_SLIB) + + +# RECURSE AND CLEAN ALL FILES clean: - rm -f $(PROJECT_NAME) $(OBJ_DIR)/* $(TESTS:$(TESTS_DIR)/%.c=%) + @for sm in $(SUBMODULES) ; do \ + $(MAKE) -C $$sm clean ; \ + done + rm -f $(PROJECT_NAME) $(OBJ_DIR)/* $(TESTS:$(TESTS_DIR)/%.c=%) ./*.a -include $(DEPENDENCIES) -.PHONY: clean all +help: + @echo "SUBMODULES: $(SUBMODULES)" + @echo "SUBMODULE_SLIB: $(SUBMODULE_SLIB)" + @echo "STATIC_LIBS: $(STATIC_LIBS)" + +.PHONY: clean all check_submods help # Create Project Hierarchy -dirs: $(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) +dirs: $(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR) $(SRC_DIR)/$(MAIN) -$(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR): +$(SRC_DIR) $(OBJ_DIR) $(TESTS_DIR) $(INCLUDE_DIR) $(SUBMODULES_DIR): mkdir -p $(@) + +$(SRC_DIR)/$(MAIN): + touch $(SRC_DIR)/$(MAIN) diff --git a/c_projects/x_tfw4c/src/x_tfw4c.c b/c_projects/x_tfw4c/src/x_tfw4c.c deleted file mode 100644 index 179f5f3..0000000 --- a/c_projects/x_tfw4c/src/x_tfw4c.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include -#include - -// printf Formating -#define X_RED "\x1B[31m" -#define X_GREEN "\x1B[32m" -#define X_YELLOW "\x1B[33m" -#define X_RST "\x1B[0m" - -// TEST FRAMEWORK STRUCT -typedef struct testnode{ - char* name; - int (*op)(void); - struct testnode* next; -}testnode; - -// LL nodes -static testnode* head = NULL; -static testnode* tail = NULL; -static testnode* ptr = NULL; - -// TEST FRAMEWORK MACRO -// create a new node and pass in the name of the test. Then make a new function -// that adds the test to the LL. __attribute__((constructor)) has the function -// run before main -#define TEST(UNIT)\ - static int UNIT(void);\ - static testnode UNIT##node = {#UNIT, UNIT, NULL};\ - __attribute__((constructor)) \ - static void add##UNIT(void){ \ - if (head == NULL){\ - head = &UNIT##node;\ - tail = head;\ - return; \ - }\ - ptr = tail;\ - tail = &UNIT##node;\ - ptr->next = tail;\ - }\ - static int UNIT(void) - -// ASSERT MACRO -#define ASSERT() - -// DEFINE TESTS -TEST(fail){ - return -1; -} - -TEST(success){ - return 0; -} - -TEST(segfault){ - int* x = NULL; - int y = *x; -} -// END OF TEST DEFINITIONS - -int main(){ - int total_tests = 0; - int errors = 0; - - int status; - - ptr = head; - while (ptr != NULL){ - total_tests++; - - pid_t cpid = fork(); - if (cpid < 0){ - perror("fork"); - exit(EXIT_FAILURE); - } - - if (cpid == 0){ - int rc = ptr->op(); - _exit(rc); - }else{ - - if (waitpid(cpid, &status, 0) < 0){ - perror("waitpid"); - exit(EXIT_FAILURE); - } - } - - if (WIFEXITED(status)){ - int rc = WEXITSTATUS(status); - if (rc == 0) { - printf("%s[PASS]%s ", X_GREEN, X_RST); - printf("%s", ptr->name); - } - else{ - printf("%s[FAIL]%s ", X_RED, X_RST); - printf("%s ", ptr->name); - printf("- Exit Code %s(%d)%s", X_YELLOW, rc, X_RST); - errors++; - } - }else if (WIFSIGNALED(status)){ - printf("%s[FAIL]%s ", X_RED, X_RST); - printf("%s ", ptr->name); - printf("- Termination Signal %s(%d)%s", X_YELLOW, WTERMSIG(status), X_RST); - errors++; - } - printf("\n"); - ptr = ptr->next; - } - - printf("Tests completed with %s%d PASS%s", X_GREEN, total_tests - errors, X_RST); - printf(" and %s%d FAIL%s\n", X_RED, errors, X_RST); - - if (errors > 0){ - return 1; - } - return 0; -} - - -// INSERT HEADERS FOR FUNCS - -// DEFINE TESTS - -// END OF TEST DEFINITIONS