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 \


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?


source to share

4 answers

Another solution would be to use vpath

. Sample code:

OBJ_PATH := build

SRCS := \
    src/foodir/foo.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:

$(OBJ_PATH)/%.o: $$(filter $$(PERCENT)/$$(subst .o,.c,$$(notdir $$@)), $(SRCS))
    $(CC) $(FLAGS) $< -o $@




Something like this will work as well.

SRCS = \
  ../../src/file1.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.
    $(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.



All Articles