GNU Make с использованием $ (eval ...) не работает - PullRequest
1 голос
/ 07 марта 2012

Вот make-файл:

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 пуст?Вывод показывает, что библиотеки были скопированы в файл .obj.

Ответы [ 3 ]

3 голосов
/ 07 марта 2012

Это связано с тем, что расширение переменных правила и выполнение команд оболочки выполняются в два этапа.

Порядок выглядит следующим образом:

  • Сначала попробуйте построить предпосылки:

    $(TARGETD) : <b>clean</b>
        ...
    
    <b>clean</b> :
        rm -rf ./obj
    
  • Затем разверните рецепт (другими словами, создайте команды, не выполняя их)

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

    Обратите внимание, что на данный момент clean уже очищен ./obj, поэтому функция wildcard ничего не возвращает.

  • Таким образом, рецепт становится:

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

На самом деле последние строки - это то, что вы можете видеть в своих выходных данных.

2 голосов
/ 07 марта 2012

Каждая командная строка в вашем правиле считается «рецептом», и каждый рецепт вызовет новый экземпляр оболочки для запуска. Таким образом, когда вы устанавливаете значение для EXTRACT в одном рецепте и пытаетесь прочитать его в другом, вы читаете из двух разных экземпляров оболочки, и значение не переносится между ними. Один из способов обойти это состоит в том, чтобы объединить ваши команды в один рецепт следующим образом:

$(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 для получения дополнительной информации

1 голос
/ 07 марта 2012

Каждая команда в правиле make-файла выполняется в своей собственной подоболочке;переменные не сохраняются от одной команды к следующей.

...