Как правильно экранировать данные для Makefile? - PullRequest
36 голосов
/ 05 октября 2011

Я динамически генерирую config.mk с помощью bash-скрипта, который будет использоваться Makefile. Файл построен с:

cat > config.mk <<CFG
SOMEVAR := $value_from_bash1
ANOTHER := $value_from_bash2
CFG

Как мне убедиться, что сгенерированный файл действительно содержит содержимое $value_from_bash*, а не что-то расширенное / интерпретированное? Возможно, мне нужно экранировать от $ до $$ и \ до \\, но есть ли другие символы, которые нужно экранировать? Возможно, есть специальное буквальное задание, о котором я не слышал?

Пробелы тоже кажутся неприятными:

$ ls -1
a b
a
$ cat Makefile
f := a b
default_target:
    echo "$(firstword $(wildcard ${f}))"
$ make
a

Если я использую f := a\ b, это работает (использование кавычек, таких как f := 'a b' тоже не сработало, makefile просто обрабатывает его как обычный символ)

Ответы [ 3 ]

52 голосов
/ 22 октября 2011

Ладно, оказалось, что Makefile-ы нуждаются в небольшом экранировании для себя, но команды, которые выполняются интерпретатором оболочки , требуют экранирования .

Символы, которые имеют особое значение в Makefile и должны быть экранированы:

  • Sharp (#, комментарий) становится \#
  • доллар ($, начало переменной) становится $$

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

Жаль, что саму обратную косую черту нельзя избежать (\\ все равно будет \\, а не \, как вы могли ожидать). Это не дает возможности поставить буквальную косую черту в конце строки, так как она будет либо есть символ новой строки, либо хэш следующего комментария. Пробел можно поставить в конце строки, но он также будет помещен и в саму переменную.

Сам рецепт интерпретируется как команда оболочки, без какой-либо изворотливой экранировки, так что вам нужно самим экранировать данные, просто представьте, что вы пишете сценарий оболочки и вставляете переменные из других файлов. Стратегия здесь заключалась бы в том, чтобы помещать переменные в одинарные кавычки и экранировать только ' с '\'' (закройте строку, вставьте литерал ' и начните новую строку). Пример: mornin' all становится 'morning'\'' all', что эквивалентно "morning' all".

Проблема firstword + wildcard вызвана тем, что имена файлов с пробелами в них firstword рассматриваются как отдельные имена файлов. Кроме того, wildcard расширяет экранирование, используя \, поэтому x\ y соответствует одному слову, x y, а не двум словам.

5 голосов
/ 24 ноября 2016

Кажется, что полный ответ на этот вопрос не найден нигде в интернете , поэтому я, наконец, сел и разобрался в случае с Windows.

В частности, «регистр Windows» относится к именам файлов, которые действительны в Windows, что означает, что они не содержат символы \, /, *, ?, ", ^, <, >, | или разрывы строк.Это также означает, что \ и / оба считаются допустимыми разделителями каталогов для целей Make.

Пример прояснит это лучше, чем я могу объяснить.По сути, если вы пытаетесь сопоставить путь к этому файлу:

Child\a$b  {'}(a.o#$@,&+=~`),[].c

Тогда вам нужно написать следующие правила:

all: Child\\a$$b\\\ \\\ {'}(a.o\#$$@,&+=~`),[].o

%.o: %.c
    $(CC) '$(subst ','"'"',$(subst \,,$(subst \\,/,$+)))'

Смотрите на него долгое время, и он будет сортироватьначать понимать что-то отдаленное.

Это работает в моей среде MSYS2, поэтому я предполагаю, что это правильно.

2 голосов
/ 05 октября 2011
  1. Я не понимаю, как этот make-файл может работать, как вы говорите.Шаблонное правило не может быть по умолчанию.
  2. Вам не хватает `$` в `$ (подстановочный знак ...)`, поэтому я думаю, что вы не опубликовали то, что действительно тестируете.
  3. Тебе тоже следует избегать перевода строки.
...