Можете ли вы сделать действительные файлы Makefile без символов табуляции?

114
target: dependencies
    command1
    command2

В моей системе (Mac OS X), makeпохоже, требуется, чтобы в Makefiles был символ табуляции, предшествующий содержимому каждой commandстроки, или это вызывает синтаксическую ошибку.

Это неприятно при создании или редактировании файлов Makefile, потому что мой редактор настроен на постоянное использование всех пространств.

Можете ли вы сделать действительные файлы Makefile без символов табуляции?

хуг
источник
4
Я также настроил свой редактор для имитации вкладок с пробелами. Но мой редактор также позволяет мне нажимать Ctrl-Tab в тех редких случаях, когда у меня обязательно должна быть вкладка, как в Makefiles. Возможно, ваш редактор тоже.
toolic

Ответы:

118

Это странность / требование синтаксиса make, оно не имеет ничего общего с Mac OS X. К сожалению, вы ничего не можете с этим поделать, если собираетесь использовать make.

Изменить : GNU Make теперь поддерживает настраиваемый префикс рецепта. Смотрите этот ответ .

Вы не первый, кому не нравится этот аспект make. Процитируем Справочник ненавистников Unix :

Проблема с Makefile Денниса заключается в том, что когда он добавил строку комментария, он случайно вставил пробел перед символом табуляции в начале строки 2. Символ табуляции - очень важная часть синтаксиса Makefile. Все командные строки (в нашем примере строки, начинающиеся с cc) должны начинаться с табуляции. После того, как он внес изменения, строка 2 не изменилась, отсюда и ошибка.

"Ну и что?" вы спросите: "Что в этом плохого?"

Само по себе в этом нет ничего плохого. Просто, когда вы рассматриваете, как другие инструменты программирования работают в Unix, использование вкладок как части синтаксиса похоже на одну из ловушек в «Зеленых беретах»: бедняга из Канзаса идет впереди Джона Уэйна и не делает этого. не вижу растяжку. В конце концов, на кукурузных полях Канзаса нет растяжек, на которые нужно обращать внимание. БУМ!

Алок Сингхал
источник
5
Проблема с вкладками - одна из первых вещей, которую узнает каждый, кто использует make, - я никогда не считал это настоящей проблемой.
2
@Neil, я тоже: я никогда не говорил, что согласен с UHH, я просто говорил, что некоторым это не нравится. :-)
Алок Сингхал
2
Похоже, хороший плагин для использования cmake. Не единственная неприятная странность в синтаксисе make.
orodbhen
3
Я только что нашел gnu.org/software/make/manual/html_node/Special-Variables.html (см. .RECIPEPREFIX). В одном из ответов ниже также упоминается это, и его следует пометить как «правильный» вместо моего. stackoverflow.com/a/21920142
Алок Сингхал,
3
Это не большая проблема, но раздражает. Каждый раз. Это надежно раздражает, и это раздражает в \ omicron линейном времени.
Парфянский выстрел
60

За время, прошедшее после того, как этот вопрос был первоначально задан, была выпущена версия GNU Make, которая позволяет вам использовать что-то иное, кроме Tabсимвола префикса. Из объявления списка рассылки :

Новая специальная переменная: .RECIPEPREFIX позволяет вам сбросить символ введения рецепта со значения по умолчанию (TAB) на другое. Первый символ значения этой переменной - это символ введения нового рецепта. Если для переменной задана пустая строка, снова используется TAB. Его можно установить и сбросить по желанию; рецепты будут использовать значение, активное при первом анализе. Чтобы обнаружить эту функцию, проверьте значение $ (. RECIPEPREFIX).

Эта функция была добавлена ​​в GNU Make 3.82, выпущенном в июле 2010 года (через шесть месяцев после первоначальной даты запроса этого вопроса). Поскольку, в свою очередь, прошло три года и с тех пор произошли изменения, вполне вероятно, что другие разновидности Make последовали за GNU Make.

Бригид МакДоннелл
источник
51

Есть запутанный способ создать действующий make-файл без вкладок.

Если вы измените свой make-файл, чтобы он читал:

target: dependencies; command1; command2

Если будет работать. Если вы хотите, чтобы это было более чем в одной строке, вы можете:

target: dependencies; \
command1; \
command2

Грязно, но это работает.

Джордж
источник
Обновление до версии Make, которая поддерживает .RECIPEPREFIX, вероятно, лучший подход. Однако, поскольку мне не хотелось этого делать, я решил использовать решение, основанное на этом. Строка 1:, target:\ Строка 2: [отступ из четырех пробелов], за которым следует;command
LS
33

Если в вашем профиле есть vimrc, вы можете добавить эту строку, чтобы vim не заменялся пробелами:

autocmd FileType make setlocal noexpandtab

Я тоже боролся с этим, и это исправило это для меня. Распространите доброе слово!

Pericolo
источник
19

Это подходит для меня, если вы хотите использовать пробелы

.RECIPEPREFIX +=

пример

Стивен Пенни
источник
Какая версия make поддерживает это? Это не работает в GNU Make 4.1.
Cerin 02
2
GNU Make 4.1, созданный для x86_64-pc-linux-gnu, извините, но он работает
neok 04
вероятно, стоит упомянуть, что эту переменную нужно объявить внутри самого make-файла (точку с префиксом легко не заметить)
urusai_na 03
По крайней мере, в версии 4.2 это должно работать. В документации поясняется, .RECIPEPREFIXчто «Если переменная пуста (как по умолчанию ), то этот символ является стандартным символом табуляции». Это означает, что переменная определена по умолчанию. Это подтверждается использованием ifeq ($(origin .RECIPEPREFIX), undefined). Поскольку +=добавить один пробел и правую часть к левому, var +=устанавливается varодин пробел (плюс пустая строка), если varэто уже было определено. (Если varне определено, +=то же самое, что и =.)
ynn
1
Этот ответ больше не работает. См. Мой ответ о последнем решении.
ynn
11

В режиме вставки vim можно использовать Ctrl-v <TAB>буквальную табуляцию, даже если вы установили клавишу табуляции для вставки пробелов. Это, конечно, не отвечает на ваш вопрос, но может быть альтернативой доступным методам, позволяющим избежать необходимости буквальных вкладок.

Патрик Санан
источник
10

Если вы используете EditorConfig , вы можете добавить в свой .editorconfigфайл следующие строки, чтобы заставить вашу IDE использовать табуляцию для отступа вместо пробелов в Makefile:

[Makefile]
indent_style = tab
iver56
источник
4

До GNU Make 4.2

Ответ Стивена Пенни работает.

.RECIPEPREFIX +=

Причина, по которой это работает, описана в моем комментарии .


Начиная с GNU Make 4.3 (выпущен 19 января 2020 г.)

Поведение +=оператора изменено обратно несовместимым образом. Если левый операнд имеет пустое значение, пробел больше не добавляется.

Вместо этого вы можете использовать

.RECIPEPREFIX := $(.RECIPEPREFIX)<space>

, где <space>- одиночный пробел. Хотя $(.RECIPEPREFIX)оно раскрывается как пустое значение, это необходимо, чтобы GNU Make не игнорировал его <space>. Обратите внимание, что этот код работает даже в GNU Make старше версии 4.3.

ynn
источник
1

в ubuntu: vi Makefiles заменяют пробел табуляцией (или чем угодно еще):

:%s/<space chars>/^I/g

Например, замените 8 пробелов табуляцией:

:%s/        /^I/g

Обратите внимание: ^ Я вставляю с помощью клавиши табуляции, а не символов ^ и I : D

nobjta_9x_tq
источник
-6

Не переносимо. Некоторые разновидности make абсолютно требуют символов табуляции. Еще одна причина предпочесть табуляции пробелам :-)


источник