Some paraphrased bits from my current project's makefile that may help you out with good old fashioned GNU make:
SOURCEDIR := dir1 dir2/subdir1 dir3 dir4 dir5/subdir1 dir6/subdir1
SOURCES := $(foreach srcdir,$(SOURCEDIR),$(wildcard $(srcdir)/*.c))
OBJECTS := $(patsubst %.c,build/%.o,$(SOURCES))
OBJDIRS := $(addprefix build/,$(SOURCEDIR))
MAKEDEPS := $(patsubst %.c,build/%.d,$(SOURCES))
all: example
$(OBJDIRS):
-mkdir -p $@
build: $(OBJDIRS)
build/%.o : %.c | build
cc -MMD -c -o $@ $<
example: $(OBJECTS)
cc -o $@ $(OBJECTS)
-include $(MAKEDEPS)
In essence, it builds all of the source files found in the designated directories into object files located in subdirectories of the build
directory in a hierarchy that parallels their source directory layout (important if multiple source files have the same name) and then links the results into an executable example
.
As a bonus, dynamic dependency generation and inclusion via the MAKEDEPS
variable and clang's -MMD
flag.