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 wantmake
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 ifrm
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 позволяет поддерживать, изменять и регенерировать группы программ. Ниже приведено краткое описание всех опций и некоторых специальных имен:
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 поддерживает пять внутренних макросов, полезных при написании правил построения целевых файлов:
Четыре из этих макросов имеют альтернативную форму. Если к любому из этих макросов добавлено 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 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 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 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
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 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 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 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
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
1,39715 silver badges27 bronze badges
answered Sep 4, 2014 at 18:16
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♦
66.2k35 gold badges114 silver badges250 bronze badges
answered Feb 10, 2015 at 14:24
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 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
You must log in to answer this question.
Not the answer you’re looking for? Browse other questions tagged
.
Not the answer you’re looking for? Browse other questions tagged
.