我正在尝试使用makefile的层次结构。使用GNU制造。
比如说,我有一个目录SRC,它有3个子目录:a、B和C。
每个目录都有自己的Makefile(Make.SRC、Make.A、Make.B和Make.C)。
Make.B和Make.C都需要对一些共享文件使用Make.A。
在SRC目录的Make.SRC文件中,我有以下几行:

include A/Make.A
include B/Make.B
include C/Make.C

但由于我有Make.A的多个include(总共3次),它会警告我重写Make.A中目标的命令。
如何处理这种层次结构的makefile?
有没有像C头文件这样的技术可以避免重复的include?

最佳答案

如果您真的需要能够单独使用各个makefilemake -f Make.B <targets>make -f Make.C <targets>,您可以添加一个检查Make.A是否已经在$MAKEFILE_LIST中,并且仅当它不在Make.SRC中时才包括它。

define condinc
    $(eval # Space needed after eval for this to function correctly.
    ifeq (,$(filter %$1,$(MAKEFILE_LIST)))
        include $1
    endif
    )
endef

Make.B中:
$(call condinc,A/Make.A)

Make.Cifeq (,$(filter %$(notdir $1),$(MAKEFILE_LIST)))
$(call condinc,../A/Make.A)

编辑:嗯。。。不,那不太管用。它需要进行一些调整,以将过滤器的路径与makefile名称分开,并包含部分。正在努力。
如果生成文件的基名都不匹配,那么在该定义中使用基本上是可行的。如果他们这样做了,那么需要对该函数进行更多的更改。但具体取决于子makefile包含的行的外观。
$ 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))

用上面的方法跑步可以让你:
$ 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.

10-04 14:29
查看更多