На самом деле GNU make понимает два разных типа предварительных условий: обычные предварительные условия, такие как описанные в предыдущем разделе, и предварительные требования только для порядка. Обычное предварительное условие состоит из двух утверждений: во-первых, оно устанавливает порядок, в котором рецепты будут вызываться: рецепты для всех предварительных условий цели будут выполнены до того, как рецепт для цели будет запущен. Во-вторых, он устанавливает отношения зависимости: если какое-либо предварительное условие новее, чем цель, то цель считается устаревшей и должна быть перестроена.
Обычно это именно то, что вам нужно: если предварительное условие цели обновлено, то цель также должна быть обновлена.
Однако иногда возникает ситуация, когда вы хотите наложить определенный порядок на правила, которые будут вызываться без принудительного обновления цели, если выполняется одно из этих правил. В этом случае вы хотите определить предварительные требования только для заказа. Предварительные условия только для заказа можно указать, поместив вертикальную черту (|) в список предварительных требований: любые предварительные условия слева от вертикальной черты являются нормальными; любые предварительные условия справа относятся только к заказу:
targets: normal-prerequisites | order-only-prerequisites
Нормальный раздел предварительных условий, конечно, может быть пустым. Кроме того, вы по-прежнему можете объявить несколько строк предварительных условий для одной и той же цели: они добавляются соответствующим образом (обычные предварительные условия добавляются к списку обычных предварительных условий; предварительные условия только для заказа добавляются к списку предварительных условий только для заказа). Обратите внимание, что если вы объявляете один и тот же файл как обычное предварительное условие, так и предварительное условие только для заказа, нормальное предварительное условие имеет приоритет (поскольку они имеют строгий надмножество поведения предварительного условия только для заказа).
Рассмотрим пример, в котором ваши цели должны быть помещены в отдельный каталог, и этот каталог может не существовать до запуска make
. В этой ситуации вы хотите, чтобы каталог был создан до того, как в него будут помещены какие-либо цели, но, поскольку временные метки в каталогах меняются всякий раз, когда файл добавляется, удаляется или переименовывается, мы, конечно, не хотим перестраивать все целевые объекты всякий раз, когда метка времени каталога изменяется. Один из способов справиться с этим - использовать предварительные условия только для заказа: сделать каталог предварительным условием только для заказа для всех целей:
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
Теперь правило для создания каталога «objdir» будет выполняться, если необходимо, до создания любого «.o», но «.o» не будет построено, поскольку временная метка каталога «objdir» изменилась.