Является ли обычная Makefile idiom "> [email protected]" (перенаправление вывода на цель) неправильно?
Трудно поверить, но мне кажется, что обычная Makefile idiom " > [email protected]" неверна. В частности, у цели, у которой правило имеет команду, которая выходит из строя, но использует это перенаправление, не будет работать в первый раз, но не в последующие моменты времени. Это связано с тем, что, несмотря на неудачу команды, перенаправление "преуспевает" в смысле создания актуальной (хотя и нулевой) цели.
Мне кажется, что правильная вещь - перенаправить на временный и на успех переименовать это временное значение в цель.
Здесь и пример Makefile:
bad-target:
command-that-will-fail > [email protected]
good-target:
command-that-will-fail > [email protected] || ( rm [email protected]; false )
mv [email protected] [email protected]
clean:
rm -f bad-target good-target
И вот последовательность команд, иллюстрирующая проблему и ее решение:
$ make clean
rm -f bad-target good-target
$ make bad-target
command-that-will-fail > bad-target
/bin/sh: command-that-will-fail: not found
make: *** [bad-target] Error 127
$ make bad-target
make: `bad-target' is up to date.
$ make good-target
command-that-will-fail > good-target.tmp || ( rm good-target.tmp; false )
/bin/sh: command-that-will-fail: not found
make: *** [good-target] Error 1
$ make good-target
command-that-will-fail > good-target.tmp || ( rm good-target.tmp; false )
/bin/sh: command-that-will-fail: not found
make: *** [good-target] Error 1
Ответы
Ответ 1
Если вы используете GNU make, вы также можете добавить специальную цель .DELETE_ON_ERROR
в свой файл makefile. Это заставит make удалить выходной файл, если во время выполнения команд для этого файла есть ошибка:
all: foo.o
foo.o:
echo bogus! > [email protected]
exit 1
.DELETE_ON_ERROR:
Вот пример этого make файла в действии:
$ gmake
echo bogus! > foo.o
exit 1
gmake: *** [foo.o] Error 1
gmake: *** Deleting file `foo.o'
Это проще в использовании, чем ваша версия, так как вам не нужно изменять каждое правило в make файле.
Ответ 2
Возможно, это очевидное решение, но многие общие команды предоставляют флаг -o или аналогичный. Поэтому вместо перенаправления вывода вы должны использовать правило:
target: target.dep
some_command target.dep -o [email protected]
Если команда не удалась, выходной файл не будет создан. У меня не было много случаев использовать перенаправление вывода в make файлах.
Ответ 3
Да, это определенно нужно помнить.
Но иногда вы в порядке с неудачей команды, и вы не хотите повторять ее, потому что ошибка будет повторяться только.
В этом случае оставить пустой результат в порядке. Просто не делайте последующий подсчет обработки, если в этом файле есть содержательный контент.