Ваша трудность связана с тем, что вы подразумеваете под промежуточный файл не то, что означает GNU Make;но специальная цель .INTERMEDIATE
позволяет вам настаивать на том, что a.o
и b.o
, которые в вашем make-файле не являются промежуточными файлами в смысле GNU Make, должны обрабатываться так, как если бы они были промежуточными в смысле GNU понимайте, и тогда вы будете ошарашены последствиями.
Что вы имеете в виду под F - это промежуточный файл : F является предварительным условием для цели T, а само F имеет предпосылки .Таким образом, a.o
и b.o
являются промежуточными по отношению к test.so
, потому что они являются предпосылками для этой цели, и сами имеют соответствующие предпосылки a.c
и bc`.
В вашем смысле промежуточные, поэтому цель test.so
не требует переделывания (a.o
| b.o
), если она не старше (a.c|b.c
).Таким образом, вы озадачены тем фактом, что когда a.o
и b.o
сделаны .INTERMEDIATE
, GNU Make всегда удаляет их , когда делает test.so
:
bo является промежуточным файлом, его не нужно снова компилировать, поскольку bc не изменился.Что я пропустил?
В основном вы пропустили 10.4 Цепи неявных правил
Обычно файл не может быть промежуточным, если он указан вMakefile в качестве цели или предпосылки.Однако вы можете явно пометить файл как промежуточный, указав его как обязательное условие специальной цели .INTERMEDIATE.Это вступает в силу, даже если файл упоминается явно как-то иначе.
Так, a.o
и b.o
обычно не будут промежуточными в смысле GNU Make, потому чтоони упоминаются в вашем make-файле как обязательные для test.so
.Но вы можете сделать их промежуточными, в смысле GNU Make, перечислив их в качестве предварительных условий .INTERMEDIATE
- как вы это сделали.
Что означает GNU Make под промежуточным , более техническичем то, что вы имеете в виду и объясняется в том же разделе руководства:
Иногда файл может быть создан с помощью последовательности неявных правил.Например, файл no можно создать из ny, запустив сначала Yacc, а затем cc.Такая последовательность называется цепочкой.
Если файл nc существует или упоминается в make-файле, специальный поиск не требуется: make находит, что объектный файл может быть создан компиляцией C из nc;позже, при рассмотрении вопроса о том, как сделать nc, используется правило для запуска Yacc.В конечном итоге и nc, и no обновляются.
Однако, даже если nc не существует и не упоминается, make знает, как представить его как недостающее звено между no и ny! В этом случае nc называется промежуточным файлом .Как только make решит использовать промежуточный файл, он будет введен в базу данных, как если бы он был упомянут в make-файле, вместе с неявным правилом, в котором указано, как его создать.
(Myакцент).Короче говоря, если Make требуется сделать цель output и обнаружить файл input такой, что:
- У него нет явного правила для создания вывод из ввод , но -
- Он знает последовательность неявных (он же встроенный ) правил, по которым файл stage , который не является целью или обязательным условием в make-файле, может быть сделан из input , и из которого output может быть выполнен, тогда он примет эту последовательность правил вывод из ввод через stage , а stage будет промежуточным файлом.
Важно, поскольку этап не является одной из ваших целей или обязательным условием для любой из них, Make знает, что это всего лишь одноразовый побочный продукт изготовления вывод из ввода и, следовательно, может быть удален, когда он служит этой цели.
Вот простой пример проекта с участием файлов, которые действительно являются промежуточными в смысле GNU Make.У нас есть yacc
source yacc.y
и lex
source lex.l
в каталоге проекта, и мы хотим построить из них парсер, parse
,со следующим make-файлом:
Makefile
YFLAGS := -d
OBJS := yacc.o lex.o
.PHONY: all clean
all: parse
parse: $(OBJS)
$(CC) $^ -o $@
clean:
$(RM) parse $(OBJS)
Он работает так:
$ make
yacc -d yacc.y
mv -f y.tab.c yacc.c
cc -c -o yacc.o yacc.c
lex -t lex.l > lex.c
cc -c -o lex.o lex.c
cc yacc.o lex.o -o parse
rm lex.c yacc.c
Теперь вы видите, что Make, используя его каталогнеявные правила, выяснили, что yacc.o
может быть сделано путем компиляции несуществующего исходного файла C yacc.c
, и что yacc.c
может быть получено из существующего исходного файла yacc.y
с помощью yacc -d yacc.y; mv -f y.tab.c yacc.c
.Аналогично, выяснилось, что lex.o
можно сделать, скомпилировав несуществующий источник C lex.c
, и что lex.c
можно сделать из lex.l
, запустив lex -t lex.l > lex.c
.Затем parse
создается из yacc.o
и lex.o
обычной связью, которую указывает make-файл.
Но ваш make-файл ничего не говорит о yacc.c
и lex.c
.Насколько вы сказали Make, для вас не имеет значения, существуют ли такие файлы когда-либо.Это промежуточные файлы , просто этапы производства .y -> .o
и .l -> .o
.Поэтому, когда Make завершает работу с ними:
rm lex.c yacc.c
Затем, если вы:
$ touch yacc.y
и снова:
$ make
yacc -d yacc.y
mv -f y.tab.c yacc.c
cc -c -o yacc.o yacc.c
cc yacc.o lex.o -o parse
rm yacc.c
only yacc.o
переделывается длясвязь parse
и промежуточный файл one yacc.c
, созданный на этот раз, удаляются.
Нижняя строка
Ваш объектфайлы не являются промежуточными в GNU Make, и вы не хотите, чтобы с ними обращались так, как если бы они были.Это нормально для объектных файлов.Так что удалите .INTERMEDIATE: $(OBJ)
.