У программиста в проекте был мейкфайл, в котором использовался perl-однострочник.
Makefile
:
# ...
templating:
perl -pe 's@/usr@$(PREFIX)@g if /$$prefix=/' templates/lib.pm.templ > $(DESTDIR)$(PERLLIBDIR)/Dh_Lib.pm
# ...
С этим однострочником в этом контексте есть по крайней мере одна серьезная проблема. А какие проблемы видите вы?
Если файла templates/lib.pm.templ
внезапно не окажется на месте –
сборка не остановится на цели templating
, и либо упадет где-то в неожиданном месте дальше,
либо вообще завершится успешно (по коду выхода).
Что напечатает следующая команда:
perl -pe 's/a/b/g' some-non-existent-file && echo SUCCESS
?
Can't open some-non-existent-file: No such file or directory.
SUCCESS
Неочевидной особенностью нашего однострочника является то, что даже если входного файла не существует – код возврата все равно 0, как если бы обработка прошла успешно. Соответственно, make продолжает работу дальше. В хорошем случае сборка упадет на следующих этапах (скорее всего, с весьма неожиданными ошибками), в плохом – сборка пройдет до конца, завершится с кодом 0, но пакет или дистрибутив, который собирается, будет с попорченным содержимым. В любом случае, happy debugging!
Что касается кода возврата однострочника – поведение вполне закономерное:
неуспешный Perl’овый open сам по себе не делает die,
в многострочных программах мы своими руками пишем open or die
(или используем autodie
).
Что же делать, чтобы отсутствие входного файла не оставалось незамеченным? Если хочется, чтобы при невозможности открыть файл сборка ломалась – лучше отдать открытие файлов shell’у. Сравните:
> perl -pe 's/q/j/g' nonexistent_file
Can't open nonexistent_file: No such file or directory.
> echo $?
0
> perl -pe 's/q/j/g' < nonexistent_file
zsh: no such file or directory: nonexistent_file
> echo $?
1
> sh -c 'perl -pe "s/q/j/g" < nonexistent_file'
sh: 1: cannot open nonexistent_file: No such file
> echo $?
2
Кстати, sed в этом отношении ведет себя хорошо, на несуществующем файле падает:
> sed 's/q/j/g' nonexistent_file
sed: can't read nonexistent_file: No such file or directory
> echo $?
2