CC = musl-gcc DBGCFLAGS = -Wall -ansi -Wpedantic -static -g RELCFLAGS = -Wall -ansi -Wpedantic -static -O2 # Wildcard expansion does not happen in variable definitions, this fails: #SRCS = *.c # But can be forced: SRCS = $(filter-out main.c,$(wildcard *.c)) OUT_DIR = /tmp/build TMP_OBJS = $(SRCS:.c=.o) OBJS = $(addprefix $(OUT_DIR)/,$(TMP_OBJS)) # llist_double_ptr.o: target name (not file name) # $< name of the first prerequisite = llist_double_ptr.c # $@ current target name, reused as filename in CC invocation #llist_double_ptr.o: llist_double_ptr.c llist_double_ptr.h #$(CC) $(CFLAGS) -c $< -o $@ # $^ space-separated names of all prerequisites # default goal because defined first debug: main.c $(OBJS) | $(OUT_DIR)/deps.mk $(CC) $(DBGCFLAGS) $^ -o $(OUT_DIR)/$@ # Order-only dependency - create OUT_DIR before building $(OBJS): | $(OUT_DIR) # generalized target to build obj files for all .c + .h pairs # OBJS var fails here #mkdir $(OUT_DIR) > /dev/null 2>&1 $(OUT_DIR)/%.o: %.c %.h $(CC) $(DBGCFLAGS) -c $< -o $@ #include file into this Makefile, '-' = don't error if doesn't exit ifneq (clean, $(MAKECMDGOALS)) -include $(OUT_DIR)/deps.mk endif #generate list of .h dependencies for all .c files in SRCS #-MM is gcc facility specifically for GNU Make #this generates: #$ gcc -MM functions_ptrs.c llist_double_ptr.c #functions_ptrs.o: functions_ptrs.c functions_ptrs.h #llist_double_ptr.o: llist_double_ptr.c llist_double_ptr.h # ^ 2 targets that don't do anything, only define dependencies $(OUT_DIR)/deps.mk: $(SRCS) | $(OUT_DIR) $(CC) -MM $^ > $@ #[ -f $(OUT_DIR)/deps.mk ] || $(CC) -MM $^ > $@ $(OUT_DIR): mkdir $(OUT_DIR) indent: indent --linux-style *.c *.h rm *~ #Tell Make that "clean" is not a filename .PHONY : clean clean: -rm -rv $(OUT_DIR)