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.
This commit is contained in:
parent
3677b50fe1
commit
0924650090
@ -11,8 +11,6 @@
|
|||||||
# Change date file was created to today
|
# Change date file was created to today
|
||||||
# run make dirs to create project hierarchy
|
# run make dirs to create project hierarchy
|
||||||
# Place headers in include and source files in src
|
# Place headers in include and source files in src
|
||||||
# Delete this text
|
|
||||||
|
|
||||||
.POSIX:
|
.POSIX:
|
||||||
|
|
||||||
# DIRECTORIES
|
# DIRECTORIES
|
||||||
@ -20,48 +18,89 @@ SRC_DIR := src
|
|||||||
INCLUDE_DIR := include
|
INCLUDE_DIR := include
|
||||||
OBJ_DIR := obj
|
OBJ_DIR := obj
|
||||||
TESTS_DIR := tests
|
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
|
# C compiler settings
|
||||||
CC := gcc
|
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 :=
|
DFLAGS :=
|
||||||
|
|
||||||
|
# Main Executable Filename
|
||||||
|
MAIN := main.c
|
||||||
|
|
||||||
# Files
|
# Files
|
||||||
SRC := $(wildcard $(SRC_DIR)/*.c)
|
SRC := $(filter-out $(SRC_DIR)/$(MAIN), $(wildcard $(SRC_DIR)/*.c))
|
||||||
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
|
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
|
||||||
TESTS := $(wildcard $(TESTS_DIR)/*.c)
|
TESTS := $(wildcard $(TESTS_DIR)/*.c)
|
||||||
|
|
||||||
# Get Dependencies from gcc using -MMD and -MP
|
# Get Dependencies from gcc using -MMD and -MP
|
||||||
DEPENDENCIES := $(OBJ:%.o=%.d)
|
DEPENDENCIES := $(OBJ:%.o=%.d)
|
||||||
|
|
||||||
# Final Binary Name
|
|
||||||
PROJECT_NAME := placeholder
|
|
||||||
|
|
||||||
|
|
||||||
all: $(PROJECT_NAME)
|
all: $(PROJECT_NAME)
|
||||||
|
|
||||||
|
# CREATE STATIC LIBRARY OF MODULE
|
||||||
|
$(PROJECT_NAME).a: $(PROJECT_OBJ) check_submods
|
||||||
|
ar rcs $(@) $(<)
|
||||||
|
|
||||||
$(TESTS:$(TESTS_DIR)/%.c=%): $(OBJ)
|
# CREATE TEST EXECUTABLES
|
||||||
$(CC) $(CFLAGS) $(DFLAGS) -o $(@) $(^)
|
$(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)
|
# CREATE MAIN OBJ
|
||||||
$(CC) $(CFLAGS) $(DFLAGS) -o $(@) $(^)
|
$(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
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||||
$(CC) $(CFLAGS) $(DFLAGS) -c -o $(@) $(<)
|
$(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:
|
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)
|
-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
|
# 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 $(@)
|
mkdir -p $(@)
|
||||||
|
|
||||||
|
$(SRC_DIR)/$(MAIN):
|
||||||
|
touch $(SRC_DIR)/$(MAIN)
|
||||||
|
|||||||
@ -1,125 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
// 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
|
|
||||||
Loading…
Reference in New Issue
Block a user