Ответ 1
Я неправильно понимаю, как работают предпосылки только для заказа?
Да, вот как это выглядит.
Название "только для заказа" несколько сбивает с толку. Предпосылки позади |
называются "предварительными условиями только для заказа" не потому, что они изменяют порядок выполнения рецепта в списке предварительных условий для одной цели, а потому, что их единственная цель состоит в том, чтобы определенные цели создавались раньше других, например, при начальной загрузке. Как точно объяснено пользователем bobbogo ниже (- спасибо за исправление): если make
решит перестроить предварительное условие для цели, он запустит рецепт для этого предварительного условия. Теперь для обычной предпосылки это обновление подразумевает, что цель устарела, и make
придется запустить целевой рецепт. С другой стороны, для обязательного предварительного заказа make
не помечает цель как нуждающуюся в обновлении.
Например, см. Раздел " Типы предпосылок" для варианта использования, в котором каталог должен быть создан до создания объектов в этом каталоге.
Возьмите этот пример makefile
:
a: b
touch a
b: c
touch b
c:
touch c
x: | y
touch x
y: | z
touch y
z:
touch z
Как вы можете видеть, b
и c
являются нормальными предпосылками для a
и b
, тогда как y
и z
являются предпосылками только для порядка для x
и y
. Начиная с чистого листа, они выглядят одинаково:
:~$ make a
touch c
touch b
touch a
:~$ make x
touch z
touch y
touch x
:~$ make a
make: 'a' is up to date.
:~$ make x
make: 'x' is up to date.
Однако, если мы теперь вручную "обновим" предварительные условия в конце цепочки (c
и z
), мы увидим разницу:
:~$ touch c
:~$ make a
touch b
touch a
:~$ touch z
:~$ make x
make: 'x' is up to date.
Это показывает, как существующие предварительные условия только для заказа не делают недействительными какие-либо цели, независимо от их отметки времени. Однако удаление цели только для заказа приводит к перестройке (но только перестройке этого отсутствующего файла):
:~$ rm c
:~$ make a
touch c
touch b
touch a
:~$ rm z
:~$ make x
touch z
Тем не менее, правильный способ изменить порядок запуска ваших рецептов - исправить зависимости между целями. Например, если вы хотите, чтобы mefirst
был построен перед a
, то вам нужно сделать mefirst
обязательным условием для a
, как в
a: mefirst
@echo a
Невозможно дать полное решение вашего вопроса, так как вы не описали подробно, в каком порядке вы ожидаете рецепты.
В вашем ответе есть ярлык, который не является решением, но все же интересно узнать. Хотя это и не задокументировано, кажется, что предпосылки для одной цели обрабатываются в том порядке, в котором они появляются. |
знак не меняет этого. В вашем простом случае вы можете воспользоваться этим, чтобы получить результат, который вы ищете:
normaltarget: mefirst2 normaltarget2
@echo "normaltarget done"
а также
helloworld: mefirst normaltarget
@echo "helloworld done"
Однако, как вы сами указали, это "решение" ломается, как только флаг -j
используется для параллельного запуска рецептов. Кроме того, как указал пользователь bobbogo, полагаться на этот механизм упорядочения - плохая практика. Введение новых зависимостей может помешать упорядочению. Так что не делай этого :-)