这与我之前的问题有关: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为最终用户自动处理。事实上,大多数客户都按字母顺序排列。他们不知道或不关心他们彼此依赖的顺序。现在要告诉他们重新订购所有这些都很臭。对不起这篇文章的篇幅。我很感激任何答案!
答案 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)