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


É 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 não posso usar svn:keywords como eu preciso do número de revisão fora do documento em questão.


4


origem




Respostas:


Isso não funciona porque o make A ferramenta 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 make para sempre usar um processo de shell para toda a receita, usando o .ONESHELL directiva:

    .ONESHELL:
    
    foo: bar baz
        line1
        line2
        line3
    

    Vejo info make "One Shell".

    (Note que enquanto .ONESHELL é recomendado pelo POSIX, nem todas as versões suportam; por exemplo. O BSD faz apenas um sinalizador de linha de comando para ele. Isso não deve ser um problema, no entanto.


6





Graças a https://stackoverflow.com/questions/6519234/cant-assign-variable-inside-recipe

Esta é a solução para alterar uma variável em uma receita:

recipe: 
        $(eval variablename=whatever)

3





De acordo com Gnu faz 6.5 configurações de variáveis:

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

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

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

1



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
Talvez o op possa definir a variável uma vez no nível superior de seu makefile então? : / - DavidPostill♦
Não, como você vê, eu preciso disso como parte da receita, já que o valor será diferente para arquivos diferentes. - Magnus


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)

0