I'm working with a tool that generates C++ source files that I need to include in my C++ project compilation.
To extraordinarily simplify things, my one non-generated source file, main.cpp
, is as follows:
extern void bar();
int main(int, char**)
{
bar();
return 0;
}
And my Makefile
is below. The overall structure is what's already existing in our project, and I'm simply adding in the parts noted to generate the needed source file bar.cpp
and makefile bar.mk
, which adds bar.cpp
to the SRCS
variable so it (I wish) gets included in the compilation:
SRCS := $(CURDIR)/main.cpp
#################### Adding everything between here... #####
BAR_MK := bar.mk
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
include $(BAR_MK)
endif
#################### ...and here ###########################
OBJ_DIR := $(CURDIR)/obj
OBJS := $(patsubst %.cpp,%.o,$(subst $(CURDIR),$(OBJ_DIR),$(SRCS)))
a.out: $(OBJS)
@echo OBJS == $(OBJS)
@echo SRCS == $(SRCS)
$(CXX) $(OBJS)
#################### Adding everything between here... #####
GEN_DIR := $(CURDIR)/gen
# "Generate" my source file(s), add them to SRCS via an external makefile
$(BAR_MK): $(GEN_DIR)/bar.cpp
$(GEN_DIR)/bar.cpp:
mkdir -p $(dir $@)
echo "void bar () {}" > $@
echo SRCS += $@ > $(BAR_MK)
#################### ...and here ###########################
$(OBJ_DIR)/%.o: %.cpp
mkdir -p $(dir $@)
$(CXX) -c -o $@ $<
clean:
rm -rf $(OBJ_DIR)
rm -f a.out
rm -rf $(GEN_DIR)
rm -f $(BAR_MK)
The issue is, the compilation fails the first time I run make
due to "undefined reference to bar()
", but running make
immediately afterward succeeds. This is because upon the first run of make
, when it evaluates the a.out:
rule, it sees SRCS
as only containing main.cpp
, and so bar.cpp
doesn't get compiled. Then on the second (and subsequent) runs, SRCS
contains both main.cpp
and bar.cpp
, so bar.cpp
gets compiled that time.
This seems odd to me, because per the GNU Make manual on "How Makefiles Are Remade":
After all makefiles have been checked, if any have actually been changed, make starts with a clean slate and reads all the makefiles over again.
So after GNU Make processes include bar.mk
on my first make
invocation, sees that it's out of date and builds it, I'd expect that it would then start over from scratch with parsing the Makefile from the start, including bar.mk
and, in turn, having SRCS
contain both main.cpp
and bar.cpp
.
Is my expectation wrong? Or is there something wrong with my (additions to the) Makefile? I'm using GNU Make 4.1 on Linux.