Reputation: 3761
I have the below Makefile.
#
# General Makefile
#
BUILD := build
CXXFLAG := -std=c++20
CXX := g++
SRC := 16.15.cc
OBJ := $(SRC:%.cc=$(BUILD)/%.o)
DEP := $(OBJ:.o=.d)
MKDIR_P := mkdir -p
all: directories $(OBJ)
directories:
$(MKDIR_P) $(BUILD)
$(BUILD)/%.o: %.cc # --> block 1
echo 1
-$(CXX) -c $(CXXFLAG) $< -o $@
$(BUILD)/16.15.o: 16.15.cc include/16.15.h # --> block 2
.PHONY: directories all
Observation:
When i modify and save include/16.15.h, Block 1 gets executed.
$ make
mkdir -p build
echo 1
1
g++ -c -std=c++20 16.15.cc -o build/16.15.o
How? How does this change on a header file trigger block 1?
Upvotes: 1
Views: 68
Reputation: 181179
How does a header file change trigger a target?
Given that this rule ...
$(BUILD)/16.15.o: 16.15.cc include/16.15.h
... provides no recipe for building the target, it is a prerequisite-only rule. make
takes into account the prerequisites named in all prerequisite-only rules for each target it needs to build, in addition to the prerequisites given in the rule that provides the recipe for that target. Therefore, yes, if you modify include/16.15.h
such that it is newer than $(BUILD)/16.15.o
then make
will consider the latter out of date and in need of rebuilding. That a different rule will provide the recipe for such a rebuilding is irrelevant.
The question suggests that you may have a flawed mental model of make
's operation. Programmers who are less familiar with make
sometimes think of make
rules as if they were functions in an imperative language, maybe with the prerequisites being arguments. I think the popularity of that arises from its familiarity, but it can be misleading. It leads to wrong ideas, such as assuming that make
will consider only the prerequisites given in the rule providing the recipe for the target.
make
is not a script interpreter, and makefiles are not scripts. Rather, make
is an expert system. The makefile language is by and large a declarative one. In particular, make
rules are data, not functions. make
operates by taking all the data provided to it
and using that to devise and execute a strategy for bringing one or more goal targets up to date with respect to their prerequisites. That often involves using a shell to execute recipes provided to make
as data, but that should not be confused with rules being executable, even the ones that provide recipes that are chosen for execution.
Upvotes: 1
Reputation: 96791
You can have more than one target: prereq1 prereq2 prereq3
for any given target. All the prerequisites for a target are combined. The only restriction is that you can have at most one recipe (a set of commands) per target.
And apparently this works in your case too. You have a pattern rule, and can add extra prerequisites to a specific instantiation of it.
Upvotes: 1