2011-01-26 64 views
1

这涉及到我刚才的问题:Why does .PHONY not work in this situation?我想让我的makefile更独立!

我有我写的很容易让开发商谁不熟悉的牌子,做他们的任务生成文件系统。简而言之,所有项目都有一个通用部分,以及一组特定于特定项目的makefile。具体项目包括通用项目。由于某种原因,它在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 [email protected]) 
    touch [email protected] 

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:= 

好了,在这种状态下,东西做工精细。正确处理所有的依赖关系,如果我触及任何文件,它将正确地“构建”它所需的那些文件,除此之外别无其他。

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

这个问题似乎是,虽然它正在经历rules.mk:当你从makefile文件采取m_prog.mk行并将其移动到列表的顶端,像这样的问题发生my_prog.mk它还不知道什么LIB1和LIB2完整库路径(它们是空字符串)。所以最后,它认为my_prog是不依赖于任何东西的,它会尝试按顺序构建它。在这个例子中,你只看到它的“触摸” my_prog第一,然后其他。当然,当我有真正的编译器和连接器命令在那里,它抛出一个错误。

当我简单地让.PHONY目标互相依赖(所以my_prog依赖于Lib1和Lib2)时,生活变得简单和谐。现在我不能那样做,生活变得更加困难。

你可以说,“heck把它放在正确的顺序!”。到目前为止,这已经通过最终用户自动处理。事实上,大多数客户一直在按字母顺序排列东西。他们不知道或不在乎彼此依赖的顺序。如果现在要告诉他们重新排列所有这些,那就太臭了。对不起,这篇文章的长度。我会很感激任何答案!

回答

1

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

如果您使用=作为赋值运算符设置变量,它们将尽可能迟(在实际使用时)延迟评估。

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

+0

这里的问题是,我重用变量BINARY,类型,位置,和在每个目标的makefile LIBS(我再重置他们在rules.mk年底清空包括前下一个客户.mk文件)。因此,如果我要将其改为=而不是:=,那么我认为它会使用该变量的最后一个值集合?如果是这样,那不是理想的结果。事实上,我在上面的例子中试过了,我得到了循环依赖。 – user545226 2011-01-27 15:06:16

+0

我不习惯这种使用make的方法,其中每个makefile基本上都是一个每次包含它时都会扩展的宏,并且包含多次,但它看起来像:makefile设置目标并包含top.mk,其中包括所有提到的在目标中,每个目标设置BINARY/LOCATION/LIBS并包含定义了很多内容的rules.mk。然后在最后定义“全部”目标。无论如何。你确实需要BINARY,TYPE,LOCATION,LIBS立即评估,所以:=对他们有好处。但请注意,ALL_BINS是使用+ =构建的,已使用延迟评估。 – metamatt 2011-01-28 02:03:09

0

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

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

vpath %.so out/$(LOCATION)