Sim, você pode usar a palavra-chave define para declarar uma variável multilinha, como esta:
define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.
It can be downloaded from $(DOWNLOAD_URL).
etc, etc.
endef
A parte complicada é retirar sua variável multilinha do makefile. Se você apenas fizer a coisa óbvia de usar "echo $ (ANNOUNCE_BODY)", verá o resultado que outros postaram aqui - o shell tenta manipular a segunda linha e as subsequentes da variável como comandos próprios.
No entanto, você pode exportar o valor da variável no estado em que se encontra para o shell como uma variável de ambiente e, em seguida, referenciá-lo do shell como uma variável de ambiente (NÃO uma variável make). Por exemplo:
export ANNOUNCE_BODY
all:
@echo "$$ANNOUNCE_BODY"
Observe o uso de $$ANNOUNCE_BODY
, indicando uma referência de variável de ambiente do shell, em vez de $(ANNOUNCE_BODY)
, que seria uma referência regular de variável make. Além disso, certifique-se de usar aspas em torno de sua referência de variável, para garantir que as novas linhas não sejam interpretadas pelo próprio shell.
Claro, esse truque específico pode ser sensível à plataforma e ao shell. Eu testei no Ubuntu Linux com GNU bash 3.2.13; YMMV.
export ANNOUNCE_BODY
apenas define a variável dentro das regras - não permite fazer referência a $$ ANNOUNCE_BODY para definir outras variáveis.ANNOUNCE_BODY
em outras definições de variáveis, apenas faça referência a ele como qualquer outra variável make. Por exemploOTHER=The variable ANNOUNCE_BODY is $(ANNOUNCE_BODY)
,. Claro que você ainda precisará doexport
truque se quiserOTHER
sair em um comando.Outra abordagem para 'obter sua variável multilinhas de volta do makefile' (apontada por Eric Melski como 'a parte complicada'), é planejar o uso da
subst
função para substituir as novas linhas introduzidasdefine
em sua string multilinhas por\n
. Em seguida, use -e comecho
para interpretá-los. Pode ser necessário definir .SHELL = bash para obter um eco que faça isso.Uma vantagem dessa abordagem é que você também coloca outros caracteres de escape em seu texto e os respeita.
Este tipo de sintetiza todas as abordagens mencionadas até agora ...
Você acaba com:
Observe que as aspas simples no eco final são cruciais.
fonte
=
depoisdefine ANNOUNCE_BODY
para colocá-lo em execução.Supondo que você deseja apenas imprimir o conteúdo de sua variável na saída padrão, há outra solução:
fonte
make: 'do-echo' is up to date.
. Usando um comando "no op", fui capaz de silenciá-lo:@: $(info $(YOUR_MULTILINE_VAR))
.PHONY
para dizer ao seu Makefile que não há nada para verificar para essa regra. Makefiles eram originalmente para compiladores, se não me engano, entãomake
está fazendo alguma mágica que eu não entendo para antecipar que a regra não mudará nada e, como tal, assume que está 'pronto'. Adicionar.PHONY do-echo
em seu arquivo dirámake
para ignorar isso e executar o código de qualquer maneira.$(info ...)
fora de uma regra de criação. Ele ainda gerará saída.Sim. Você escapa das novas linhas com
\
:atualizar
Ah, você quer as novas linhas? Então não, eu não acho que haja nenhuma maneira de fazer baunilha. No entanto, você sempre pode usar um here-document na parte de comando
[Isso não funciona, veja o comentário de MadScientist]
fonte
Apenas um pós-escrito para a resposta de Eric Melski: Você pode incluir a saída de comandos no texto, mas deve usar a sintaxe Makefile "$ (shell foo)" ao invés da sintaxe shell "$ (foo)". Por exemplo:
fonte
Isso não fornece um documento here, mas exibe uma mensagem multilinha de uma forma adequada para canais.
=====
=====
Você também pode usar macros chamáveis do Gnu:
=====
=====
Aqui está o resultado:
=====
=====
fonte
Por que você não usa o caractere \ n em sua string para definir o fim da linha? Adicione também a barra invertida extra para adicioná-la em várias linhas.
fonte
$(subst \n ,\n,$(TEXT))
embora gostaria que houvesse uma maneira melhor!GNU `make 'manual, 6.8: Definindo Variáveis Multi-Line
fonte
echo
.Você deve usar a construção de Make "define / endef":
Então você deve passar o valor desta variável para o comando shell. Mas, se você fizer isso usando Fazer substituição de variável, o comando será dividido em vários:
Qouting também não vai ajudar.
A melhor maneira de passar valor é passá-lo por meio da variável de ambiente:
Aviso prévio:
fonte
No espírito de .ONESHELL, é possível chegar bem perto em ambientes desafiadores .ONESHELL:
Um exemplo de uso seria algo assim:
Isso mostra a saída (assumindo pid 27801):
Essa abordagem permite algumas funcionalidades extras:
Essas opções de shell irão:
Outras possibilidades interessantes provavelmente surgirão.
fonte
Eu gosto mais da resposta de Alhadis. Mas para manter a formatação colunar, adicione mais uma coisa.
Saídas:
fonte
make
, ele geralmente o faz esperando iniciar um processo de construção.Não totalmente relacionado ao OP, mas espero que isso ajude alguém no futuro. (visto que esta questão é a que mais surge nas buscas do google).
No meu Makefile, eu queria passar o conteúdo de um arquivo para um comando docker build, depois de muita consternação, decidi:
veja o exemplo abaixo.
nb: No meu caso particular, eu queria passar uma chave ssh, durante a construção da imagem, usando o exemplo de https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ (usando uma compilação docker de vários estágios para clonar um repo git e, em seguida, remova a chave ssh da imagem final no segundo estágio da compilação)
Makefile
Dockerfile
fonte
Com o GNU Make 3.82 e superior, a
.ONESHELL
opção é sua quando se trata de fragmentos de shell de várias linhas. Juntando dicas de outras respostas, eu obtenho:Certifique-se, ao copiar e colar o exemplo acima em seu editor, de que todos os
<tab>
caracteres sejam preservados, caso contrário, oversion
alvo será quebrado!Note que
.ONESHELL
fará com que todos os alvos no Makefile usem um único shell para todos os seus comandos.fonte
make version printf "Version 1.2.3 of foo-bar has been released. /bin/sh: 1: Syntax error: Unterminated quoted string make: *** [version] Error 2
(GNU make 3,81)@printf ...
instrução - parece que os TABs são sempre renderizados como 4 espaços ....ONESHELL
é novo na marca 3.82.*** missing separator. Stop.
.Não é realmente uma resposta útil, mas apenas para indicar que 'definir' não funciona como respondido por Ax (não cabia em um comentário):
Ele dá um erro que o comando 'It' não pode ser encontrado, então ele tenta interpretar a segunda linha de ANNOUNCE BODY como um comando.
fonte
Funcionou para mim:
fonte
GNU Makefile pode fazer coisas como o seguinte. É feio e não vou dizer que você deve fazer isso, mas eu faço em certas situações.
make .profile
cria um arquivo .profile se não houver um.Esta solução foi usada onde o aplicativo só usará GNU Makefile em um ambiente de shell POSIX. O projeto não é um projeto de código aberto onde a compatibilidade da plataforma é um problema.
O objetivo era criar um Makefile que facilitasse a configuração e o uso de um determinado tipo de espaço de trabalho. O Makefile traz consigo vários recursos simples sem exigir coisas como outro arquivo especial, etc. É, de certa forma, um arquivo de shell. Um procedimento pode então dizer coisas como soltar este Makefile na pasta para trabalhar. Configure sua área de trabalho
make workspace
, enter , então para blá, entermake blah
, etc.O que pode ser complicado é descobrir o que deve ser feito. O acima faz o trabalho e está próximo da idéia de especificar um documento here no Makefile. Se é uma boa ideia para uso geral é outra questão.
fonte
Acredito que a resposta mais segura para uso em várias plataformas seria usar um eco por linha:
Isso evita fazer suposições sobre a versão do echo disponível.
fonte
Use substituição de string :
Então, na sua receita, coloque
Isso funciona porque o Make está substituindo todas as ocorrências de
|
(observe o espaço) e trocando-o por um caractere de nova linha ($$'\n'
). Você pode pensar nas invocações de script de shell equivalentes como algo assim:Antes:
Depois de:
Não tenho certeza se
$'\n'
está disponível em sistemas não POSIX, mas se você pode obter acesso a um único caractere de nova linha (mesmo lendo uma string de um arquivo externo), o princípio subjacente é o mesmo.Se você tiver muitas mensagens como esta, pode reduzir o ruído usando uma macro :
Onde você o invocaria assim:
Espero que isso ajude alguém. =)
fonte
Como alternativa, você pode usar o comando printf. Isso é útil em OSX ou outras plataformas com menos recursos.
Para simplesmente enviar uma mensagem de várias linhas:
Se estiver tentando passar a string como um argumento para outro programa, você pode fazer assim:
fonte