Многострочная команда Makefile не работает должным образом в Docker - PullRequest
0 голосов
/ 07 апреля 2019

Я пытаюсь скомпилировать HTML из Markdown. Мой makefile выглядит так:

MD = pandoc \
    --from markdown --standalone

# ...

$(MD_TARGETS):$(TARGET_DIR)/%.html: $(SOURCE_DIR)/%.md
    mkdir -p $(@D); \
    $(MD) --to html5 $< --output $@; \
    sed -i '' -e '/href="./s/\.md/\.html/g' $@

Когда я запускаю это на локальной машине, все работает.

Когда я запускаю то же самое в Docker, я получаю следующую ошибку:

mkdir -p /project/docs; \
pandoc --from markdown --standalone --to html5 /project/source/changelog.md --output /project/docs/changelog.html; \
sed -i '' -e '/href="./s/\.md/\.html/g' /project/docs/changelog.html
sed: can't read : No such file or directory
makefile:85: recipe for target '/project/docs/changelog.html' failed
make: *** [/project/docs/changelog.html] Error 2

Последующий вызов make выдает ту же ошибку, но с другим файлом:

sed: can't read : No such file or directory
makefile:85: recipe for target '/project/docs/todo.html' failed

Очевидно, что make каким-то образом пытается sed раньше, чем HTML. Но я использую многострочный синтаксис ; \ make, чтобы избежать использования subshell. Я тоже попробовал && \ но ни один из них не работает. Что мне делать?

1 Ответ

1 голос
/ 07 апреля 2019

К сожалению, вы были введены в заблуждение своим «очевидным» заключением Очевидно, что make каким-то образом пытается использовать sed раньше, чем HTML-код :) Это совсем не проблема. Внимательно просмотрите сообщение об ошибке:

sed: can't read : No such file or directory

Обратите внимание на can't read :; там должно быть имя файла. Это должно сказать что-то вроде can't read foobar:. Так ясно sed пытается прочитать файл с именем пустой строки. Вот строка, которую вы используете:

sed -i '' -e '/href="./s/\.md/\.html/g' /project/docs/changelog.html

Очевидным виновником здесь является аргумент пустой строки для -i. Страница man sed описывает параметр -i следующим образом:

   -i[SUFFIX], --in-place[=SUFFIX]

          edit files in place (makes backup if SUFFIX supplied)

Обратите внимание, что (a) SUFFIX является необязательным, и (b) между аргументом и его параметром нет пробела. В вашем примере вы добавили пробел, который заставляет sed полагать, что SUFFIX не был предоставлен, и обрабатывать следующий аргумент ('') как имя файла, с которым нужно работать.

Я не уверен, почему это работало, когда вы запускали его из командной строки: я должен предположить, что ваша версия командной строки не содержала пустую строку или в ней не было пробела между -i и ''.

Используйте одно из:

sed -i'' -e '/href="./s/\.md/\.html/g' $@

или

sed --in-place= -e '/href="./s/\.md/\.html/g' $@
...