Чи можете ви зробити дійсні Makefiles без символів табуляції?


114
target: dependencies
    command1
    command2

У моїй системі (Mac OS X), makeсхоже, потрібно, щоб у Makefiles був символ вкладки, що передує вмісту кожного commandрядка, або він видає синтаксичну помилку.

Це викликає роздратування під час створення чи редагування Makefiles, оскільки в мене редактор налаштований на всі простори.

Чи можете ви зробити дійсні Makefiles без символів табуляції?


4
Я також налаштував свій редактор для імітації вкладок пробілами. Але мій редактор також дозволяє мені вводити Ctrl-Tab у рідкісних випадках, коли я абсолютно позитивно повинен мати вкладку, як у Makefiles. Можливо, і ваш редактор.
інструментарій

Відповіді:


118

Це незвичайність / вимога синтаксису make, вона не має нічого спільного з Mac OS X. На жаль, ви нічого не можете з цим зробити, якщо ви збираєтесь використовувати make.

Редагувати : GNU Make now підтримує спеціальний префікс рецепта. Дивіться цю відповідь .

Ви не перший, хто не любить цей аспект make. Щоб цитувати посібник від Unix Haters :

Проблема з Makefile Makefile полягає в тому, що коли він додав рядок коментарів, він ненавмисно вставив пробіл перед символом вкладки на початку рядка 2. Символ вкладки є дуже важливою частиною синтаксису Makefiles. Усі командні рядки (рядки, що починаються з cc у нашому прикладі) повинні починатися з вкладок. Після внесення змін, рядок 2 не став, отже, помилка.

"І що?" ви запитуєте: "Що з цим не так?"

У цьому немає нічого поганого. Просто тоді, коли ви розглядаєте, як працюють інші інструменти програмування в Unix, використання вкладок як частини синтаксису - це як одна з тих пасток палки, що потрапляють у "Зелені берети": бідний хлопець із штату Канзас крокує навпроти Джона Уейна і не хоче " t бачити провідний провід. Зрештою, на кукурудзяних полях у штаті Канзас немає жодного проводу, який слідкувати. ЩО!


5
Проблема з вкладками - це одне з перших, про що дізнається хтось, хто користується, - я ніколи не вважав, що це справжня проблема.

2
@Neil, мені також: Я ніколи не говорив, що погоджуюся з UHH, я просто говорив, що деяким не подобається. :-)
Алок Сінгал

2
Схоже, хороший штекер для використання cmake. Не єдине дивовижне дивацтво в синтаксисі make.
інструбхен

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

Існує спільний спосіб мати дійсний makefile без вкладок.

Якщо ви зміните свій файл файлів на наступний:

target: dependencies; command1; command2

Якщо буде працювати. Якщо ви хочете, щоб це було більше, ніж один рядок, ви можете зробити:

target: dependencies; \
command1; \
command2

Брудний, але це працює.


Оновлення до версії Make, яка підтримує .RECIPEPREFIX, мабуть, найкращий підхід. Однак, оскільки мені цього не подобалося, я закінчив використовувати рішення, засноване на цьому. Рядок 1:, target:\ рядок 2: [відступ чотирьох пробілів], далі;command
LS

33

Якщо у вашому профілі є vimrc, ви можете додати цей рядок, щоб запобігти переходу vim на пробіли:

autocmd FileType make setlocal noexpandtab

Я теж боровся з цим, і це зафіксувало це для мене. Пошири доброго слова!


19

Це робиться для мене, якщо ви хочете використовувати пробіли

.RECIPEPREFIX +=

Приклад


Яка версія make підтримує це? У GNU Make 4.1 це не працює.
Серін

2
GNU Make 4.1 Built for x86_64-pc-linux-gnu Вибачте, але це працює
neok

напевно, потрібно згадати, що цю змінну потрібно оголосити всередині make file make (префіксація крапки легко не помітити)
urusai_na

Принаймні, у версії 4.2 це має працювати. Документація говорить у поясненні, .RECIPEPREFIXщо "Якщо змінна порожня (як це за замовчуванням ), цей символ є стандартним символом вкладки". Це означає, що змінна визначена за замовчуванням. Це підтверджується використанням ifeq ($(origin .RECIPEPREFIX), undefined). Оскільки +=додайте єдиний пробіл і rhs до lhs, var +=встановлюється varєдиний пробіл (плюс порожній рядок) до тих пір, як varце вже було визначено. (Якщо varне визначено, +=це те саме, що =).
Інь

1
Ця відповідь більше не працює. Дивіться мою відповідь щодо останнього рішення.
YNN

11

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


10

Якщо ви використовуєте EditorConfig , ви можете додати наступні рядки у .editorconfigфайл, щоб змусити ваш IDE використовувати вкладку для відступу замість пробілів у Makefile:

[Makefile]
indent_style = tab

4

До GNU Зробіть 4.2

Відповідь Стівена Пенні працює.

.RECIPEPREFIX +=

Причина, чому це працює, описана в моєму коментарі .


З моменту створення GNU Make 4.3 (випущена 19 січня 2020 року)

Поведінка +=оператора була змінена назад-несумісним способом. Якщо лівий операнд має порожнє значення, пробіл більше не додається.

Можна замість цього використовувати

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

, де <space>є єдиний простір. Хоча $(.RECIPEPREFIX)це розширено як порожнє значення, це потрібно, щоб GNU Make ігнорував <space>. Зауважте, що цей код працює навіть у GNU Make старше, ніж версія 4.3.


1

в ubuntu: vi Makefiles замінює простір на вкладку (або все, що завгодно):

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

Для заміни 8 пробілів на вкладку:

:%s/        /^I/g

Будьте уважні: ^ Я вставляю клавішу табуляції, а не ^ і I символи: D


-6

Не портативно. Для певних ароматів марки абсолютно потрібні символи табуляції Ще одна причина переваги вкладки над пробілами :-)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.