Reputation: 203
I have the following directory structure.
Project/
├── bin/
├── src/
│ ├── main.c
│ ├── util/
│ ├── util.c
│ ├── util.h
├── obj/
├── .depend/
All my source code are in the src folder. In the src root is my main.c file; which includes other files that are on the same level that he (or within a same level folder). I have a Makefile below that works well for all files in the same level of main.c but does not work on files in a subfolder within src
How change my Makefile to allow subfolder within the src folder?
CC := gcc
CFLAGS := -Wall -Wextra
BINDIR := bin
OBJDIR := obj
SRCDIR := src
DEPDIR := .depend
SOURCES := $(wildcard $(SRCDIR)/*.c)
OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SRCDIR)/%.c, $(DEPDIR)/%.d, $(SOURCES))
$(BINDIR)/app: $(OBJECTS) | $(BINDIR)
@$(CC) -o $@ $^
-include $(DEPENDS)
$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
@$(CC) $(CFLAGS) -c -o $@ $<
$(DEPDIR)/%.d: $(SRCDIR)/%.c | $(DEPDIR)
@$(CC) -MM -MG $< | sed 's!^\(.\+\).o:!$(DEPDIR)/\1.d $(OBJDIR)/\1.o:!' > $@
$(DEPDIR) $(BINDIR) $(OBJDIR):
@mkdir $@
clean:
@rm -rf $(BINDIR)/*
@rm -rf $(OBJDIR)/*
.PHONY: clean
EDIT: the .o
and .d
files do not need to respect the original design of the structure. And I'm using Windows (MinGW)
Upvotes: 1
Views: 2363
Reputation: 1686
First, you'll have to change your SOURCES
to recursively find the sources. This can be done in pure make:
subdirs = $(filter-out $1,$(sort $(dir $(wildcard $1*/))))
rfind = $(wildcard $1$2) $(foreach d,$(call subdirs,$1),$(call rfind,$d,$2))
SOURCES := $(call rfind,$(SRCDIR)/,*.c)
Everything else will work, except for directory creation. First, change your prerequisites to use $(@D)
with secondary expansion:
.SECONDEXPANSION:
$(OBJDIR)/%.o: $(SRCDIR)/%.c | $$(@D)
...
$(DEPDIR)/%.d: $(SRCDIR)/%.c | $$(@D)
...
Then, change your directory creation rule to include all the directories:
$(BINDIR) $(patsubst %/,%,$(sort $(dir $(OBJECTS) $(DEPENDS)))):
@mkdir -p $@
Like the recursive find, it uses sort
to deduplicate the directories (otherwise make will warn) and strips the trailing slash (because $(@D)
won't have a trailing slash). Note that -p
is needed to avoid issues with order and with directories only containing other directories and no sources.
Upvotes: 3
Reputation: 2079
try to set your sources like this:
SOURCES := $(shell find $(SRCDIR) -type f -name "*.c")
if it does not work right a way, try to debug it by just running in your command line
find src -type f -name "*.c"
and see if it outputs the correct list of files and with correct relative path, adjust accordingly.
Note, that this approach works only in unix-like environment, if you are using MinGW from MSYS or Cygwin environment it should work.
Upvotes: 0