Est-il possible de créer un multi-ligne de chaîne variable dans un fichier Makefile
Je veux créer un fichier makefile variable qui est un multi-ligne de chaîne (par exemple, le corps d'un email annonce de publication). quelque chose comme
ANNOUNCE_BODY="
Version $(VERSION) of $(PACKAGE_NAME) has been released
It can be downloaded from $(DOWNLOAD_URL)
etc, etc"
Mais je n'arrive pas à trouver une façon de le faire. Est-il possible?
Vous devez vous connecter pour publier un commentaire.
Oui, vous pouvez utiliser le définir des mots clés pour déclarer un multi-ligne variable, comme ceci:
La partie la plus délicate est l'obtention de votre multi-ligne de la variable de retour de l'makefile. Si vous venez de faire la chose la plus évidente de l'utilisation de "echo $(ANNOUNCE_BODY)", vous verrez le résultat que les autres ont posté ici: le shell essaie de traiter la deuxième ligne et les lignes suivantes de la variable que les commandes elles-mêmes.
Toutefois, vous pouvez exporter la valeur de la variable en tant que-est de la carapace comme une variable d'environnement, puis de référence de la coquille comme une variable d'environnement (PAS une variable). Par exemple:
Notez l'utilisation de
$$ANNOUNCE_BODY
, indiquant un environnement shell variable de référence, plutôt que de$(ANNOUNCE_BODY)
, qui serait régulièrement faire référence à une variable. Assurez-vous également d'utiliser des guillemets autour de la variable de référence, afin de s'assurer que les retours à la ligne ne sont pas interprétés par le shell lui-même.Bien sûr, cette astuce peut être de la plateforme et de shell sensibles. Je l'ai testé sur Ubuntu Linux avec GNU bash 3.2.13; YMMV.
export ANNOUNCE_BODY
seulement définit la variable à l'intérieur des règles, il ne permet pas de référencement $$ANNOUNCE_BODY de définir d'autres variables.ANNOUNCE_BODY
dans d'autres définitions de variables, juste référence comme toute autre variable. Par exemple,OTHER=The variable ANNOUNCE_BODY is $(ANNOUNCE_BODY)
. Bien sûr, vous aurez toujours besoin de laexport
truc si vous voulez obtenirOTHER
dans une commande.Makefile.am
Une autre approche de l'obtention de votre multi-ligne de la variable de retour de l'makefile "(noté par Eric Melski comme " la partie la plus délicate), c'est planifier l'utilisation de l'
subst
fonction pour remplacer les retours à la ligne introduit avecdefine
dans votre multi-ligne de chaîne avec\n
. Ensuite, utilisez -e avececho
de les interpréter. Vous devrez peut-être régler le .=SHELL bash pour obtenir un écho qui fait cela.Un avantage de cette approche est que vous aussi vous mettre d'autres caractères d'échappement dans votre texte et de les faire respecter.
Ce genre de fait une synthèse de toutes les approches mentionnées jusqu'à présent...
Vous vous retrouvez avec:
Notez les guillemets simples sur la dernière écho sont cruciales.
=
aprèsdefine ANNOUNCE_BODY
pour le remettre en marche.En supposant que vous ne souhaitez imprimer le contenu de la variable sur la sortie standard, il y a une autre solution :
make: 'do-echo' is up to date.
. À l'aide d'un "non op" comand j'ai été capable de la faire taire:@: $(info $(YOUR_MULTILINE_VAR))
.PHONY
de dire à votre Makefile qu'il n'y a rien à vérifier que la règle. Les Makefiles étaient à l'origine pour les compilateurs, si je ne me trompe pas, doncmake
est en train de faire un peu de magie que je ne comprends pas à prévoir que la règle ne changera rien, et en tant que tels suppose qu'il est "terminé". L'ajout de.PHONY do-echo
dans votre fichier de diremake
de l'ignorer et d'exécuter le code de toute façon.Oui. De vous échapper de l'retours à la ligne avec
\
:mise à jour
Ah, vous voulez que les retours à la ligne? Alors non, je ne pense pas qu'il y a moyen de vanille. Cependant, vous pouvez toujours utiliser un ici-document dans la partie de commande
[Cela ne fonctionne pas, voir le commentaire de MadScientist]
Juste un post-scriptum à Eric Melski réponse: Vous pouvez inclure les sorties des commandes dans le texte, mais vous devez utiliser le Makefile de la syntaxe "$(shell foo)" plutôt que de la syntaxe shell "$(foo)". Par exemple:
Pourquoi ne pas utiliser le caractère \n dans votre chaîne de caractères pour définir la fin-de-ligne? Également ajouter de la barre oblique inverse supplémentaire à ajouter sur plusieurs lignes.
$(subst \n ,\n,$(TEXT))
même si je souhaite qu'il y ait une meilleure façon!GNU "faire" manuel, 6.8: Définition Multi-Variables en Ligne
echo
.Vous devez utiliser "définir/endef" Faire construire:
Vous devez passer la valeur de cette variable pour la commande du shell. Mais, si vous faites cela à l'aide de Faire de la substitution de variable, il sera la cause de commande divisé en plusieurs:
Qouting ne va pas aider non plus.
La meilleure façon de passer de la valeur est de passer par l'intermédiaire de la variable d'environnement:
Avis:
Avec GNU Make, le
.ONESHELL
option est votre ami quand il s'agit de plusieurs lignes de shell extraits. Mettre ensemble des conseils d'autres réponses, j'obtiens:Assurez-vous, lorsque vous copiez et collez l'exemple ci-dessus dans votre éditeur, que tout
<tab>
caractères sont conservés, le reste de laversion
cible rompre!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 ...
déclaration, il ressemble à Onglets sont toujours rendus que 4 places....ONESHELL
est nouveau dans 3.82.*** missing separator. Stop.
.Cela ne donne pas ici un document, mais il ne veut afficher un multi-ligne message d'une manière qui convient pour les tuyaux.
=====
=====
Vous pouvez également utiliser Gnu appelable macros:
=====
=====
Voici le résultat:
=====
=====
Dans l'esprit de .ONESHELL, il est possible d'obtenir assez proche de la .ONESHELL contesté environnements:
Un exemple d'utilisation serait quelque chose comme ceci:
Qui montre la sortie (en supposant pid 27801):
Cette approche ne permet pour certaines fonctionnalités supplémentaires:
Ces shell options:
D'autres possibilités intéressantes va probablement suggérer eux-mêmes.
J'aime alhadis la réponse de meilleur. Mais pour garder les colonnes mise en forme, ajouter une chose en plus.
Sorties:
make
, ils le font généralement attendre pour commencer un processus de construction.Pas totalement liés à l'OP, mais j'espère que cela va aider quelqu'un dans le futur.
(comme cette question est celle qui revient le plus dans les recherches google).
Dans mon Makefile, j'ai voulu passer le contenu d'un fichier, d'un panneau commande de construction,
après beaucoup de consternation, j'ai décidé de:
voir l'exemple ci-dessous.
nb: Dans mon cas particulier, je voulais transmettre une clé ssh, durant l'image de construire, en utilisant l'exemple de https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ (à l'aide d'un multi-stage docker construire pour cloner un repo git, puis jeter la clé ssh de l'image finale dans la 2e étape de la construction)
Makefile
Dockerfile
Pas vraiment une réponse utile, mais juste pour indiquer que "définir" ne fonctionne pas comme réponse à la Hache (ne rentre pas dans un commentaire):
Il donne une erreur que la commande 'Il' ne peut pas être trouvé, il tente d'interpréter la deuxième ligne d'ANNONCER CORPS comme une commande.
Il a travaillé pour moi:
GNU Makefile peut faire ce qui suit. Il est laid, et je ne dis pas que vous devriez le faire, mais je ne dans certaines situations.
make .profile
crée un .profil de fichier si il n'existe pas.Cette solution a été utilisée lorsque la demande sera uniquement l'utilisation de GNU Makefile dans un shell POSIX environnement. Le projet n'est pas un projet open source où compatibilité de plate-forme 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 de l'espace de travail. Le Makefile apporte avec elle les divers simple des ressources sans avoir besoin des choses comme une autre archive spéciale, etc. C'est, en un sens, une coquille d'archives. Une procédure peut alors dire des choses comme la chute de ce Makefile dans le dossier de travail. Configurez votre espace de travail entrer
make workspace
, puis à faire bla, entrezmake blah
, etc.Ce qui peut être délicat est de savoir ce que shell devis. Le ci-dessus ne fait le travail et est proche de l'idée de spécifier ici un document dans le fichier Makefile. Si c'est une bonne idée pour une utilisation générale est une toute autre question.
Je crois que la réponse la plus sûre pour la croix-plate-forme serait d'utiliser un echo par ligne:
Cela évite de faire toutes les hypothèses de la version de l'écho disponibles.
Utilisation substitution de chaîne:
Puis dans votre recette, mettre
Cela fonctionne parce que Faire est remplaçant toutes les occurrences de
|
(notez l'espace) et de la permutation avec un caractère de saut de ligne ($$'\n'
). Vous pouvez penser à l'équivalent shell-script invocations comme étant quelque chose comme ceci:Avant:
Après:
Je ne suis pas sûr si
$'\n'
est disponible sur la non-POSIX systèmes, mais si vous pouvez accéder à un seul caractère de saut de ligne (même par la lecture d'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 à l'aide d'un macro:
Où vous l'appeler comme ceci:
Espère que cela aide quelqu'un. =)
Comme alternative, vous pouvez utiliser la commande printf. C'est utile sur OSX ou d'autres plates-formes avec moins de fonctionnalités.
Simplement la sortie d'une multiligne message:
Si vous êtes en essayant de passer la chaîne d'un arg pour un autre programme, vous pouvez le faire comme ceci: