В каком порядке будут сделаны предположения GNU make?

Предполагая, что мы имеем правило:

a: b c d e

и b, c, d и e не зависят друг от друга.

Определен ли порядок выполнения b, c, d, e? Кажется, что в целом они будут сделаны в порядке b, c, d, e, но может случиться, что порядок будет другим?

Ответ 1

Конечно, если я использую make -j a, они могут быть созданы одновременно (в зависимости от того, имеют ли теги b, c, d или e другие/взаимосвязанные зависимости).

Ответ 2

Нет, порядок не определен. В этом и заключается смысл использования декларативно-зависимого программирования: компьютер может выбрать оптимальный порядок оценки или фактически оценить их даже в то же время.

Ответ 3

В каком порядке будут сделаны предположения 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

В правильном порядке, в соответствии с правилами, которые вы предоставляете. Для вашего конкретного примера это может означать любое из нескольких разных (4!= 24, из памяти) заказов.

Все программы make могут выбирать порядок, который им нравится, пока выполняются зависимости. Если в вашем примере были другие правила, скажем c: b, то c будет выполняться до b (но это не так, как вы указываете).

Если вам нужно полагаться на определенный заказ, вам потребуется больше правил для его принудительного применения. В противном случае make может делать то, что ему нравится. documentation для GNU. Указывает только, как обрабатываются правила, а не порядок, в котором обрабатываются зависимости внутри правила. Самый логичный порядок (для меня, во всяком случае) был бы порядком, в котором они перечислены, но которые не гарантированы.

Ответ 5

Нет, вы не можете рассчитывать на упорядочение, когда нет зависимостей.

  • make необходимо сделать топологический вид, поскольку зависимости могут иметь дополнительные и множественные отношения. Сорт, который делает make, потенциально довольно сложный, поскольку узлы в графе могут быть связаны несколько раз на разных уровнях.
  • в общих алгоритмах сортировки не являются естественными stable даже для простых сортировок по ключевому слову

Ответ 6

Если порядок имеет значение, вы можете выборочно применять его, используя recursive make. Например, предположим, что вас не волнует, в каком порядке b и c сделаны, пока они оба сделаны до того, как d и d будут сделаны до e. Затем вы можете написать свое правило как:

a: b c
    $(MAKE) d
    $(MAKE) e
    # Additional steps to make a

Помните, что в зависимости от сложности d и e этот подход может сделать Bad Things для вашего времени сборки: см. Рекурсивное принятие считается вредоносным (PDF) для аргументов против этого.