Ответ 1
Конечно, если я использую make -j a
, они могут быть созданы одновременно (в зависимости от того, имеют ли теги b
, c
, d
или e
другие/взаимосвязанные зависимости).
Предполагая, что мы имеем правило:
a: b c d e
и b
, c
, d
и e
не зависят друг от друга.
Определен ли порядок выполнения b
, c
, d
, e
? Кажется, что в целом они будут сделаны в порядке b
, c
, d
, e
, но может случиться, что порядок будет другим?
Конечно, если я использую make -j a
, они могут быть созданы одновременно (в зависимости от того, имеют ли теги b
, c
, d
или e
другие/взаимосвязанные зависимости).
Нет, порядок не определен. В этом и заключается смысл использования декларативно-зависимого программирования: компьютер может выбрать оптимальный порядок оценки или фактически оценить их даже в то же время.
В каком порядке будут сделаны предположения GNU make?
Это зависит от типа предпосылки. В соответствии с GNU Make Manual, раздел 4.2:
На самом деле существуют два разных типа предпосылок, понятых 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 изменена.
В правильном порядке, в соответствии с правилами, которые вы предоставляете. Для вашего конкретного примера это может означать любое из нескольких разных (4!= 24, из памяти) заказов.
Все программы make
могут выбирать порядок, который им нравится, пока выполняются зависимости. Если в вашем примере были другие правила, скажем c: b
, то c
будет выполняться до b
(но это не так, как вы указываете).
Если вам нужно полагаться на определенный заказ, вам потребуется больше правил для его принудительного применения. В противном случае make
может делать то, что ему нравится. documentation для GNU. Указывает только, как обрабатываются правила, а не порядок, в котором обрабатываются зависимости внутри правила. Самый логичный порядок (для меня, во всяком случае) был бы порядком, в котором они перечислены, но которые не гарантированы.
Нет, вы не можете рассчитывать на упорядочение, когда нет зависимостей.
Если порядок имеет значение, вы можете выборочно применять его, используя recursive make. Например, предположим, что вас не волнует, в каком порядке b и c сделаны, пока они оба сделаны до того, как d и d будут сделаны до e. Затем вы можете написать свое правило как:
a: b c
$(MAKE) d
$(MAKE) e
# Additional steps to make a
Помните, что в зависимости от сложности d и e этот подход может сделать Bad Things для вашего времени сборки: см. Рекурсивное принятие считается вредоносным (PDF) для аргументов против этого.