Reputation: 7779
I need to delay inclusion of dependency fragments until second expansion time because the make file I'm editing is itself an include file and I will not have a list of source files to generate the includes until secondary expansion.
.SECONDEXPANSION:
AUTO_DEPENDENCY_FILES = $(patsubst %.cc, depend/%.d, $(CC_SRC_FILES))
# the following does the work because the include argument is not a rule
# prerequisite therefore no secondary expansion occurs
include $$(AUTO_DEPENDENCY_FILES)
depend:
-mkdir depend
all: autodepend
autodepend: depend autodepend_include
autodepend_include: $$(AUTO_DEPENDENCY_FILES)
@echo \"$^\"
$$(AUTO_DEPENDENCY_FILES): depend
depend/%.d: | %.cc
# generate .d files that do not exist
$(COMPILE.cc) -E $*.cc > /dev/null
%.o: %.cc
# update .d files that exist
$(COMPILE.cc) -o $@ $<
Note the COMPILE.cc
is a very long string that includes -MP -MMD -MFdepend/$*.d
flags for auto dependency generation.
Upvotes: 1
Views: 1669
Reputation: 81052
I don't know that there's a clean solution to this problem but with a bit of a hack you can get you what you want.
Given a main Makefile
of:
$(info main one)
include depend.mk
$(info main two)
CC_SRC_FILES := $(addsuffix .c,a b c d e f)
$(info main three)
and a depend.mk
of:
$(info depend one)
AUTO_DEPENDENCY_FILES = $(patsubst %.c,%.d,$(CC_SRC_FILES))
$(info AUTO_DEPENDENCY_FILES := $(AUTO_DEPENDENCY_FILES))
$(info MAKE_RESTARTS := $(MAKE_RESTARTS))
$(info CC_SRC_FILES := $(CC_SRC_FILES))
$(info depend two)
you get the following output when you run make
:
main one
depend one
AUTO_DEPENDENCY_FILES :=
MAKE_RESTARTS :=
CC_SRC_FILES :=
depend two
main two
main three
make: `all' is up to date.
Which isn't surprising given the order of assignment and inclusion of files, etc.
Here's where the horrible hack comes in.
When make encounters an include
directive that references a file that doesn't exist make sticks the file in a list of "missing include
files" and continues parsing the makefile.
When it gets to the end of the makefile(s) it then tries to treat each entry in that list as a potential goal target1 and attempts to make the file.
Once the makefiles have been built make restarts itself and tries again.
You can use this to capture the value of CC_SRC_FILES
in an built makefile that your makefile includes and have it be visible when you need it.
If we make depend.mk
look like this:
$(info depend one)
include hack.mk
AUTO_DEPENDENCY_FILES = $(patsubst %.c,%.d,$(CC_SRC_FILES))
$(info AUTO_DEPENDENCY_FILES := $(AUTO_DEPENDENCY_FILES))
$(info MAKE_RESTARTS := $(MAKE_RESTARTS))
$(info CC_SRC_FILES := $(CC_SRC_FILES))
$(info depend two)
hack.mk: $(if $(MAKE_RESTARTS),,force)
@echo creating hack.mk
@echo 'CC_SRC_FILES := $(CC_SRC_FILES)' > '$@'
force: ;
Then our output from make
becomes:
main one
depend one
depend.mk:3: hack.mk: No such file or directory
AUTO_DEPENDENCY_FILES :=
MAKE_RESTARTS :=
CC_SRC_FILES :=
depend two
main two
main three
creating hack.mk
main one
depend one
AUTO_DEPENDENCY_FILES := a.d b.d c.d d.d e.d f.d
MAKE_RESTARTS := 1
CC_SRC_FILES := a.c b.c c.c d.c e.c f.c
depend two
main two
main three
make: `all' is up to date.
Which gives us the value where we want it.
This isn't pretty but it does work.
Upvotes: 3