简体   繁体   中英

GNU Make using $(eval …) not working

Here is the 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

Here is the output:

[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 

Why is EXTRACT empty? The output show that the libs were copied over to the .obj file.

That's because rule variables expansion and shell command execution occur in two distinct phases.

The order is like the following:

  • First, try to build prerequisites:

    \n$(TARGETD) :  \n    ... \n\n :  :\n    rm -rf ./obj \n
  • Then expand the recipe (in other words, construct the commands without executing them)

    \n$(TARGETD) : clean \n    mkdir -p ./obj ./libRelease \n     \n     \n    echo  \n     \n     \n

    Note that at this point clean has already purged ./obj , thus wildcard function returns nothing.

  • So the recipe becomes:

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

Actually the last lines is what you can see in your output.

Each command line in your rule is considered to be a 'recipe', and each recipe will invoke a new instance of shell to run. Thus, when you set a value for EXTRACT in one recipe, and try to read it in another, you are reading from two different shell instances, and the value does not carry between them. One way to get around this is to join your commands into a single recipe as so:

$(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; \

Thus, when you set EXTRACT, it will be available for all the commands within your recipe.

See http://www.gnu.org/software/make/manual/make.html#Recipes for more info

Every command in a makefile rule executes in its own subshell; variables do not survive from one command to the next.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM