Трудно поверить, но мне кажется, что общая идиома Makefile "> $ @"неверно. В частности, цель, в правиле которой есть команда, которая не работает, но использует это перенаправление, потерпит неудачу в первый раз, но не в последующие разы. Это потому, что даже если команда терпит неудачу, перенаправление" успешно "в смысле создания актуальная (хотя и нулевой длины) цель.
Мне кажется, что правильнее всего сделать - это перенаправить на временную и в случае успеха переименовать эту временную цель в цель.
Вот и пример Makefile :
bad-target:
command-that-will-fail > $@
good-target:
command-that-will-fail > $@.tmp || ( rm $@.tmp; false )
mv $@.tmp $@
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
Если вы используете GNU make, вы также можете добавить в свой make-файл специальную цель .DELETE_ON_ERROR
. Это приведет к тому, что make удалит выходной файл, если во время выполнения команд для этого файла возникнет ошибка:
all: foo.o
foo.o:
echo bogus! > $@
exit 1
.DELETE_ON_ERROR:
Вот пример этого make-файла в действии:
$ gmake
echo bogus! > foo.o
exit 1
gmake: *** [foo.o] Error 1
gmake: *** Deleting file `foo.o'
Это проще в использовании, чем ваша версия, так как вам нужно не изменять каждое правило в make-файле.
Да, это определенно нужно иметь в виду.
Но иногда вас устраивает, что команда не удалась, и вы не хотите повторять ее, потому что ошибка будет только повторяться.
В этом случае можно оставить пустой результат. Просто не рассчитывайте на то, что последующая обработка будет содержать значимый контент в этом файле.