GNU使用$(eval ...)无法正常工作

时间:2012-03-07 17:21:24

标签: makefile gnu-make

这是makefile:

LIBDIRS       += ./libRelease
LIBDIRS       += ./SharedArcGIS/DepFilesLinux64/LibReleaseLinux64/Skia
LIBDIRS       += ./SharedArcGIS/DepFilesLinux64/LibReleaseLinux64/LibTess
LIBDIRS       += ./SharedArcGIS/DepFilesLinux64/LibReleaseLinux64/SQLite
STATICS       = $(wildcard $(LIBDIRS:=/*.a))
TARGETA       = libRuntimeCoreJava.a
TARGETD       = libRuntimeCoreJava.so
TARGETD1      = $(TARGETD).1
TARGETD2      = $(TARGETD).1.0
TARGETD3      = $(TARGETD).1.0.0
AR            = ar cqs
AR_EXTRACT    = ar -x
LINK          = g++
SYMLINK       = ln -f -s
LDFLAGS       = -shared -Wl,-soname,libRuntimeCoreJava.so
EXTRACT       =

all : $(TARGETD) $(TARGETA)

$(TARGETD) : clean
        mkdir -p ./obj ./libRelease
        $(foreach lib, $(STATICS), cp $(lib) ./obj;)
        $(eval EXTRACT := $(wildcard ./obj/*.a))
        echo $(EXTRACT)
        $(foreach lib, $(EXTRACT), $(AR_EXTRACT) $(lib);)
        $(foreach lib, $(EXTRACT), rm -f $(lib);)

        #$(CXX) $(LDFLAGS) $(OBJS)
        #$(SYMLINK) $(TARGETD) $(TARGETD1)
        #$(SYMLINK) $(TARGETD) $(TARGETD2)
        #$(SYMLINK) $(TARGETD) $(TARGETD3)

$(TARGETA) :
        $(eval OBJS:=$(wildcard ./obj/*.o))
        echo $(OBJS)
        #$(AR) $(TARGETA) $(OBJS)

clean :
        rm -rf ./ob

这是输出:

[matt6809@hogganz400 ArcGIS2]$ ls -l ./obj
total 23332
-rw-rw-r-- 1 matt6809 matt6809  191324 Mar  7 09:18 libCommon.a
-rw-rw-r-- 1 matt6809 matt6809 8427134 Mar  7 09:18 libGeometryXLib.a
-rw-rw-r-- 1 matt6809 matt6809   88580 Mar  7 09:18 libLibTess.a
-rw-rw-r-- 1 matt6809 matt6809 3401554 Mar  7 09:18 libMapping.a
-rw-rw-r-- 1 matt6809 matt6809 3558746 Mar  7 09:18 libpe_s.a
-rw-rw-r-- 1 matt6809 matt6809  412634 Mar  7 09:18 libpe++_s.a
-rw-rw-r-- 1 matt6809 matt6809  597808 Mar  7 09:18 libsg_s.a
-rw-rw-r-- 1 matt6809 matt6809 3523726 Mar  7 09:18 libSkia.a
-rw-rw-r-- 1 matt6809 matt6809  730064 Mar  7 09:18 libSQLite.a
-rw-rw-r-- 1 matt6809 matt6809  814234 Mar  7 09:18 libSymbolDictionary.a
-rw-rw-r-- 1 matt6809 matt6809 2128742 Mar  7 09:18 libSymbolXLib.a
[matt6809@hogganz400 ArcGIS2]$ make
rm -rf ./obj
mkdir -p ./obj ./libRelease
cp ./libRelease/libCommon.a ./obj;  cp ./libRelease/libGeometryXLib.a ./obj;  cp ./libRelease/libMapping.a ./obj;  cp ./libRelease/libpe_s.a ./obj;  cp ./libRelease/libpe++_s.a ./obj;  cp ./libRelease/libsg_s.a ./obj;  cp ./libRelease/libSymbolDictionary.a ./obj;  cp ./libRelease/libSymbolXLib.a ./obj;  cp ./SharedArcGIS/DepFilesLinux64/LibReleaseLinux64/Skia/libSkia.a ./obj;  cp ./SharedArcGIS/DepFilesLinux64/LibReleaseLinux64/LibTess/libLibTess.a ./obj;  cp ./SharedArcGIS/DepFilesLinux64/LibReleaseLinux64/SQLite/libSQLite.a ./obj;
echo 

#g++ -shared -Wl,-soname,libRuntimeCoreJava.so 
#ln -f -s libRuntimeCoreJava.so libRuntimeCoreJava.so.1
#ln -f -s libRuntimeCoreJava.so libRuntimeCoreJava.so.1.0
#ln -f -s libRuntimeCoreJava.so libRuntimeCoreJava.so.1.0.0
echo 

#ar cqs libRuntimeCoreJava.a 

为什么EXTRACT为空?输出显示libs被复制到.obj文件。

3 个答案:

答案 0 :(得分:3)

这是因为规则变量扩展和shell命令执行发生在两个不同的阶段。

订单如下:

  • 首先,尝试构建先决条件:

    $(TARGETD) : clean
        ...
    
    clean :
        rm -rf ./obj
    
  • 然后展开配方(换句话说,构造命令而不执行它们)

    $(TARGETD) : clean
        mkdir -p ./obj ./libRelease
        $(foreach lib, $(STATICS), cp $(lib) ./obj;)
        $(eval EXTRACT := $(wildcard ./obj/*.a))
        echo $(EXTRACT)
        $(foreach lib, $(EXTRACT), $(AR_EXTRACT) $(lib);)
        $(foreach lib, $(EXTRACT), rm -f $(lib);)
    

    请注意,此时clean已清除./obj,因此wildcard函数不返回任何内容。

  • 所以食谱变成了:

    $(TARGETD) : clean
        mkdir -p ./obj ./libRelease
        cp ./libRelease/libCommon.a ./obj;  cp ...
    
    
       echo
    

实际上最后一行是你在输出中看到的。

答案 1 :(得分:2)

规则中的每个命令行都被视为“配方”,每个配方都会调用要运行的新shell实例。因此,当您在一个配方中为EXTRACT设置一个值并尝试在另一个配方中读取它时,您正在从两个不同的shell实例中读取它们,并且它们之间没有值。解决这个问题的一种方法是将命令加入到单个配方中,如下所示:

$(TARGETD) : clean
        mkdir -p ./obj ./libRelease;  \
        for lib in $(STATICS) do; cp $$lib ./obj; done; \
        EXTRACT=`ls ./obj/*.a`; echo $$EXTRACT; \
        for lib in $$EXTRACT do; $(AR_EXTRACT) $$lib done; \
        for lib in $$EXTRACT do; rm -f $$lib; done; \

因此,当您设置EXTRACT时,它将可用于配方中的所有命令。

有关详细信息,请参阅http://www.gnu.org/software/make/manual/make.html#Recipes

答案 2 :(得分:1)

makefile规则中的每个命令都在自己的子shell中执行;变量不能从一个命令存活到下一个命令。