Как заставить переоценку переменных в make-файле - PullRequest
0 голосов
/ 17 марта 2012

У меня есть make-файл, который запускает двоичный файл для генерации файлов cpp. Затем я компилирую файлы cpp и генерирую файлы .o для каждого файла cpp.

Проблема в том, что при первом вызове make-файла папка пуста, поскольку бинарный файл еще не запущен, и

CPP_FILES=$(wildcard $(MY_DIR)/inc/output/*.cpp) 

будет пустой переменной.

Итак, я изменил строку на

CPPFILES=$$(wildcard $(MY_DIR)/inc/output/*.cpp) 
OBJFILES=$$(patsubst $(MY_DIR)/*.cpp,$(MY_DIR)/*.o,$(CPPFILES))

и

// запустил двоичный файл для генерации файлов cpp

.SECONDEXPANSION:
libEXP.so:$(CPPFILES),$(OBJFILES)
       $(CC) $(CFLAGS) -I(INC) -L(LIBS) -shared -o $(OBJFILES) $@

Вторичное расширение завершается неудачно, сообщая, что оболочка не может найти подстановочную команду.
Что я делаю не так ??

Ответы [ 5 ]

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

Проблема, с которой вы столкнулись, заключается в том, что make всегда работает от конечной цели НАЗАД до источников, а затем снова начинает строить и разрешать предпосылки обратно.Make запускается с библиотекой, затем видит, каковы ее предварительные условия, затем видит, каковы предварительные условия для них, затем необходимые условия для ТЕ и т. Д. И т. Д.

Итак, когда make расширяет значение $(OBJFILES), даже еслиВы задерживаете это при втором расширении, но все равно случается, что файлы .cpp еще не созданы.

Вы должны объяснить, что существует правило, которое может генерировать файл .cpp.Как только make поймет это, он применит ваше правило для вас.Однако вы не сможете использовать подстановочный знак для определения файлов .cpp, которые нужно собрать, если только вы не захотите сделать что-то вроде первой сборки всех файлов .cpp, а затем рекурсивно вызвать make.

Редактировать:

Вы спросили, почему не работает второе расширение.Я упоминал об этом в моем первом абзаце, но, вероятно, не был достаточно ясен.Марка проходит две стадии обработки.Сначала он читает make-файлы, затем он проходит через правила и создает вещи.Вторичный шаг расширения задерживает разрешение до этого второго шага ... но это не поможет вам в этом случае.

Вы просите make собрать libEXP.so.Для этого ему необходимо расширить предварительные условия для libEXP.so, чтобы он знал, от чего зависит цель. ЭТО - это когда выполняется второе расширение, но здесь мы еще не создали никаких файлов .cpp, потому что мы не знаем, что они нам нужны, поэтому подстановочный знак расширяется до нуля.Make не будет создавать эти файлы .cpp, пока не узнает, что они им нужны, и не сможет знать, что они им нужны, пока у них их уже нет, поэтому он может сгенерировать список файлов .o для предварительных требований libEXP.so.Это явно не сработает:)

1 голос
/ 01 июня 2016

Чтобы сделать это явным: вы не должны использовать $(wildcard ) для сгенерированных файлов.Если вам нужен «список всех сгенерированных файлов», $(wildcard ) предоставит вам этот список только по счастливой случайности (если все файлы уже созданы).

Если существует соответствие 1-к-1между файлом генератора и сгенерированным файлом, вы можете использовать $(wildcard) в файлах генератора и преобразовать результат.

На примере буферов протокола Google (он может генерировать файлы .cc из файлов .proto)

PROTOSS := $(wildcard *.proto)
GENERATED_SOURCES := ${PROTOSS:.proto=.cc}
GENERATED_HEADERS := ${PROTOSS:.proto=.h}
0 голосов
/ 16 сентября 2017

Другой вариант - использовать цикл for в bash:

target: prereqs
    for file in files/*; do \
        ... \
    done
0 голосов
/ 07 января 2017

Я столкнулся с этой ситуацией.Я пробовал несколько уровней косвенного обращения (используя постоянную последовательность, которая называла постоянную последовательность, которая использовала wildcard), но make всегда оценивал подстановочный знак перед выполнением рецепта, который генерировал файлы.Мое решение состояло в том, чтобы написать сценарий Perl, чтобы собрать список файлов и выполнить операцию, которую мне нужно было выполнить с ними, а затем вызвать сценарий из make-файла.Я только хотел бы, чтобы я сделал это раньше.Я думал, что хотел бы избежать введения дополнительного файла, но в целом работать со сценарием намного проще, чем с нетривиальным рецептом make-файла, что это сэкономило бы много времени для этого с самого начала.

0 голосов
/ 17 марта 2012

Оставьте CPPFILES и OBJFILES как обычные рекурсивные переменные:

CPPFILES = $(wildcard $(MY_DIR)/inc/output/*.cpp)
OBJFILES = $(CPPFILES:%.cpp=%.o)

И для отсрочки расширения используйте двойные доллары следующим образом:

.SECONDEXPANSION:
libEXP.so: $$(OBJFILES)
    $(CC) $(CFLAGS) -I(INC) -L(LIBS) -shared -o $(OBJFILES) $@

Но я думаюпроблема в том, что расширение происходит до того, как вы запустите генератор файлов cpp.Как вы вызываете это?Это правило или что-то еще?

...