# - - - - - - # # # # COLORS # # # # - - - - - - # GRAY = "\e[0;30m" RED = "\e[0;31m" GREEN = "\e[0;32m" YELLOW = "\e[0;33m" BLUE = "\e[0;34m" PURPLE = "\e[0;35m" CYAN = "\e[0;36m" WHITE = "\e[0;37m" B_GRAY = "\e[1;30m" B_RED = "\e[1;31m" B_GREEN = "\e[1;32m" B_YELLOW = "\e[1;33m" B_BLUE = "\e[1;34m" B_PURPLE = "\e[1;35m" B_CYAN = "\e[1;36m" B_WHITE = "\e[1;37m" RESET = "\e[0m" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # . name = value \ . += append to a variable # # VARIABLES . value . != set result of command # # . name is case sensitive . ?= set if not already set # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # FILES : #NAME -> defined in subfolder makefiles #SRCS -> defined in subfolder makefiles #CLONES -> defined in subfolder makefiles #CREATE_CLONE -> defined in subfolder makefiles #RM_MORE -> might be defined in subfolder makefiles LIBS = D_SRCS = . D_HEADERS = . HEADERS = # COMPILATION CONFIG : CC = clang EXT = c CFLAGS = -Wall -Wextra -Werror $(INCLUDES) CFLAGS += -g3 # AUTOMATICALLY CREATED : D_OBJS = builds OBJS = $(SRCS:%.$(EXT)=$(D_OBJS)/%.o) EXPLODED = $(SRCS:%.$(EXT)=%_exploded.$(EXT)) VPATH = $(D_SRCS) F_INCLUDES = $(HEADERS:%=$(D_HEADERS)/%) INCLUDES = -I$(D_HEADERS) ifeq "$(D_OBJS)" "." RM_OBJS = rm -f $(OBJS) else RM_OBJS = rm -rf $(D_OBJS) endif # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # . target: prerequisites . $@ : target # # RULES . recipe . $< : 1st prerequisite # # . recipe . $^ : all prerequisites # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # all: concat $(NAME) # sed : # -z : instead of classic "-e", looks for lines that ends with \0 instead of \n, usefull when lines can contain \n # 's/\\\n\t*//g' : subsitutes backslash '\\' followed by newline '\n' followed by any number of tabs '\t*', and replace them by nothing # empty recipe : # - to avoid makefile complaining when $(EXPLODED) does not exist # - https://www.gnu.org/software/make/manual/html_node/Empty-Recipes.html concat: $(EXPLODED) @echo $(CYAN)"create the condensed version of the quine :"$(RESET) - test -f $< && sed -z 's/\\\n\t*//g' $< > $(SRCS) $(EXPLODED): ; # %.$(EXT) | $(D_OBJS) -> pipe is for order-only prerequisites : # - for each file "%.$(EXT)" : # - if it has been modified since last time # - execute rules on corresponding target file "$(D_OBJS)/%.o" # - and directory "$(D_OBJS)" is order-only prerequisite : # - it must exist before executing rule # - but last time modification is not checked # - it avoids recompiling each time because the build folder was # modified by creation of other objects files $(D_OBJS)/%.o: %.$(EXT) | $(D_OBJS) @echo $(CYAN)"compilation (objects.o) :"$(RESET) $(CC) $(CFLAGS) -c $< -o $@ $(D_OBJS): mkdir $@ $(OBJS): $(F_INCLUDES) $(NAME): $(OBJS) @echo $(CYAN)"linkage (link objects.o) :"$(RESET) $(CC) $(OBJS) -o $@ $(LIBS) leaks: $(NAME) valgrind --leak-check=full --show-leak-kinds=all $(CREATE_CLONE) run: $(CREATE_CLONE) diff: $(NAME) @echo $(CYAN)"compare source with output :"$(RESET) - diff --color $(CLONE) $(SRCS); \ if [ $$? -eq 0 ]; then echo $(GREEN)"Files $(SRCS) and $(CLONES) are identical"$(RESET); else echo $(RED)":Files $(SRCS) and $(CLONES) differ"$(RESET); fi clean: $(RM_OBJS) fclean: clean rm -f $(NAME) rm -f $(CLONES) $(RM_MORE) re: fclean all .PHONY : all clean fclean re concat run diff leaks