Czy możesz tworzyć poprawne pliki Makefile bez znaków tabulacji?

114
target: dependencies
    command1
    command2

W moim systemie (Mac OS X) makewydaje się wymagać, aby pliki Makefiles miały znak tabulacji poprzedzający zawartość każdego commandwiersza lub generuje błąd składni.

Jest to irytujące podczas tworzenia lub edytowania plików Makefile, ponieważ mój edytor jest ustawiony na cały czas.

Czy możesz tworzyć poprawne pliki Makefile bez znaków tabulacji?

xyz
źródło
4
Skonfigurowałem również mój edytor, aby emulował karty ze spacjami. Ale mój edytor pozwala mi również na wpisanie Ctrl-Tab w rzadkich przypadkach, kiedy absolutnie, pozytywnie muszę mieć kartę, jak w Makefiles. Być może twój redaktor też to robi.
narzędziowy

Odpowiedzi:

118

Jest to dziwactwo składniowe / wymaganie make, nie ma to nic wspólnego z Mac OS X. Niestety, jeśli zamierzasz używać, nic nie możesz z tym zrobić make.

Edycja : GNU Make obsługuje teraz przedrostek niestandardowej receptury. Zobacz tę odpowiedź .

Nie jesteś pierwszą osobą, której nie lubisz tego aspektu make. Cytując podręcznik uniksowych hejterów :

Problem z Makefile Dennisa polega na tym, że kiedy dodał wiersz komentarza, przypadkowo wstawił spację przed znakiem tabulatora na początku wiersza 2. Znak tabulacji jest bardzo ważną częścią składni Makefiles. Wszystkie wiersze poleceń (w naszym przykładzie linie zaczynające się od cc) muszą zaczynać się od tabulatorów. Po dokonaniu zmiany linia 2 nie, stąd błąd.

"Więc co?" pytasz: „Co w tym złego?”

Samo w sobie nie ma w tym nic złego. Chodzi tylko o to, że kiedy zastanawiasz się, jak inne narzędzia programistyczne działają w systemie Unix, używanie zakładek jako części składni jest jak jedna z tych pułapek na kij pungee w The Green Berets: biedny dzieciak z Kansas idzie punkt przed Johnem Wayne i nie robi nie widzę przewodu wyzwalającego. W końcu na polach kukurydzy w Kansas nie ma żadnych kabli, na które trzeba uważać. WHAM!

Alok Singhal
źródło
5
Problem z zakładkami jest jedną z pierwszych rzeczy, których uczy się ktoś, kto używa make - nigdy nie stwierdziłem, że jest to prawdziwy problem.
2
@Neil, ja też nie: nigdy nie powiedziałem, że zgadzam się z UHH, po prostu mówiłem, że niektórym to się nie podoba. :-)
Alok Singhal
2
Wygląda na dobrą wtyczkę do używania cmake. Nie jedyna frustrująca osobliwość w składni make.
orodbhen
3
Właśnie znalazłem gnu.org/software/make/manual/html_node/Special-Variables.html (patrz .RECIPEPREFIX). Jedna z poniższych odpowiedzi również o tym wspomina i powinna być oznaczona jako „prawidłowa” zamiast mojej. stackoverflow.com/a/21920142
Alok Singhal,
3
Nie jest to duży problem, ale jest denerwujący. Za każdym razem. Jest to niezawodnie denerwujące i denerwujące w liniowym czasie \ omicron.
Parthian Shot
60

Od czasu, gdy pierwotnie zadano to pytanie, została wydana wersja GNU Make, która pozwala na użycie czegoś innego niż Tabznak przedrostka. Z ogłoszenia listy mailingowej :

Nowa zmienna specjalna: .RECIPEPREFIX umożliwia zresetowanie znaku wprowadzenia receptury z domyślnego (TAB) na coś innego. Pierwszym znakiem wartości tej zmiennej jest znak wprowadzenia nowej receptury. Jeśli zmienna jest ustawiona na pusty łańcuch, ponownie używany jest klawisz TAB. Można go ustawiać i resetować w dowolnym momencie; receptury będą używały wartości aktywnej podczas pierwszego analizowania. Aby wykryć tę funkcję, sprawdź wartość $ (. RECIPEPREFIX).

Ta funkcja została dodana w GNU Make 3.82, wydanym w lipcu 2010 (sześć miesięcy po pierwotnej dacie zadania pytania). Ponieważ z kolei minęły trzy lata i od tego czasu się zmieniły, jest prawdopodobne, że inne smaki Make podążyły za GNU Make.

Brighid McDonnell
źródło
51

Istnieje skomplikowany sposób posiadania prawidłowego pliku makefile bez zakładek.

Jeśli zmienisz plik makefile na:

target: dependencies; command1; command2

Jeśli zadziała. Jeśli chcesz, aby był w więcej niż jednej linii, możesz zrobić:

target: dependencies; \
command1; \
command2

Niechlujne, ale działa.

Jerzy
źródło
Aktualizacja do obsługiwanej wersji programu Make .RECIPEPREFIXjest prawdopodobnie najlepszym podejściem. Jednak ponieważ nie miałem na to ochoty, ostatecznie skorzystałem z rozwiązania opartego na tym. Linia 1 target:\ :, Linia 2: [wcięcie z czterema spacjami], a następnie;command
LS
33

Jeśli masz vimrc w swoim profilu, możesz dodać tę linię, aby zapobiec zamianie vima na spacje:

autocmd FileType make setlocal noexpandtab

Ja też się z tym zmagałem i to naprawiło to dla mnie. Daj znać!

Pericolo
źródło
19

Robi to dla mnie, jeśli chcesz używać spacji

.RECIPEPREFIX +=

Przykład

Steven Penny
źródło
Która wersja marki to obsługuje? To nie działa w GNU Make 4.1.
Cerin
2
GNU Make 4.1 Zbudowany dla x86_64-pc-linux-gnu Przykro mi, ale działa
neok
Prawdopodobnie, musi wspomniano, że to musi być zmienne zadeklarowane wewnątrz samego (poprzedzając kropka łatwo nie dostrzec) pliku make
urusai_na
Przynajmniej w wersji 4.2 powinno to działać. Dokumentacja mówi w wyjaśnieniu, .RECIPEPREFIXże „Jeśli zmienna jest pusta (jak jest domyślnie ), ten znak jest standardowym znakiem tabulacji”. Oznacza to, że zmienna jest zdefiniowana domyślnie. Potwierdza się to za pomocą ifeq ($(origin .RECIPEPREFIX), undefined). Ponieważ +=dołączamy pojedynczą spację i prawa do lewej strony, var +=ustawia varsię na pojedynczą spację (plus pusty ciąg), o ile varzostał już zdefiniowany. (Jeśli varnie zdefiniowano, +=oznacza to samo, co =.)
dniu
1
Ta odpowiedź już nie działa. Zobacz moją odpowiedź na najnowsze rozwiązanie.
ynn
11

W trybie wstawiania vima, można użyć Ctrl-v <TAB>do wstawienia literału tabulacji, nawet jeśli ustawiłeś klawisz tabulacji na wstawianie spacji. To oczywiście nie odpowiada na twoje pytanie, ale może być alternatywą dla dostępnych metod, aby uniknąć konieczności stosowania dosłownych zakładek.

Patrick Sanan
źródło
10

Jeśli używasz EditorConfig , możesz dodać następujące wiersze do swojego .editorconfigpliku, aby wymusić na IDE użycie tabulatora zamiast spacji w Makefile:

[Makefile]
indent_style = tab
iver56
źródło
4

Aż do GNU Make 4.2.0

Odpowiedź Stevena Penny'ego działa.

.RECIPEPREFIX +=

Powód, dla którego to działa, jest opisany w moim komentarzu .


Od GNU Make 4.3 (wydany 19 stycznia 2020 r.)

Zachowanie +=operatora zostało zmienione w sposób niekompatybilny wstecz. Jeśli lewy operand ma pustą wartość, spacja nie jest już dodawana.

Możesz zamiast tego użyć

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

, gdzie <space>jest pojedyncza spacja. Chociaż $(.RECIPEPREFIX)jest interpretowany jako pusta wartość, jest to potrzebne, aby GNU Make nie ignorowało <space>. Zauważ, że ten kod działa nawet na GNU Make starszym niż wersja 4.3.

ynn
źródło
1

w ubuntu: vi Makefiles zamień spację na tabulator (lub cokolwiek innego):

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

Na przykład zastąp 8 spacji tabulatorem:

:%s/        /^I/g

Uwaga: ^ Wstawiam klawiszem tabulacji, a nie ^ i I znaki: D

nobjta_9x_tq
źródło
-6

Nie przenośnie. Niektóre smaki make absolutnie wymagają znaków tabulacji. Kolejny powód, dla którego warto przedkładać tabulatory nad spacje :-)


źródło