Rakib
Rakib

Reputation: 811

Including same Makefile from other makefiles

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

Answers (1)

Etan Reisner
Etan Reisner

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

Related Questions