Подтвердить что ты не робот

Является ли обычная 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
4b9b3361

Ответ 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

Да, это определенно нужно помнить.

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

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