Variáveis ​​no GNU Crie receitas, isso é possível?


11

É possível ter variáveis ​​nas receitas do GNU Make?

Algo assim não funciona:

%_t.mkd : %.mkd
    REV=$$(svn info $<|grep 'Last Changed Rev'|cut -f4 -d\ )
    echo $${REV}

Existe alguma maneira de fazer esse trabalho?

Como você pode ver o que eu quero é extrair a revisão que um arquivo foi alterado e depois usá-lo mais tarde na receita completa. Infelizmente eu não posso usar svn:keywordscomo eu preciso do número de revisão fora do documento em questão.

Respostas:


7

Isso não funciona porque a makeferramenta inicia um novo processo de shell para cada linha de receita. E variáveis ​​de shell - mesmo variáveis ​​de ambiente 'exportadas' - não podem se propagar "para cima"; eles desaparecem assim que o processo do shell termina.

  • O método tradicional é unir as linhas de receita usando \no Makefile:

    foo: bar baz
        line1; \
        line2; \
        line3
    

    (Observe que os comandos devem ser separados usando ;ou &&, porque as barras invertidas também são passadas para o shell que faz a mesma junção de linhas.)

    Veja também info make "Splitting Lines"e info make "Splitting Recipe Lines"no manual GNU Make.

  • O outro método é dizer makepara usar sempre um processo de shell para toda a receita, usando a .ONESHELLdiretiva:

    .ONESHELL:
    
    foo: bar baz
        line1
        line2
        line3
    

    Veja info make "One Shell".

    (Observe que, embora .ONESHELLseja recomendado pelo POSIX, nem todas as versões do make o suportam ; por exemplo, o BSD faz apenas um sinalizador de linha de comando para ele. Isso não deve ser um problema.)



1

De acordo com o Gnu Make 6.5 Setting Variables :

O operador de atribuição de shell !=pode ser usado para executar um programa e definir uma variável para sua saída. Este operador primeiro avalia o lado direito e passa esse resultado para o shell para execução. Se o resultado da execução terminar em uma nova linha, essa nova linha será removida; todas as outras novas linhas são substituídas por espaços. A string resultante é então colocada na variável expandida recursivamente denominada.

Então você poderia tentar o seguinte (não testado):

REV != $$(svn info $<|grep 'Last Changed Rev'|cut -f4 -d\ ) \
echo $${REV}

2
Isso funcionaria no nível superior de um makefile, mas não no meio de uma receita (onde a sintaxe do shell é usada, não a sintaxe Make). Seria REV != svn info ...também.
Grawity

1
Talvez o op possa definir a variável uma vez no nível superior de seu makefile então? : /
DavidPostill

1
Não, como você vê, eu preciso disso como parte da receita, já que o valor será diferente para arquivos diferentes.
Magnus

0

pegando o que @ user3645902 mencionou, aqui está a solução para a questão principal:

recipe:
    @$(eval REV=`svn info $<|grep 'Last Changed Rev'|cut -f4 -d`)
    @echo $(REV)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.