Reputation: 811
I am trying to work with a hierarchy of Makefiles. Using GNU Make.
Lets say, I have a directory SRC which has 3 sub directories: A, B and C.
Every directory has it's own Makefile (Make.SRC, Make.A, Make.B and Make.C).
Both Make.B and Make.C need to use Make.A for some shared files.
In the Make.SRC file of SRC directory, I have the following lines:
include A/Make.A
include B/Make.B
include C/Make.C
But since I have multiple include of Make.A (a total of 3 times), it's giving me warnings for overriding commands for the targets inside Make.A .
What should be the way to work this kind of hierarchical Makefiles? Is there any technique like C header files to avoid repeated include?
Upvotes: 0
Views: 202
Reputation: 80931
If you really need to be able to use the individual makefiles on their own make -f Make.B <targets>
or make -f Make.C <targets>
you could add a check for whether Make.A
is in $MAKEFILE_LIST
already or not and include it only if it isn't.
define condinc
$(eval # Space needed after eval for this to function correctly.
ifeq (,$(filter %$1,$(MAKEFILE_LIST)))
include $1
endif
)
endef
In Make.SRC
:
$(call condinc,A/Make.A)
In Make.B
or Make.C
$(call condinc,../A/Make.A)
Edit: Hm... no that's not going to work quite right. It'll need some tweaking to separate the path from the makefile name for the filter and include parts. Working on it.
If none of the basenames of the makefiles are going to match then using ifeq (,$(filter %$(notdir $1),$(MAKEFILE_LIST)))
in that define mostly works. If they do then more changes to that function are necessary. But what exactly depends on what the sub-makefile include lines look like I think.
$ more {Makefile,{A,B,C}/Make.*} | cat
::::::::::::::
Makefile
::::::::::::::
define condinc
$(eval
ifeq (,$(filter %$(notdir $1),$(MAKEFILE_LIST)))
include $1
endif
)
endef
$(info one)
$(call condinc,A/Make.A)
$(info two)
$(call condinc,B/Make.B)
$(info three)
$(call condinc,C/Make.C)
$(info four)
::::::::::::::
A/Make.A
::::::::::::::
$(info Make.A included)
$(info MAKEFILE_LIST is $(MAKEFILE_LIST))
::::::::::::::
B/Make.B
::::::::::::::
$(info Make.B included)
$(info MAKEFILE_LIST is $(MAKEFILE_LIST))
$(call condinc,$(CURDIR)/A/Make.A)
::::::::::::::
C/Make.C
::::::::::::::
$(info Make.C included)
$(info MAKEFILE_LIST is $(MAKEFILE_LIST))
Running with the above gets you:
$ make
one
Make.A included
MAKEFILE_LIST is Makefile A/Make.A
two
Make.B included
MAKEFILE_LIST is Makefile A/Make.A B/Make.B
three
Make.C included
MAKEFILE_LIST is Makefile A/Make.A B/Make.B C/Make.C
four
make: *** No targets. Stop.
Upvotes: 1