После возврата из каждой команды шелла, запускаемой для обработки target, утилита make смотрит на статус выхода команды. Если команда шелла вернула статус успеха (статус exit равен 0), то выполнится следующая строка recipe в новом shell; после завершения последней строки обработка правила завершена.
Если в какой-то команде произошла ошибка (статус exit не нулевой), то make сдается на текущем правиле, и возможно на всех остальных правилах.
Иногда отказ в определенной строке recipe не означает наличие проблемы. Например, вы можете использовать команду mkdir, чтобы обеспечить существование директории. Если директория уже существует, то mkdir сообщит об ошибке, однако вероятно вы захотите продолжить работу make, независимо от статуса возврата mkdir.
Чтобы игнорировать ошибку на строке recipe, начните её текст с символа '-' (после первого символа табуляции). Символ '-' отбрасывается перед передачей команды шеллу.
Например,
.. приведет к тому, что make продолжит работу, если даже rm не сможет удалить файл.
Когда вы запускаете make с опцией -i или --ignore-errors, то ошибки игнорируются во всех recipe всех правил. Правило в makefile для специальной target .IGNORE дает тот же эффект, если у неё нет prerequisite. Это не настолько гибкое решение, но иногда бывает полезным.
Когда ошибки должны игнорироваться из-за '-' или опции -i, утилита make обрабатывает возвращаемую ошибку так же, как и успех, за исключением того, что он распечатывает сообщение, в котором сообщается код состояния, с которым вышла оболочка, и говорит, что ошибка была проигнорирована.
Когда произошла ошибка, которая не была обозначена для make как игнорируемая, это подразумевает, что не может быть корректно перестроена как текущая target, так и любая другая target, которая зависит от неё явно или косвенно. Дальнейшие recipe для этих target не будут выполняться, поскольку их предварительные условия не были достигнуты.
Обычно в этом случае make сразу сдается, и возвращает ненулевой статус. Однако, если указана опция -k или --keep-going, то make продолжает учитывать другие prerequisite ожидающих обработки target-ов, перестраивая их при необходимости перед тем, как сдаться и вернуть ненулевой статус. Например, после ошибки в одном компилируемом объектном файле make -k продолжит компиляцию других объектных файлов, хотя уже известно, что выполнить конечную цель сборки будет невозможно. См. "9.8 Summary of Options" [1].
Обычное поведение предполагает, что ваша цель состоит в том, чтобы при сборке поддерживать обновленными указанные цели; как только утилита make обнаружит, что это невозможно, она может немедленно сообщить о проблеме. Опция -k говорит о том, что реальная цель состоит в том, чтобы протестировать как можно больше изменений, сделанных в программе, и возможно обнаружить несколько независимых проблем в компилируемых файлах исходного кода, чтобы можно было исправить их все до следующей попытки запуска компиляции. Именно по этой причине команда компиляции Emacs по умолчанию передает опцию -k; применение этого флага может быть полезно при компиляции очень больших проектов.
Обычно при сбое строки recipe, если она вообще изменила целевой файл, этот файл будет поврежденным, и его использовать нельзя, или как минимум он не может быть полностью обновлен или даже вообще сгенерирован. Тем не менее, если файл был создан, то метка файла говорит, что файл обновлен, и при следующей попытке запуска этот файл не будет обновляться. Ситуация точно такая же, как если бы shell был прибит сигналом (когда пользователь в процессе компиляции нажал Ctrl+C); см. "5.6 Interrupting or Killing make" [1]. Так что было бы правильно удалить целевой файл, если recipe терпит неудачу после начала изменения файла. Утилита make может это сделать автоматически, если в качестве target появляется .DELETE_ON_ERROR [3]. Это почти всегда то, что вы хотите сделать, но это не историческая практика; поэтому для обеспечения совместимости вы должны явно запросить это действие.
[Ссылки]
1. GNU make. 2. Магия makefile на простых примерах. 3. Makefile: специальные встроенные имена целей. |