Как правильно удалить данные для Makefile? - программирование

Как правильно удалить данные для Makefile?

Я динамически генерирую config.mk с помощью bash script, который будет использоваться 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 просто рассматривает его как обычный символ)

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

  • Я не вижу, как этот make файл может работать, как вы говорите. Правило шаблона не может быть значением по умолчанию.
  • Вам не хватает `$` в `$ (wildcard...)`, поэтому я думаю, что вы не опубликовали то, что вы действительно тестируете.
  • Вам также следует избегать новых строк.

Ответ 3

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

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

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

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

Затем вы должны написать эти правила:

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

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

Посмотрите на него в течение долгого времени, и это начнет делать какой-то отдаленный смысл.

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