Игнорировать ошибки make

https://www.gnu.org/software/make/manual/make.html#Errors

Sometimes the failure of a certain recipe line does not indicate a problem. For example, you may use the mkdir command to ensure that a directory exists. If the directory already exists, mkdir will report an error, but you probably want make to continue regardless.

To ignore errors in a recipe line, write a - at the beginning of the line’s text (after the initial tab). The - is discarded before the line is passed to the shell for execution.

For example,

clean:
        -rm -f *.o

This causes make to continue even if rm is unable to remove a file.

When you run make with the -i or --ignore-errors flag, errors are ignored in all recipes of all rules. A rule in the makefile for the special target .IGNORE has the same effect, if there are no prerequisites. These ways of ignoring errors are obsolete because - is more flexible.

In other words, make --ignore-errors behaves like there is a - in front of all commands.

When errors are to be ignored, because of either a - or the -i flag, make treats an error return just like success, except that it prints out a message that tells you the status code the shell exited with, and says that the error has been ignored.

When an error happens that make has not been told to ignore, it implies that the current target cannot be correctly remade, and neither can any other that depends on it either directly or indirectly. No further recipes will be executed for these targets, since their preconditions have not been achieved.

Normally make gives up immediately in this circumstance, returning a nonzero status. However, if the -k or --keep-going flag is specified, make continues to consider the other prerequisites of the pending targets, remaking them if necessary, before it gives up and returns nonzero status. For example, after an error in compiling one object file, make -k will continue compiling other object files even though it already knows that linking them will be impossible. See Summary of Options.

The usual behavior assumes that your purpose is to get the specified targets up to date; once make learns that this is impossible, it might as well report the failure immediately. The -k option says that the real purpose is to test as many of the changes made in the program as possible, perhaps to find several independent problems so that you can correct them all before the next attempt to compile. This is why Emacs’ compile command passes the -k flag by default.

Let’s take this example:

target: intermediate-1 intermediate-2 intermediate-3
        cat intermediate-1 intermediate-2 intermediate-3 > target

intermediate-1:
        echo "oh no, I'm failing!"
        false

intermediate-2:
        echo 'hello' > intermediate-2

intermediate-3:
        echo 'world' > intermediate-3

Normally when you run make target (and none of the files exist yet), it will first try to make intermediate-1. That target fails because one of the associated commands (false) returns a non-zero exit status. make then immediately gives up and does not even look at intermediate-2 or intermediate-3.

However, with make --keep-going target, it will note the failure of intermediate-1, but keep on going to make intermediate-2 and intermediate-3, which succeeds (creating files containing «hello» and «world», respectively).

In the end it still gives up and reports a failure to make target, but it has tried to create all intermediate targets, even ones it knows won’t be used in this run of make because another prerequisite already failed.

If you use both flags (make --ignore-errors --keep-going), then --keep-going is effectively ignored. --keep-going only affects how make behaves when it encounters an error in an intermediate target, but --ignore-errors means make will never encounter an error.

Ошибки в рецептах

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

Если возникает ошибка (статус выхода отличен от нуля), make отказывается от текущего правила и, возможно, от всех правил.

Иногда сбой в определенной строке рецепта не указывает на проблему. Например, вы можете использовать команду mkdir , чтобы убедиться, что каталог существует. Если каталог уже существует, mkdir сообщит об ошибке, но вы, вероятно, захотите продолжить make

Чтобы игнорировать ошибки в строке рецепта,напишите ‘‘ в начале текста строки (после начальной табуляции). ‘‘ отбрасывается до того, как строка будет передана оболочке для выполнения.

For example,

Это заставляет make продолжить, даже если rm не может удалить файл.

Когда вы запускаете make с ‘-i‘ или же ‘—ignore-errors‘ ошибки игнорируются во всех рецептах всех правил. Правило в make-файле для специальной цели .IGNORE имеет тот же эффект, если нет предварительных требований. Это менее гибко, но иногда полезно.

Когда ошибки должны быть проигнорированы,по причине либо ‘‘ или ‘-i‘, make обрабатывает возврат ошибки так же, как и успех, за исключением того, что он выводит сообщение, в котором сообщается код состояния, с которым оболочка завершила работу, и говорится, что ошибка была проигнорирована.

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

Обычно в этом случае make немедленно сдается, возвращая ненулевой статус. Однако, если ‘-k‘ или же ‘—keep-going‘, make продолжает рассматривать другие предпосылки ожидающих целей, при необходимости переделывая их, прежде чем сдаться и вернуть ненулевой статус. Например, после ошибки при компиляции одного объектного файла ‘make -k‘ продолжит компиляцию других объектных файлов, даже если уже знает, что их компоновка будет невозможна. См. сводку опций .

Обычное поведение предполагает, что ваша цель — обновить указанные цели; как только make узнает, что это невозможно, он может немедленно сообщить об ошибке. ‘-k‘ говорит, что реальная цель состоит в том, чтобы протестировать как можно больше изменений, внесенных в программу, возможно, чтобы найти несколько независимых проблем, чтобы вы могли исправить их все перед следующей попыткой компиляции. Вот почему команда compile Emacs передает ‘-k‘ флаг по умолчанию.

Обычно, когда строка рецепта дает сбой, если она вообще изменила целевой файл, файл поврежден и не может быть использован — или, по крайней мере, он не полностью обновлен. Тем не менее, отметка времени файла говорит о том, что он обновлен, поэтому при следующем запуске make не будет пытаться обновить этот файл. Ситуация точно такая же, как когда оболочка убита по сигналу; см . Прерывания . Так что, как правило, правильнее будет удалить целевой файл, если рецепт не работает после начала изменения файла. make сделает это, если в качестве цели появится .DELETE_ON_ERROR .Это почти всегда то, что вы хотите make , но это не историческая практика; поэтому для совместимости вы должны явно запросить его.


GNU Make

4.4

  • Переменные из окружающей среды

    Переменные в make могут исходить из запущенной среды.

  • Ошибки,генерируемые Make

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

  • Функция eval

    Функция eval очень особенная: она позволяет вам определять новые конструкции make-файла, которые не являются постоянными; результат оценки других переменных и

  • Recipe Execution

    Когда приходит время выполнить цель обновления рецептов, они выполняются путем вызова новой подоболочки для каждой строки специального эффекта .ONESHELL (см. Использование

MAKE(1)

НАЗВАНИЕ

make — поддержка, обновление и восстановление групп

программ

СИНТАКСИС

   make  [-f make-файл] [-p] [-i] [-k] [-s] [-r] [-n] [-b] [-e] [-u] [-t] [

	 [целевой_файл ...]

ОПИСАНИЕ

Утилита make позволяет поддерживать, изменять и регенерировать группы программ. Ниже приведено краткое описание всех опций и некоторых специальных имен:

-f make-файл

Задание имени файла с описаниями.

-p
Вывести все макроопределения, а также описания зависимостей и операций для создания целевых_файлов.

-i
Игнорировать коды ошибок, возвращаемых запускаемыми программами. Этот режим устанавливается также

при появлении в файле описаний специального целевого имени .IGNORE.

-k
При ошибке прекращать выполнение команд, связанных

с текущей зависимостью, но продолжать обработку

других зависимостей.

-s
Не выводить командные строки перед их выполнением.

Этот режим устанавливается также при появлении в

файле описаний специального целевого имени

.SILENT.

-r
Не использовать встроенные правила.

-n
Выводить команды, но не выполнять их. Выводятся

даже команды, которые начинаются с @.

-b
Режим для совместимости со старыми версиями

make-файлов.

-e
В первую очередь используются переменные окружения, а не одноименные макросы make-файлов.

-u
Вызывает безусловное обновление.

-t
«Массаж» целевых_файлов: время их создания устанавливается равным текущему времени; команды,

предназначенные для получения целевых_файлов, не

выполняются.

-q
Запрос. Команда make возвращает нулевой или ненулевой код завершения в зависимости от того, нужно

ли обновлять целевые_файлы (0, если не нужно). Печать команд подавляется, даже если присутствует

опция -n.

.DEFAULT

Если должен быть сделан файл, но нет ни явных команд, ни соответствующих встроенных правил, то используются команды, ассоциированные со специальным

целевым именем .DEFAULT, если они существуют.

.PRECIOUS

Файлы, которые зависят от этого специального имени, не удаляются, если работа команды make была

прервана или прекращена.

.SILENT

Дает тот же эффект, что и опция -s.

.IGNORE

Дает тот же эффект, что и опция -i.

Make выполняет команды из make-файла для обновления одного или нескольких целевых_файлов, имена которых указаны в команде. Если отсутствует опция -f, то ищутся

файлы makefile, Makefile, и файлы системы управления

исходными текстами (SCCS) s.makefile и s.Makefile в

указанном порядке. Если вместо make-файла указан -, то

это означает стандартный ввод. В командной строке может

встретиться более чем одна пара -f make-файл.

Команда make обновляет целевой_файл только в том случае, если файлы, от которых он зависит, оказываются новее в смысле времени модификации (кроме случая, когда

была использована опция -u с целью вызвать безусловное

обновление). Все файлы, от которых зависит целевой_файл

добавляются рекурсивно к списку целевых файлов. Отсутствующие файлы считаются требующими обновления.

Make-файл состоит из последовательности разделов, определяющих зависимости. Первая строка раздела — непустой

список разделенных пробелами имен целевых файлов, затем

знак :, затем (возможно пустой) список необходимых файлов или зависимостей. Текст, следующий за ; и все последующие строки, начинающиеся с табуляции, представляет

собой команды shell’а, которые необходимо выполнить для

обновления целевого файла. Первая строка, которая не

начинается с табуляции или #, открывает новое описание

зависимости или макроопределение. Команды shell’а могут

быть продолжены в следующей строке, если последним символом текущей строки поставить \. Все, что выводит

make, кроме начальных символов табуляции, передается

shell’у в исходном виде. Например,

	echo a\

	b

даст

	ab

как если бы команда выполнялась просто shell’ом.

Символы # и перевод_строки обрамляют комментарии.

В приведенном ниже make-файле определяется, что pgm зависит от двух файлов: a.o и b.o, и что они в свою очередь зависят от соответствующих исходных файлов (a.c и

b.c) и общего файла incl.h:

     pgm: a.o b.o

        cc a.o b.o -o pgm

     a.o: incl.h a.c

        cc -c a.c

     b.o: incl.h b.c

        cc -c b.c

Командные строки выполняются по одной, каждая своим

собственным shell’ом. Чтобы указать, каким shell’ом выполнять команду, можно использовать переменную окружения SHELL. Первые один или два символа команды могут

быть следующими: -, @, -@, @-. Если присутствует @, то

подавляется вывод команды. При указании символа — make

игнорирует ошибки. Команда перед ее выполнением выводится, если только не указана опция -s, или в make-файле отсутствует вход .SILENT:, или в начале команды не

стоит знак @. Опция -n специфицирует вывод команд без

их выполнения; однако, если командная строка содержит

текст $(MAKE), то она всегда выполняется (см. MAKEFLAGS

в пункте Окружение). Если указана опция -t, то изменяется время последней модификации файлов без выполнения

каких-либо команд. К сожалению, при этом не изменяются

даты сохранения файлов в библиотеках (см. Библиотеки),

а меняется только время последней модификации библиотеки.

Команды, возвращающие ненулевой код завершения, обычно

прекращают выполнение make. Если же указана опция -i

или в make-файле присутствует вход .IGNORE:, или командная строка начинается со знака -, то ошибки игнорируются. Если указана опция -k, то прекращается обработка текущего раздела, но продолжаются действия, которые

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

были достигнуты.

Опция -b позволяет без ошибок выполнять make-файлы, написанные для старой версии make’а. Отличие состоит в

том, что в новой версии все строки зависимостей должны

содержать (возможно пустые или задаваемые по умолчанию)

команды, связанные с ними. В предыдущей версии считалось, что неспецифицированная команда является пустой.

Сигналы прерывания и выхода вызывают уничтожение целевого файла, если только он не зависит от специального

имени .PRECIOUS.

Окружение

Команда make читает окружение. Все переменные окружения

обрабатываются как макроопределения. Все они читаются и

обрабатываются до обработки make-файла и после обработки встроенных правил; поэтому макроопределения из

make-файла перекрывают макроопределения из окружения.

Если задана опция -e, то переменные из окружения перекрывают макроопределения из make-файла. Суффиксы и связанные с ними правила из make-файла перекрывают описания суффиксов во встроенных правилах.

Переменная окружения MAKEFLAGS обрабатывается как содержащая любую из допустимых опций (кроме -f и -p),

описанных для командной строки. Далее, если такой переменной в окружении нет, то make создает ее, помещая в

нее все указанные в командной строке опции, и передает

ее всем запускаемым им командам. Таким образом,

MAKEFLAGS всегда содержит текущие опции. Эта возможность очень полезна, если возникла необходимость отладить make-файл для проекта, состоящего из подсистем,

для которых есть свои собственные make-файлы. Как уже

отмечалось выше (при использовании опции -n) команда

$(MAKE) выполняется всегда, следовательно, можно выполнить make -n рекурсивно по всему проекту, чтобы посмотреть, что было бы выполнено при отсутствии опции -n.

Это возможно, так как флаг -n помещается в MAKEFLAGS и

передается при вызове $(MAKE). Тем самым перед нами

один из способов проверить все make-файлы проекта, не

выполняя их на самом деле.

Включение файлов

Если в make-файле строка начинается с цепочки символов

include и после нее пробел или табуляция, то остаток

строки после подстановки макросов считается именем файла и этот файл будет прочтен и включен в make-файл.

Макросы

Разделы, имеющие вид

	цепочка1=цепочка2

являются макроопределениями. В цепочку2 входят все символы до начала комментария или до неэкранированного перевода строки. Последующие вхождения конструкции $(цепочка1[:подцеп1=[подцеп2]]) заменяются цепочкой2. При

этом, если в цепочке2 встречаются подцепочки подцеп1,

за которыми следует пробел или табуляция, и подцеп1 начинается с точки, они заменяются на подцепочку подцеп2.

Если имя макроса состоит из одного символа и нет подстановок, то круглые скобки можно опускать. Пример использования подстановок см. в пункте Библиотеки.

Внутренние макросы

Мake поддерживает пять внутренних макросов, полезных

при написании правил построения целевых файлов:

$*
Этот макрос является именем файла без расширения

из текущей зависимости; вычисляется только для

подразумеваемых правил (см. Суффиксы).

$@
Этот макрос заменяется на полное имя целевого файла; вычисляется только для явно заданных зависимостей.

$<
Вычисляется только для подразумеваемых правил или

для правила .DEFAULT. Этот макрос заменяется на

имя файла, от которого по умолчанию зависит целевой файл. Так, в правиле .c.o макрос $< будет заменен на имя файла с расширением .c. Например,

правило для изготовления оптимизированного об ектного файла из файла с расширением .c может быть

таким:

	.c.o:

               cc -c -O $*.c

или

	 .c.o:

	        cc -c -O $<

$?
Макрос $? можно использовать в явных правилах

make-файла. Этот макрос заменяется на список файлов-источников, которые изменялись позднее целевого файла.

$%
Этот макрос применяется только тогда, когда целевой файл указан в виде библ(файл.o), что означает,

что он находится в библиотеке библ. В этом случае

$@ заменяется на библ (имя архива), а $% заменяется на настоящее имя файла, файл.o.

Четыре из этих макросов имеют альтернативную форму. Если к любому из этих макросов добавлено F, то он заменяется на соответствующее макросу имя файла без имени каталога; если же добавлено D, то макрос заменяется на

остальную часть значения первоначального макроса без

последнего символа /, то есть на имя каталога. Так,

$(@D) соответствует каталогу из $@. Если каталог не

указан, то генерируется текущий каталог (.). Только

макрос $? не имеет альтернативной формы.

Суффиксы

Некоторые файлы (например файлы, имена которых оканчиваются на .o) имеют подразумеваемые источники, например, файлы, имена которых оканчиваются на .c, .s и т.д.

Если для этих файлов не указаны команды их модификации

в make-файле, но существуют подразумеваемые источники,

то они (источники) компилируются для получения требуемых файлов. В таких случаях make применяет подразумеваемые (встроенные) правила вывода, позволяющие получить

одни файлы из других путем исследования суффиксов и определения соответствующих команд. Подразумеваемые правила вывода таковы:

	.c .c~ .f .f~ .sh .sh~

	.c.o .c.a .c~.o .c~.c .c~.a

	.f.o .f.a .f~.o .f~.f .f~.a

	.h~.h .s.o .s~.o .s~.s .s~.a .sh~.sh

	.l.o .l.c .l~.o .l~.l .l~.c

	.y.o .y.c .y~.o .y~.y .y~.c

Встроенные правила можно изменять. Чтобы вывести их в

виде, пригодном для изменения, нужно воспользоваться

командой

	make -fp - 2>/dev/null rules

Символ ~ (тильда) используется в этих правилах для

SCCS-файлов [см. sccsfile(4)]. Так, правило .c~.o

трансформирует SCCS C-файл в об ектный файл .o. Так как

s. в SCCS-файлах является префиксом, то это несовместимо с принятым в make способом определения правила по

суффиксу. Использование тильды вызывает замену ссылки

на файл ссылкой на SCCS-файл.

Правила с одним суффиксом (например .c:) описывают, как

получить файл x из x.c (то есть второй суффикс пустой).

Это полезно для построения целевого файла только из одного исходного файла (например, для построения

shell-процедуры или простой C-программы).

Дополнительные суффиксы даются как список зависимостей

для специального имени .SUFFIXES. При этом важен порядок: первое возможное имя, для которого существуют и

файл и правило, используется как имя источника. По

умолчанию этот список выглядит так:

	.SUFFIXES: .o .c .c~ .y .y~ .l .l~ .s .s~ .h~ .h .f .f~

	.sh~ .sh

Команда, указанная выше для вывода списка встроенных

правил, показывает также встроенный список суффиксов.

Многократные указания .SUFFIXES: об единяют списки суффиксов; указание .SUFFIXES: с пустым списком очищает

список суффиксов.

Подразумеваемые правила

Пример с целевым файлом pgm можно записать короче:

     pgm: a.o b.o

        cc a.o b.o -o pgm

     a.o b.o: incl.h

Это возможно, так как make использует набор внутренних

правил. Пользователь может добавить правила просто поместив их в make-файл.

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

получающихся команд. Например, CFLAGS, LFLAFS, и YFLAGS

используется для задания опций компиляторам cc(1),

lex(1), и yacc(1) соответственно. Для определения значений по умолчанию этих макросов можно снова порекомендовать описанный ранее метод для просмотра встроенных

правил.

Подразумеваемые правила можно изменять. Правило создания файла с суффиксом .o из файла с суффиксом .c указывается как раздел с именем .c.o: и пустым списком зависимостей. Команды shell’а, связанные с этим именем, определяют способ получения файла .o из файла .c. Любое

имя, в которое не входит символ /, и которое начинается

с точки, распознается как имя правила, а не настоящего

целевого файла.

Библиотеки

Если целевой файл или имя из списка зависимостей содержит скобки, то оно рассматривается как имя архивной

библиотеки, а цепочка символов в скобках — как имя элемента библиотеки. Так, и библ(файл.o), и

$(БИБЛ)(файл.o) обозначают библиотеку, содержащую

файл.o (предполагается, что макрос БИБЛ был предварительно определен). Выражение $(БИБЛ)(файл1.o файл2.o)

недопустимо. Правила обработки библиотечных файлов имеют вид .XX.a, где XX — суффикс, по которому будет получен элемент библиотеки. К сожалению, в текущей реализации требуется, чтобы XX отличался от суффикса элемента

библиотеки. Например, нельзя, чтобы библ(файл.o) зависел от файл.o явно. Наиболее общее использование интерфейса работы с библиотеками следующее (предполагается,

что исходными являются файлы на языке C):

     lib: lib(file1.o) lib(file2.o) lib(file3.o)

        @echo lib is now up-to-date

     .c.a:

        $(CC) -c $(CFLAGS) $<

        $(AR) $(ARFLAGS) $@ $*.o

        rm -f $*.o

Фактически, правило .c.a, приведенное выше, встроено в

make. Более интересный, но более ограниченный пример

конструкции, поддерживающей работу с библиотеками:

     lib: lib(file1.o) lib(file2.o) lib(file3.o)

        $(CC) -c $(CFLAGS) $(?:.o=.c)

        $(AR) $(ARFLAGS) lib $?

        rm $?  @echo lib is now up-to-date

     .c.a:;

Здесь используется режим подстановки расширений макросов. Список $? определен как множество имен об ектных

файлов (в библиотеке lib), чьи исходные C-файлы были

изменены. Подстановка заменяет .o на .c. (К сожалению,

нельзя еще трансформировать в .c~; однако, это может

стать возможно в будущем). Заметим также, что запрещается правило .c.a:, создающее каждый об ектный файл

один за другим. Эта конструкция значительно ускоряет

обновление библиотек, но становится весьма громоздкой,

если библиотека содержит как программы на C, так и на

ассемблере.

ФАЙЛЫ

	[Mm]akefile и s.[Mm]akefile

	/bin/sh

СМ. ТАКЖЕ

sccsfile(4).

cc(1), lex(1), yacc(1), cd(1), sh(1) в Справочнике

пользователя.

СЮРПРИЗЫ

Некоторые команды возвращают ненулевой код завершения и

после успешной работы; для преодоления этой трудности

используйте опцию -i.

Не допускаются файлы с символами =:@ в имени.

Команды, непосредственно выполняемые shell’ом, например

cd(1), нельзя продолжать на новую строку.

Если после слова include находится больше одного пробела, то make не сможет прочитать включаемый файл.

Макрос $(a:.o=.c~) не работает. Именованные фильтры

поддерживаются плохо.

Выражение $(LIB)(file1.o file2.o) синтаксически неверно. Нельзя построить lib(file.o) из file.o.

В текущей версии не распознается опция -u.

В текущей версии целевой файл не удаляется, если произошла ошибка. Специальное имя .PRECIOUS не работает.

Специальное имя .DEFAULT не работает.

Макросы $(@D), $(*D), $(<D) и $(%D) не вполне правильно

работают с подстановкой: подстановка производится не в

имя каталога, а в имя файла.

I have an rule that creates a directory

bin:
    -mkdir $@

However after the first time the directory has been generated, I receive this output:

mkdir bin
mkdir: cannot create directory `bin': File exists
make: [bin] Error 1 (ignored)

Is there some way I can only run the rule if the directory doesn’t exist, or suppress the output when the directory already exists?

asked Aug 13, 2010 at 13:46

Matt Joiner's user avatar

Matt JoinerMatt Joiner

113k110 gold badges377 silver badges526 bronze badges

1

Another way to suppress the make: error ... (ignored) output is to append || true to a command that could fail. Example with grep that checks for errors in a LaTeX log file:

undefined:
  @grep -i undefined *.log || true

Without the || true, make complains when grep fails to find any matches.

This works for all commands, not just mkdir; that’s why I added this answer.

answered Apr 16, 2012 at 8:17

daniel kullmann's user avatar

daniel kullmanndaniel kullmann

13.7k8 gold badges51 silver badges67 bronze badges

3

The error is ignored already by the leading ‘-‘ on the command line. If you really want to lose the error messages from mkdir, use I/O redirection:

bin:
    -mkdir bin 2> /dev/null

You will still get the ‘ignored’ warning from make, though, so it might be better to use the option to mkdir that doesn’t cause it to fail when the target already exists, which is the -p option:

MKDIR_P = mkdir -p

bin:
    ${MKDIR_P} $@

The -p option actually creates all the directories that are missing on the given paths, so it can generate a a number of directories in one invocation, but a side-effect is that it does not generate an error for already existing directories. This does assume a POSIX-ish implementation of mkdir; older machines may not support it (though it has been standard for a long time now).

answered Aug 13, 2010 at 13:57

Jonathan Leffler's user avatar

Jonathan LefflerJonathan Leffler

732k141 gold badges908 silver badges1279 bronze badges

2

The traditional way to handle directory creation is to use a stamp file that is depended on and creates the dir as a side effect. Remove the stamp file when making distclean or whatever your «really clean» target is:

bin/.dirstamp:
    mkdir -p $(DIRS)
    touch $@

bin/foo: bin/.dirstamp
    $(MKFOO) -o $@

distclean:
    rm -rf bin

The reason for this is as follows: whenever a file in bin is created/removed, the mtime of the containing directory is updated. If a target depends on bin, then the next time make runs, it will then recreate files that it doesn’t need to.

answered Aug 24, 2010 at 7:48

Jack Kelly's user avatar

2

Well I ended up with this construct, maybe someone will find it useful or can comment on it:

BINDIR = .
TMPDIR = tmp
OUTDIRS = $(BINDIR) $(TMPDIR)
$(OUTDIRS):
    @test -d $@ || mkdir $@

answered Aug 14, 2010 at 1:26

Matt Joiner's user avatar

Matt JoinerMatt Joiner

113k110 gold badges377 silver badges526 bronze badges

1

You rule should not be executed unless its target does not exists or is out of date because of its dependencies. In other words, you should never encounter this error.

[Example Added]

[max@truth tmp]$ ls -la
total 20
drwxr-xr-x.  2 max users 4096 Aug 14 21:11 .
drwx------. 80 max max   4096 Aug 14 18:25 ..
-rw-rw-r--   1 max max     38 Aug 14 21:11 Makefile
[max@truth tmp]$ cat Makefile 
.PHONY: all
all: bin

bin:
    mkdir $@

[max@truth tmp]$ make
mkdir bin
[max@truth tmp]$ ls -la
total 24
drwxr-xr-x.  3 max users 4096 Aug 14 21:11 .
drwx------. 80 max max   4096 Aug 14 18:25 ..
drwxrwxr-x   2 max max   4096 Aug 14 21:11 bin
-rw-rw-r--   1 max max     38 Aug 14 21:11 Makefile
[max@truth tmp]$ make
make: Nothing to be done for `all'.
[max@truth tmp]$ make
make: Nothing to be done for `all'.

Does your folder depend on anything? Is your folder a phony target?

answered Aug 13, 2010 at 14:12

Maxim Egorushkin's user avatar

Maxim EgorushkinMaxim Egorushkin

132k17 gold badges183 silver badges272 bronze badges

1

Make assumes the first target is the default target. If that is your complete makefile, then it must be always trying to remake the default target, which is bin. Insert the following lines to the top of your makefile:

all: bin
.PHONY: all

answered Aug 20, 2010 at 16:26

Maxim Egorushkin's user avatar

Maxim EgorushkinMaxim Egorushkin

132k17 gold badges183 silver badges272 bronze badges

I am trying to instruct GNU Make 3.81 to not stop if a command fails (so I prefix the command with -) but I also want to check the exit status on the next command and print a more informative message. However my Makefile below fails:

$ cat Makefile 
all:
    -/bin/false
    ([ $$? -eq 0 ] && echo "success!") || echo "failure!"
$
$ make
/bin/false
make: [all] Error 1 (ignored)
([ $? -eq 0 ] && echo "success!") || echo "failure!"
success!

Why does the Makefile above echo «success!» instead of «failure!» ?

update:

Following and expanding on the accepted answer, below is how it should be written:

failure:                                                                                                                                                                                                                                      
    @-/bin/false && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"                                                                                                                                                                 
success:                                                                                                                                                                                                                                      
    @-/bin/true && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"     

asked Sep 4, 2014 at 15:13

Marcus Junius Brutus's user avatar

3

Each update command in a Makefile rule is executed in a separate shell. So $? does not contain the exit status of the previous failed command, it contains whatever the default value is for $? in a new shell. That’s why your [ $? -eq 0 ] test always succeeds.

pevik's user avatar

pevik

1,39715 silver badges27 bronze badges

answered Sep 4, 2014 at 18:16

Kyle Jones's user avatar

Kyle JonesKyle Jones

14.9k3 gold badges40 silver badges51 bronze badges

You don’t need the test of $? since && works if $? is zero and || is proceed in case of a non-zero return value.

And you don’t need the minus since at the return value to make is taken from the last proceed program call of the line. So this works fine

failure:

      @/bin/false && echo "success!" || echo "failure!" 

success:

      @/bin/true && echo "success!" || echo "failure!"

The opposite happens: If you wanna do your own message and want to break the make process anyway with a non-zero value, you need to write something like this:

failure:

      @/bin/false && echo "success!" || { echo "failure!"; exit 1; }

Jeff Schaller's user avatar

Jeff Schaller

66.2k35 gold badges114 silver badges250 bronze badges

answered Feb 10, 2015 at 14:24

Andreas's user avatar

AndreasAndreas

1911 silver badge2 bronze badges

From the GNU make documentation:

When errors are to be ignored, because of either a ‘-’ or the ‘-i’ flag, make treats an error return just like success, except that it prints out a message that tells you the status code the shell exited with, and says that the error has been ignored.

To utilize make‘s exit status in a case like this, execute make from a script:

#!/bin/bash
make
([ $? -eq 0 ] && echo "success!") || echo "failure!"

And have your Makefile contain:

all:
    /bin/false

answered Sep 4, 2014 at 18:04

Timothy Martin's user avatar

Timothy MartinTimothy Martin

8,4771 gold badge35 silver badges40 bronze badges

Here is how I ended up doing it:

.PHONY: test-cleanup
test-cleanup:
    $(eval CLEANUP = echo "Some cleanup procedure")
    @/bin/true && touch _testok || $(CLEANUP) ;\
    if [ -f "_testok" ]; then \
        rm -f _testok ;\
        echo "What a success!" ;\
    else \
        echo "Failure :-(" ;\
        exit 1 ;\
    fi

Which prints:

What a success!

If you change /bin/true to /bin/false then you get the following output:

Some cleanup procedure
Failure :-(
make: *** [Makefile:4: test-cleanup] Error 1

answered Sep 8, 2022 at 15:13

Francesco Casula's user avatar

You must log in to answer this question.

Not the answer you’re looking for? Browse other questions tagged

.

Понравилась статья? Поделить с друзьями:

Интересное по теме:

  • Игра лови ошибку
  • Игра мафия ошибка 4214
  • Игра киберпанк 2077 прекратила работу ошибка на пиратке
  • Ивеко дейли ошибка 081 082
  • Ивеко траккер met ошибка что означает

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии