Oui, vous pouvez utiliser le mot-clé define pour déclarer une variable multiligne, comme ceci:
define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.
It can be downloaded from $(DOWNLOAD_URL).
etc, etc.
endef
La partie délicate est de récupérer votre variable multiligne du makefile. Si vous faites simplement la chose évidente d'utiliser "echo $ (ANNOUNCE_BODY)", vous verrez le résultat que d'autres ont posté ici - le shell essaie de gérer la deuxième ligne et les suivantes de la variable comme des commandes.
Cependant, vous pouvez exporter la valeur de la variable telle quelle vers le shell en tant que variable d'environnement, puis la référencer depuis le shell en tant que variable d'environnement (PAS une variable de fabrication). Par exemple:
export ANNOUNCE_BODY
all:
@echo "$$ANNOUNCE_BODY"
Notez l'utilisation de $$ANNOUNCE_BODY
, indiquant une référence de variable d'environnement shell, plutôt que $(ANNOUNCE_BODY)
, qui serait une référence de variable make régulière. Veillez également à utiliser des guillemets autour de votre référence de variable, pour vous assurer que les retours à la ligne ne sont pas interprétés par le shell lui-même.
Bien sûr, cette astuce particulière peut être sensible à la plate-forme et au shell. Je l'ai testé sur Ubuntu Linux avec GNU bash 3.2.13; YMMV.
export ANNOUNCE_BODY
ne définit la variable que dans les règles - cela ne permet pas de référencer $$ ANNOUNCE_BODY pour définir d'autres variables.ANNOUNCE_BODY
dans d'autres définitions de variable, référencez-la simplement comme n'importe quelle autre variable make. Par exempleOTHER=The variable ANNOUNCE_BODY is $(ANNOUNCE_BODY)
,. Bien sûr, vous aurez toujours besoin de l'export
astuce si vous voulezOTHER
sortir dans une commande.Une autre approche pour «récupérer votre variable multiligne du makefile» (noté par Eric Melski comme «la partie délicate»), consiste à prévoir d'utiliser la
subst
fonction pour remplacer les nouvelles lignes introduites pardefine
dans votre chaîne multiligne par\n
. Utilisez ensuite -e avececho
pour les interpréter. Vous devrez peut-être définir le .SHELL = bash pour obtenir un écho qui fait cela.Un avantage de cette approche est que vous mettez également d'autres caractères d'échappement de ce type dans votre texte et que vous les faites respecter.
Ce genre de synthétise toutes les approches mentionnées jusqu'à présent ...
Vous vous retrouvez avec:
Notez que les guillemets simples sur l'écho final sont cruciaux.
la source
=
afterdefine ANNOUNCE_BODY
pour le faire fonctionner.En supposant que vous souhaitiez uniquement imprimer le contenu de votre variable sur la sortie standard, il existe une autre solution:
la source
make: 'do-echo' is up to date.
. En utilisant une commande "no op" j'ai pu le faire taire:@: $(info $(YOUR_MULTILINE_VAR))
.PHONY
pour dire à votre Makefile qu'il n'y a rien à vérifier pour cette règle. Les makefiles étaient à l'origine pour les compilateurs, si je ne me trompe pas,make
faire de la magie que je ne comprends pas pour prévoir que la règle ne changera rien, et en tant que tel suppose que cela est «fait». L'ajout.PHONY do-echo
de votre fichier vous diramake
d'ignorer cela et d'exécuter le code de toute façon.$(info ...)
dehors d'une règle de fabrication. Il générera toujours une sortie.Oui. Vous échappez aux nouvelles lignes avec
\
:mettre à jour
Ah, tu veux les nouvelles lignes? Alors non, je ne pense pas qu'il y ait moyen de faire vanille. Cependant, vous pouvez toujours utiliser un document ici dans la partie commande
[Cela ne fonctionne pas, voir le commentaire de MadScientist]
la source
Juste un post-scriptum à la réponse d'Eric Melski: Vous pouvez inclure la sortie des commandes dans le texte, mais vous devez utiliser la syntaxe Makefile "$ (shell foo)" plutôt que la syntaxe shell "$ (foo)". Par exemple:
la source
Cela ne donne pas de document ici, mais affiche un message sur plusieurs lignes d'une manière adaptée aux tuyaux.
=====
=====
Vous pouvez également utiliser les macros appelables de Gnu:
=====
=====
Voici le résultat:
=====
=====
la source
Pourquoi n'utilisez-vous pas le caractère \ n dans votre chaîne pour définir la fin de ligne? Ajoutez également la barre oblique inverse supplémentaire pour l'ajouter sur plusieurs lignes.
la source
$(subst \n ,\n,$(TEXT))
bien que j'aurais aimé qu'il y ait un meilleur moyen!Manuel GNU `make ', 6.8: Définition de variables multilignes
la source
echo
.Vous devez utiliser "define / endef" Make construct:
Ensuite, vous devez passer la valeur de cette variable à la commande shell. Mais, si vous faites cela en utilisant la substitution de variable, la commande se divisera en plusieurs:
Qouting n'aidera pas non plus.
La meilleure façon de transmettre une valeur est de la transmettre via la variable d'environnement:
Remarquer:
la source
Dans l'esprit du .ONESHELL, il est possible de se rapprocher assez près des environnements .ONESHELL contestés:
Un exemple d'utilisation serait quelque chose comme ceci:
Cela montre la sortie (en supposant pid 27801):
Cette approche permet certaines fonctionnalités supplémentaires:
Ces options de shell vont:
D'autres possibilités intéressantes se suggéreront probablement.
la source
J'aime mieux la réponse d'alhadis. Mais pour conserver le formatage en colonnes, ajoutez une dernière chose.
Les sorties:
la source
make
, il s'attend généralement à démarrer un processus de génération.Pas complètement lié au PO, mais j'espère que cela aidera quelqu'un à l'avenir. (car cette question est celle qui revient le plus dans les recherches Google).
Dans mon Makefile, je voulais passer le contenu d'un fichier, à une commande de construction de docker, après beaucoup de consternation, j'ai décidé de:
voir l'exemple ci-dessous.
nb: Dans mon cas particulier, je voulais passer une clé ssh, lors de la construction de l'image, en utilisant l'exemple de https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ (en utilisant une build de docker en plusieurs étapes pour cloner un repo git, puis déposez la clé ssh de l'image finale dans la 2ème étape de la construction)
Makefile
Dockerfile
la source
Avec GNU Make 3.82 et supérieur, l'
.ONESHELL
option est votre ami quand il s'agit d'extraits de shell multilignes. En rassemblant les indices d'autres réponses, j'obtiens:Assurez-vous, lorsque vous copiez et collez l'exemple ci-dessus dans votre éditeur, que tous les
<tab>
caractères sont conservés, sinon laversion
cible se cassera!Notez que
.ONESHELL
toutes les cibles du Makefile utiliseront un seul shell pour toutes leurs commandes.la source
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 ...
instruction - il semble que les tabulations soient toujours rendues sous forme de 4 espaces ....ONESHELL
soit nouveau dans la marque 3.82.*** missing separator. Stop.
.Pas vraiment une réponse utile, mais juste pour indiquer que `` définir '' ne fonctionne pas comme la réponse d'Axe (ne rentre pas dans un commentaire):
Cela donne une erreur indiquant que la commande «Il» ne peut pas être trouvée, donc il essaie d'interpréter la deuxième ligne de ANNOUNCE BODY comme une commande.
la source
Cela a fonctionné pour moi:
la source
GNU Makefile peut faire des choses comme ce qui suit. C'est moche, et je ne dirai pas que vous devriez le faire, mais je le fais dans certaines situations.
make .profile
crée un fichier .profile s'il n'en existe pas.Cette solution a été utilisée là où l'application utilisera uniquement GNU Makefile dans un environnement shell POSIX. Le projet n'est pas un projet open source où la compatibilité des plates-formes est un problème.
L'objectif était de créer un Makefile qui facilite à la fois la configuration et l'utilisation d'un type particulier d'espace de travail. Le Makefile apporte avec lui diverses ressources simples sans nécessiter des choses comme une autre archive spéciale, etc. C'est, en un sens, une archive shell. Une procédure peut alors dire des choses comme déposer ce Makefile dans le dossier pour travailler. Configurez votre espace de travail enter
make workspace
, puis pour faire bla, entermake blah
, etc.Ce qui peut être délicat, c'est de savoir quoi faire. Ce qui précède fait le travail et est proche de l'idée de spécifier un document ici dans le Makefile. Que ce soit une bonne idée pour une utilisation générale est une toute autre question.
la source
Je pense que la réponse la plus sûre pour une utilisation multiplateforme serait d'utiliser un écho par ligne:
Cela évite de faire des hypothèses sur la version de l'écho disponible.
la source
Utilisez la substitution de chaîne :
Puis dans votre recette, mettez
Cela fonctionne car Make remplace toutes les occurrences de
|
(notez l'espace) et le remplace par un caractère de nouvelle ligne ($$'\n'
). Vous pouvez penser aux invocations équivalentes de script shell comme étant quelque chose comme ceci:Avant:
Après:
Je ne sais pas si
$'\n'
est disponible sur les systèmes non POSIX, mais si vous pouvez accéder à un seul caractère de nouvelle ligne (même en lisant une chaîne à partir d'un fichier externe), le principe sous-jacent est le même.Si vous avez beaucoup de messages comme celui-ci, vous pouvez réduire le bruit en utilisant une macro :
Où vous l'invoqueriez comme ceci:
J'espère que cela aide quelqu'un. =)
la source
Vous pouvez également utiliser la commande printf. Ceci est utile sur OSX ou d'autres plates-formes avec moins de fonctionnalités.
Pour sortir simplement un message multiligne:
Si vous essayez de transmettre la chaîne comme argument à un autre programme, vous pouvez le faire comme ceci:
la source