Каковы последствия наличия почти одинаковых целевых правил в Makefile? - PullRequest
0 голосов
/ 02 мая 2020

Я унаследовал проблему c Makefile.am, которая вызывала проблемы со сборкой. В этом make-файле есть пара случаев, когда существуют почти повторяющиеся целевые правила. Они почти повторяются, потому что у второго есть одна или две дополнительные предпосылки. Вот пример:

target1 target2: prereq1 prereq2 
        ACTION

target1 target2: prereq1 prereq2 prereq3
        ACTION

Действие идентично, а target1 и target2 идентичны. Каковы последствия этого? Будут ли выполнены оба правила?

Чтобы немного расширить этот вопрос, как бы это закончилось, если бы prereq3 был автоматически сгенерирован во время процесса make? Если make запускается параллельно, это может вызвать большие проблемы?

Ответы [ 2 ]

0 голосов
/ 02 мая 2020

Действие идентично, а target1 и target2 идентичны. Каковы последствия этого? Будут ли выполняться оба правила?

Следствием этого является то, что сгенерированные на основе этого Makefile.am make-файлы, которые будут включать оба правила дословно, не будут соответствовать спецификациям POSIX для make-файлов. POSIX запрещает, чтобы более чем одно целевое правило обеспечивало рецепт для любой данной цели.

Если вам случится использовать GNU make для сборки, тогда вместо прямого отклонения make-файла он будет использовать последний заданный рецепт для каждой цели; все остальные правила цели для каждой цели будут рассматриваться как правила только для предварительных условий, независимо от того, предоставляют они рецепт или нет. Если вы используете другой make (который явно поддерживается Autotools), результаты могут отличаться. Полагаясь на поведение, определяемое реализацией c, такое как это, очень плохая форма в системах сборки Autotools.

Поскольку рецепты одинаковы, цели одинаковы, а список предварительных требований более раннего правила подмножество списка обязательных требований более позднего правила, я не вижу причин для сохранения более раннего правила. Просто удалите его оптом. Никакое поведение не изменится под GNU make, и вам не придется беспокоиться о поведении других make, отличающихся из-за этой проблемы.

Это предполагает, однако, что нет другие целевые правила для target1 или target2. Если последнее появившееся правило для target2, предоставляющее рецепт, отличается от последнего появившегося правила для target1, предоставляющего рецепт, то будут запущены два рецепта: один для генерации target1 (возможно, со стороной эффект также генерирует target2), а другой генерирует target2 (возможно, с побочным эффектом также генерирует target1). Относительный порядок их не указан, и результат может быть противоречивым.

Вы также должны прочитать комментарии руководства Automake об инструментах и ​​правилах, которые генерируют несколько целей .

Чтобы немного расширить этот вопрос, если prereq3 был автоматически сгенерирован во время процесса сборки, как бы это закончилось?

Не иначе, как уже описано, по крайней мере для GNU make. Возможно, что описанная вами конструкция была мотивирована неправильным пониманием этой проблемы или, возможно, она нацелена на поведение c, специфичное для реализации, некоторой другой реализации make, чем GNU, но если в настоящее время программное обеспечение собирается правильно с GNU make, затем удаление первого правила просто преобразует полученный make-файл в POSIX-совместимый (в этом отношении), без каких-либо причин ожидать каких-либо изменений в поведении.

Могут быть нюансы и альтернативные решения, связанные со спецификой вашей ситуации, но все вышеприведенные комментарии применимы независимо от каких-либо таких деталей.

Если make выполняется параллельно, может ли это вызвать большие проблемы?

Дублирование правил описываемой вами формы не имеет конкретного взаимодействия с параллелью make. Тем не менее, вы, скорее всего, столкнетесь с проблемами с параллельным make, если вы не express полностью определите зависимости каждой цели, и особенно зависимости от других встроенных целей. Но учтите, что обычно вам не нужно express зависимостей от заголовочных файлов C или C ++, даже встроенных, потому что сгенерированные Automake make-файлы содержат код для их автоматического обнаружения и отслеживания.

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

Кроме того, хотя дублирование правила может не быть проблемой для параллельного make, если один запуск рецепта генерирует обе цели, затем , что может создать проблемы для параллельной make. Обратитесь к руководству Automake, указанному выше, для получения дополнительных комментариев по этому вопросу.

0 голосов
/ 02 мая 2020

Если вы используете gnu make, предупреждение указывает на то, что первое правило игнорируется. Запустив make с lol, выполните ДЕЙСТВИЕ из 2-го рецепта. ДЕЙСТВИЕ из первого рецепта можно удалить (что приведет к удалению предупреждений!).

make

Makefile:5: warning: overriding recipe for target 'target1'
Makefile:2: warning: ignoring old recipe for target 'target1'
Makefile:5: warning: overriding recipe for target 'target2'
Makefile:2: warning: ignoring old recipe for target 'target2'
echo "Action2"
Action2

Цитирование из gnu make manual: https://www.gnu.org/software/make/manual/make.html

предупреждение: переопределение рецепта для цели xxx' warning: ignoring old recipe for target xxx '

GNU make позволяет указывать только один рецепт для цели (кроме правил с двоеточием). Если вы даете рецепт для цели, которая уже была определена как имеющая, это предупреждение выдается, и второй рецепт перезаписывает первый. См. Несколько правил для одной цели.

...