2010-02-02 4 views
0

У меня есть грим файл, более или менее, следующая структура, которая компилирует C++ исходный код:Скомпилировать подстановочный шаблон слишком рано?

.PHONY: all 
all: compile_obj_files my_binary 

# This rule generates the object files. It works fine afaik. 
.PHONY: compile_obj_files 
compile_obj_files: 
    $(MAKE) --file=child.makefile 

# my_binary is a real binary file that I wish to build. 
my_binary: $(wildcard *.o) 
    $(CC) $(wildcard *.o) -o my_binary 

На первом запуске это делают файл генерируемой все объектные файлы, но $(wildcard *.o) возвращаемой пустой список. На втором запуске он ничего не собирал, как и ожидалось, и $(wildcard *.o) действительно возвратил все объектные файлы. Похоже, что $(wildcard *.o) выполняется до создания всех объектных файлов, несмотря на то, что правило my_binary работает всегда после compile_obj_files. Я сижу, глядя беспомощно на этот сценарий, не представляя, что здесь не так (должно быть, что-то глупое). Можете ли вы что-нибудь придумать?

ответ

3

Вы должны действительно не использовать $(wildcard ...) внутри правил, а сделать что-то вроде

MYSRC:=$(wildcard *.c) 
MYOBJ:=$(patsubst %.c, %.o, $(MYSRC)) 

%.o: %.c 
     $(CC) -c $< -o [email protected] 

my_binary: $(MYOBJ) 
     $(CC) $^ -o [email protected] 

Таким образом, вы знаете, что MYSRC и MYOBJ матч. Также обратите внимание на использование $< для обозначения зависимости текущей цели и [email protected] для обозначения целевого имени файла для текущей цели.

EDIT: Изменены $< на $^ в шаге компоновки включить все объектные файлы, а не только последнюю.

EDIT: Если вы не хотите, чтобы извлечь исходные имена файлов из child.makefile, вы должны быть в состоянии сделать что-то вроде этого:

.PHONY: all 
all: 
    $(MAKE) --file=child.makefile 
    $(MAKE) my_binary OBJS="$(wildcard *.o)" 

my_binary: $(OBJS) 
    $(CC) $< -o my_binary 

Важной частью является то, что значение OBJS соответствует при строительстве my_binary. Таким образом, вы четко разделите сборку на два шага, и список объектных файлов будет прочитан перед выполнением второго make.

+0

Спасибо. Я не уверен, что могу легко реализовать это решение. Мои файлы разбросаны в разных каталогах, поэтому сложно вычислить все имена. Вот почему мне было проще проверить все скомпилированные объекты. Я попытаюсь его реализовать, но, тем не менее, почему мое решение не работало? Разве мое выражение подстановки не должно быть оценено, когда правило будет разрешено? – FireAphis

+0

+1 Это было, по сути, то, что я сказал бы. Обратите внимание, что ': =' заставляет его пересчитывать при использовании. Если вы вместо этого используете '=', он будет вычислять значение только один раз в верхней части. –

+0

T.E.D., на самом деле все наоборот. Вот цитата из руководства GNU Make: «Просто расширенные переменные определяются строками, использующими«: = ». Значение просто расширенной переменной сканируется раз и навсегда (...), оно содержит их (переменные) значения с время, когда была определена эта переменная ». http://www.gnu.org/software/make/manual/html_node/Flavors.html – FireAphis