Makefile does not allow incremental build
I have a makefile from a sample project and it unfortunately forces a re-build when any one file in the project changes. I don't have much experience with makefiles, so I'm not sure how to fix this problem.
The makefile defines the files to compile as one variable SRCS
, as shown below. Of course, there are about 40 files in this list, in quite different directories.
SRCS = \
../../src/file1.c \
../../src/file2.c
It then defines the build rules for each file .o
generated from each file .c
.
$(OBJ_PATH)/%.o: $(SRCS)
$(CC) $(FLAGS) $(filter %/$(subst .o,.c,$(notdir $@)), $(SRCS)) -o $@
According to running with the parameter, -d
all object files must be compiled again when one file .c
changes as it $(SRCS)
is defined as a dependency above.
How can I change this, so if one file changes, only file 1 .o
needs to be compiled again?
Another solution would be to use vpath
. Sample code:
OBJ_PATH := build
SRCS := \
src/foodir/foo.c \
src/bardir/bar.c
OBJS := $(addprefix $(OBJ_PATH)/,$(notdir $(SRCS:%.c=%.o)))
vpath %.c $(dir $(SRCS))
all: $(OBJS)
$(OBJ_PATH)/%.o: %.c
$(CC) $(FLAGS) $< -o $@
Your recipe was written by someone knowledgeable about makefiles; this is almost correct. One adjustment is to move the statement $(filter)
to the prerequisite line. In this case, this is exactly what it should be.
Once it appears, you need to make a few additional settings, which you can read about in the manual. So, like this:
PERCENT := %
.SECONDEXPANSION:
$(OBJ_PATH)/%.o: $$(filter $$(PERCENT)/$$(subst .o,.c,$$(notdir $$@)), $(SRCS))
$(CC) $(FLAGS) $< -o $@
Something like this will work as well.
SRCS = \
../../src/file1.c \
../../src/file2.c
# Set prerequisites for each output .o file from the matching .c file
$(foreach src,$(SRCS),$(eval $(OBJ_PATH)/$(notdir $(src:.c=.o)): $(src)))
# Create pattern rule with no additional prerequisites.
$(OBJ_PATH)/%.o:
$(CC) $(FLAGS) $< -o $@
So it occurred to me that in some ways an even more minimal change would be:
$(OBJ_PATH)/%.o: $(SRCS)
file='$(filter %/$(subst .o,.c,$(notdir $@)), $?)'; [ "$$file" ] && \
$(CC) $(FLAGS) "$$file" -o $@
Typically, in the Makefile, you don't put specific .c files as dependencies.
Typically, you specify .o files as dependencies of the main executable.
Make has internal rules for how to create a .o file from a .c file, you can override them with your own custom rule, or often just change a few config.
The complete make tutorial is more than what I want to type in this box, but they can be found with a quick web search.