Você pode fazer Makefiles válidos sem caracteres de tabulação?

114
target: dependencies
    command1
    command2

No meu sistema (Mac OS X), makeparece exigir que os Makefiles tenham um caractere de tabulação antes do conteúdo de cada commandlinha, ou ele gera um erro de sintaxe.

Isso é um aborrecimento ao criar ou editar Makefiles porque eu tenho meu editor configurado para ter todos os espaços o tempo todo.

Você pode fazer Makefiles válidos sem caracteres de tabulação?

xyz
fonte
4
Também configurei meu editor para emular guias com espaços. Mas meu editor também me permite digitar Ctrl-Tab nas raras ocasiões em que absolutamente, positivamente devo ter uma guia, como nos Makefiles. Talvez seu editor também tenha.
2010

Respostas:

118

Esta é uma peculiaridade / exigência de sintaxe make, não tem nada a ver com o Mac OS X. Infelizmente, não há nada que você possa fazer sobre isso se for usar make.

Editar : GNU Make agora suporta um prefixo de receita personalizado. Veja esta resposta .

Você não é o primeiro a não gostar desse aspecto make. Para citar o Unix Haters 'Handbook :

O problema com o Makefile de Dennis é que, ao adicionar a linha de comentário, ele inadvertidamente inseriu um espaço antes do caractere de tabulação no início da linha 2. O caractere de tabulação é uma parte muito importante da sintaxe dos Makefiles. Todas as linhas de comando (as linhas que começam com cc em nosso exemplo) devem começar com guias. Depois que ele fez a alteração, a linha 2 não o fez, daí o erro.

"E daí?" você pergunta: "O que há de errado com isso?"

Não há nada de errado com isso, por si só. É só que quando você considera como outras ferramentas de programação funcionam no Unix, usar guias como parte da sintaxe é como uma daquelas armadilhas de bastão em Os Boinas Verdes: o pobre garoto do Kansas está andando na frente de John Wayne e não t ver o fio da viagem. Afinal de contas, não há cabos de disparo a serem observados nos campos de milho do Kansas. WHAM!

Alok Singhal
fonte
5
O problema com as guias é uma das primeiras coisas que qualquer pessoa que usa make aprende - nunca achei que fosse um problema real.
2
@ Neil, nem eu: Eu nunca disse que concordava com o UHH, só estava dizendo que algumas pessoas não gostam. :-)
Alok Singhal
2
Parece um bom plugue para usar o cmake. Não a única excentricidade frustrante na sintaxe do make.
orodbhen
3
Acabei de encontrar gnu.org/software/make/manual/html_node/Special-Variables.html (consulte .RECIPEPREFIX). Uma das respostas abaixo também menciona isso, e deve ser marcada como "correta" em vez da minha. stackoverflow.com/a/21920142
Alok Singhal
3
Não é um grande problema, mas é irritante. Cada vez. É confiantemente irritante, e é irritante no tempo linear \ omicron.
Parthian Shot
60

Desde que esta pergunta foi feita originalmente, uma versão do GNU Make foi lançada que permite que você use algo diferente do Tabcaractere de prefixo. Do anúncio da lista de e-mails :

Nova variável especial: .RECIPEPREFIX permite que você redefina o caractere de introdução da receita do padrão (TAB) para outro. O primeiro caractere deste valor de variável é o caractere de introdução da nova receita. Se a variável for definida como uma string vazia, TAB é usado novamente. Ele pode ser definido e redefinido à vontade; as receitas usarão o valor ativo quando foram analisadas pela primeira vez. Para detectar esse recurso, verifique o valor de $ (. RECIPEPREFIX).

Este recurso foi adicionado no GNU Make 3.82, lançado em julho de 2010 (seis meses após a data original de venda desta pergunta). Como já se passaram três anos e mudanças desde então, é provável que outros sabores do Make tenham seguido o GNU Make.

Brighid McDonnell
fonte
51

Existe uma maneira complicada de ter um makefile válido sem guias.

Se você alterar seu makefile para ler:

target: dependencies; command1; command2

Se vai funcionar. Se quiser em mais de uma linha, você pode fazer:

target: dependencies; \
command1; \
command2

Confuso, mas funciona.

George
fonte
Atualizar para uma versão do Make que suporte .RECIPEPREFIXé provavelmente a melhor abordagem. Porém, como não tive vontade de fazer isso, acabei usando uma solução baseada nesta. Linha 1:, target:\ Linha 2: [recuo de quatro espaços] seguido por;command
LS
33

Se você tem um vimrc em seu perfil, pode adicionar esta linha para evitar que o vim mude para espaços:

autocmd FileType make setlocal noexpandtab

Eu também estava lutando com isso, e isso resolveu para mim. Espalhe a boa palavra!

Pericolo
fonte
19

Isso é suficiente para mim, se você quiser usar espaços

.RECIPEPREFIX +=

Exemplo

Steven Penny
fonte
Qual versão do make suporta isso? Isso não funciona no GNU Make 4.1.
Cerin
2
GNU Make 4.1 Construído para x86_64-pc-linux-gnu, sinto muito, mas funciona
neok
provavelmente, precisa ser mencionado, que esta variável precisa ser declarada dentro do próprio make file (prefixando ponto fácil de não detectar)
urusai_na
Pelo menos na versão 4.2, isso deve funcionar. A documentação diz na explicação de .RECIPEPREFIXque "Se a variável estiver vazia (como está por padrão ), esse caractere é o caractere de tabulação padrão." Isso significa que a variável é definida por padrão. É confirmado usando ifeq ($(origin .RECIPEPREFIX), undefined). Porque +=anexar um único espaço e o rhs ao lhs, var +=define varpara um único espaço (mais uma string vazia), desde que varjá tenha sido definido. (Se varnão estiver definido, +=é o mesmo que =.)
ynn
1
Esta resposta não funciona mais. Veja minha resposta para a solução mais recente.
janeiro
11

No modo de inserção do vim, pode-se usar Ctrl-v <TAB>para inserir uma tabulação literal, mesmo se você configurou a tecla tab para inserir espaços. Isso não responde à sua pergunta, é claro, mas pode ser uma alternativa aos métodos disponíveis para evitar a necessidade de guias literais.

Patrick Sanan
fonte
10

Se estiver usando o EditorConfig , você pode adicionar as seguintes linhas ao seu .editorconfigarquivo para forçar o IDE a usar tabulação para recuo em vez de espaços em Makefile:

[Makefile]
indent_style = tab
iver56
fonte
4

Até GNU Make 4.2

A resposta de Steven Penny funciona.

.RECIPEPREFIX +=

O motivo pelo qual isso funciona é descrito em meu comentário .


Desde GNU Make 4.3 (lançado em 19 de janeiro de 2020)

O comportamento do +=operador foi alterado de maneira incompatível com versões anteriores. Se o operando esquerdo tiver um valor vazio, um espaço não será mais adicionado.

Você pode usar

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

, onde <space>está um único espaço. Embora $(.RECIPEPREFIX)seja expandido como um valor vazio, isso é necessário para não permitir que o GNU Make ignore <space>. Observe que este código funciona até mesmo no GNU Make anterior à versão 4.3.

ynn
fonte
1

no ubuntu: vi Makefiles substitui espaço por tab (ou qualquer outra coisa que você quiser):

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

Por exemplo, substitua 8 espaços por tabulação:

:%s/        /^I/g

Atenção: ^ Eu insiro com a tecla tab, não ^ e I caracteres: D

nobjta_9x_tq
fonte
-6

Não portável. Certos sabores de make requerem absolutamente caracteres de tabulação. Mais uma razão para preferir tabulações a espaços :-)


fonte