Pouvez-vous créer des Makefiles valides sans tabulation?

114
target: dependencies
    command1
    command2

Sur mon système (Mac OS X), makesemble exiger que les Makefiles aient un caractère de tabulation précédant le contenu de chaque commandligne, ou cela lève une erreur de syntaxe.

C'est un inconvénient lors de la création ou de l'édition de Makefiles car mon éditeur est configuré pour être tout-espace-tout-le-temps.

Pouvez-vous créer des Makefiles valides sans tabulation?

xyz
la source
4
J'ai également configuré mon éditeur pour émuler des onglets avec des espaces. Mais, mon éditeur me permet également de taper Ctrl-Tab dans les rares occasions où je dois absolument, positivement avoir un onglet, comme dans Makefiles. Peut-être que votre éditeur le fait aussi.
toolic

Réponses:

118

C'est une bizarrerie / exigence de syntaxe make, cela n'a rien à voir avec Mac OS X. Malheureusement, vous ne pouvez rien y faire si vous comptez utiliser make.

Edit : GNU Make prend désormais en charge un préfixe de recette personnalisé. Voyez cette réponse .

Vous n'êtes pas le premier à ne pas aimer cet aspect make. Pour citer le manuel Unix Haters :

Le problème avec le Makefile de Dennis est que lorsqu'il a ajouté la ligne de commentaire, il a inséré par inadvertance un espace avant le caractère de tabulation au début de la ligne 2. Le caractère de tabulation est une partie très importante de la syntaxe de Makefiles. Toutes les lignes de commande (les lignes commençant par cc dans notre exemple) doivent commencer par des tabulations. Après avoir fait sa modification, la ligne 2 ne l'a pas fait, d'où l'erreur.

"Et alors?" vous demandez: "Qu'est-ce qui ne va pas avec ça?"

Il n'y a rien de mal à cela, en soi. C'est juste que lorsque vous considérez comment d'autres outils de programmation fonctionnent sous Unix, l'utilisation d'onglets dans le cadre de la syntaxe est comme l'un de ces pièges à pungee dans The Green Berets: le pauvre enfant du Kansas marche devant John Wayne et ne le fait pas. t voir le fil de déclenchement. Après tout, il n'y a pas de fils de déclenchement à surveiller dans les champs de maïs du Kansas. PAN!

Alok Singhal
la source
5
Le problème avec les onglets est l'une des premières choses que quiconque utilise make learns - je n'ai jamais trouvé que c'était un vrai problème.
2
@Neil, Moi non plus: je n'ai jamais dit que j'étais d'accord avec l'UHH, je disais juste que certaines personnes n'aiment pas ça. :-)
Alok Singhal
2
Semble être un bon plug pour utiliser cmake. Pas la seule bizarrerie frustrante dans la syntaxe de make.
orodbhen
3
Je viens de trouver gnu.org/software/make/manual/html_node/Special-Variables.html (voir .RECIPEPREFIX). L'une des réponses ci-dessous mentionne également cela et devrait être marquée comme «correcte» au lieu de la mienne. stackoverflow.com/a/21920142
Alok Singhal
3
Ce n'est pas un gros problème, mais c'est ennuyeux. A chaque fois. C'est ennuyeux de manière fiable, et c'est ennuyeux en temps linéaire \ omicron.
Tir parthe du
60

Depuis que cette question a été posée à l'origine, une version de GNU Make a été publiée qui vous permet d'utiliser autre chose que Tabcomme caractère de préfixe. À partir de l'annonce de la liste de diffusion :

Nouvelle variable spéciale: .RECIPEPREFIX vous permet de réinitialiser le caractère d'introduction de la recette par défaut (TAB) à autre chose. Le premier caractère de cette valeur de variable est le nouveau caractère d'introduction de recette. Si la variable est définie sur la chaîne vide, TAB est à nouveau utilisé. Il peut être réglé et réinitialisé à volonté; les recettes utiliseront la valeur active lors de leur première analyse. Pour détecter cette fonction, vérifiez la valeur de $ (. RECIPEPREFIX).

Cette fonctionnalité a été ajoutée dans GNU Make 3.82, sorti en juillet 2010 (six mois après la date de demande initiale de cette question). Comme cela fait à son tour trois ans et que cela change depuis, il est probable que d'autres saveurs Make aient suivi GNU Make.

Brighid McDonnell
la source
51

Il existe un moyen compliqué d'avoir un fichier Make valide sans onglets.

Si vous changez votre makefile pour lire:

target: dependencies; command1; command2

Si cela fonctionnera. Si vous le souhaitez sur plus d'une ligne, vous pouvez faire:

target: dependencies; \
command1; \
command2

Désordonné, mais ça marche.

George
la source
La mise à niveau vers une version de Make qui prend en charge .RECIPEPREFIXest probablement la meilleure approche. Cependant, comme je n'avais pas envie de faire ça, j'ai fini par utiliser une solution basée sur celle-ci. Ligne 1 target:\ ;command
LS
33

Si vous avez un vimrc dans votre profil, vous pouvez ajouter cette ligne pour empêcher vim de se transformer en espaces:

autocmd FileType make setlocal noexpandtab

Moi aussi, je luttais avec ça, et cela a résolu le problème pour moi. Passez le bon mot!

Pericolo
la source
19

Cela le fait pour moi si vous souhaitez utiliser des espaces

.RECIPEPREFIX +=

Exemple

Steven Penny
la source
Quelle version de make prend en charge cela? Cela ne fonctionne pas dans GNU Make 4.1.
Cerin
2
GNU Make 4.1 Construit pour x86_64-pc-linux-gnu je suis désolé mais ça marche
neok
probablement, il doit être mentionné, que cette variable doit être déclarée dans le fichier make lui-même (préfixant le point facile à ne pas repérer)
urusai_na
Au moins dans la version 4.2, cela devrait fonctionner. La documentation dit dans l'explication .RECIPEPREFIXque "Si la variable est vide (comme c'est le cas par défaut ), ce caractère est le caractère de tabulation standard." Cela signifie que la variable est définie par défaut. Il est confirmé en utilisant ifeq ($(origin .RECIPEPREFIX), undefined). Parce que +=ajouter un seul espace et les rhs aux lhs, var +=définit varun seul espace (plus une chaîne vide) aussi longtemps que cela vara déjà été défini. (Si varn'est pas défini, +=est le même que =.)
ynn
1
Cette réponse ne fonctionne plus. Voir ma réponse pour la dernière solution.
ynn le
11

En mode d'insertion de vim, on peut utiliser Ctrl-v <TAB>pour insérer une tabulation littérale, même si vous avez défini la touche de tabulation pour insérer des espaces. Cela ne répond pas à votre question, bien sûr, mais pourrait être une alternative aux méthodes disponibles pour éviter d'avoir besoin d'onglets littéraux.

Patrick Sanan
la source
10

Si vous utilisez EditorConfig , vous pouvez ajouter les lignes suivantes à votre .editorconfigfichier pour forcer votre IDE à utiliser tab pour l'indentation au lieu d'espaces dans Makefile:

[Makefile]
indent_style = tab
iver56
la source
4

Jusqu'à GNU Make 4.2

La réponse de Steven Penny fonctionne.

.RECIPEPREFIX +=

La raison pour laquelle cela fonctionne est décrite dans mon commentaire .


Depuis GNU Make 4.3 (publié le 19 janvier 2020)

Le comportement de l' +=opérateur a été modifié d'une manière rétrocompatible. Si l'opérande de gauche a une valeur vide, un espace n'est plus ajouté.

Vous pouvez à la place utiliser

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

, où <space>est un seul espace. Bien qu'il $(.RECIPEPREFIX)soit développé comme une valeur vide, cela est nécessaire pour ne pas laisser GNU Make ignorer<space> . Notez que ce code fonctionne même sur GNU Make antérieur à la version 4.3.

ynn
la source
1

dans ubuntu: vi Makefiles remplace l'espace par tabulation (ou tout ce que vous voulez):

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

Par ex, remplacez 8 espaces par tabulation:

:%s/        /^I/g

Attention: ^ j'insère avec la touche de tabulation, pas ^ et I caractères: D

nobjta_9x_tq
la source
-6

Pas transférable. Certaines versions de make nécessitent absolument des tabulations. Encore une autre raison de préférer les tabulations aux espaces :-)


la source