我希望我的makefile更加独立于订单!

时间:2011-01-26 22:43:36

标签: makefile

这与我之前的问题有关:Why does .PHONY not work in this situation?

我有一个makefile系统,我写这篇系统是为了让那些不熟悉make的开发人员轻松完成他们的任务。简而言之,对于所有项目都有一个通用部分,以及一组特定于给定项目的makefile。具体项目包括通用项目。由于某种原因,它在make 3.80上运行得很好,但是当我尝试使用3.81时,我遇到了一些问题。这迫使我做出上述帖子中提到的更改。现在我有一些新问题,所以我决定再发一个帖子。就像那篇文章一样,我制作了一个更小,更简单的makefile文件来显示问题。不幸的是,“简单”案例包含6个文件。对于那个很抱歉。首先,我将从“项目特定”开始(这些都很简单):

生成文件:

TARGETS:=\
    Lib1.mk \
    Lib2.mk \
    my_prog.mk \

include generic/top.mk

Lib1.mk:

BINARY:=Lib1
TYPE:=LIB
LOCATION:=a/location

include generic/rules.mk

Lib2.mk:

BINARY:=Lib2
TYPE:=LIB
LOCATION:=another/location
LIBS:=Lib1

include generic/rules.mk

my_prog.mk:

BINARY:=my_prog
TYPE:=EXE
LOCATION:=some/location
LIBS:=Lib1 Lib2

include generic/rules.mk

快速说明:Makefile只列出所有目标的名称。目标是可执行文件或库。 BINARY是库或可执行文件的名称(扩展名由通用部分添加)。 TYPE是EXE或LIB。 LOCATION是二进制应该去的地方。 LIBS是这个二进制文件所依赖的库。真正的那些处理为用户创建所有-L,rpath等东西(以及它们对于visual studio的等价物)。现在是通用的(这些是真正的工作):

通用/ top.mk:

ALL_BINS:=

.PHONY: all
all:

include $(TARGETS)

all: $(ALL_BINS)

%.so %.exe:
    mkdir -p $(dir $@)
    touch $@

clean:
    rm -rf out

最后..

通用/ rules.mk:

ifeq (EXE,$(TYPE))
$(BINARY).FULL_FILE_NAME:=out/$(LOCATION)/$(BINARY).exe
else
$(BINARY).FULL_FILE_NAME:=out/$(LOCATION)/lib$(BINARY).so
endif

$(BINARY).DEP_LIBS:=$(foreach a,$(LIBS),$($(a).FULL_FILE_NAME))
ALL_BINS+=$(BINARY)

$(BINARY): $($(BINARY).FULL_FILE_NAME)
$($(BINARY).FULL_FILE_NAME): $($(BINARY).DEP_LIBS)

BINARY:=
LOCATION:=
LIBS:=

好的,在这种状态下,事情很好。 make正确处理所有依赖项,如果我触摸任何文件,它将正确地“构建”它所拥有的那些,仅此而已。从 makefile 获取m_prog.mk行并将其移动到列表顶部时会出现问题,如下所示:

TARGETS:=\
    my_prog.mk \
    Lib1.mk \
    Lib2.mk \

问题似乎是,当它通过 rules.mk 进行 my_prog.mk 时,它还不知道Lib1和Lib2的完整库路径是什么(它们是空的字符串)。所以最后,它认为my_prog依赖于什么,它试图不按顺序构建它。在这个例子中,你只是看到它首先“触摸”my_prog然后是另一个2.当然,当我在那里有真正的编译器和链接器命令时,它会抛出一个错误。

当我简单地将.PHONY目标相互依赖(因此my_prog依赖于Lib1和Lib2)时,生活变得轻松和谐。现在我不能这样做,生活变得更加困难。

你可能会说,“哎呀把它按正确的顺序排好!”。到目前为止,这已经通过make为最终用户自动处理。事实上,大多数客户都按字母顺序排列。他们不知道或不关心他们彼此依赖的顺序。现在要告诉他们重新订购所有这些都很臭。对不起这篇文章的篇幅。我很感激任何答案!

2 个答案:

答案 0 :(得分:1)

如果使用:=赋值运算符设置变量,则会立即评估赋值。

如果使用just =作为赋值运算符设置变量,则会尽可能晚地(在实际使用时)对它们进行懒惰评估。

请参阅http://www.gnu.org/software/automake/manual/make/Flavors.html

答案 1 :(得分:0)

有几种方法可以做你想要的。最干净的可能是使用vpath。只需修改rules.mk

即可
$(BINARY).DEP_LIBS:=$(foreach a,$(LIBS),$(a).so)
ALL_BINS+=$(BINARY)

vpath %.so out/$(LOCATION)