Sí, puede usar la palabra clave define para declarar una variable de varias líneas, como esta:
define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.
It can be downloaded from $(DOWNLOAD_URL).
etc, etc.
endef
La parte complicada es recuperar la variable de varias líneas del archivo MAKE. Si simplemente hace lo obvio de usar "echo $ (ANNOUNCE_BODY)", verá el resultado que otros han publicado aquí: el shell intenta manejar la segunda línea y las siguientes de la variable como comandos ellos mismos.
Sin embargo, puede exportar el valor de la variable tal cual al shell como una variable de entorno y luego hacer referencia a él desde el shell como una variable de entorno (NO una variable make). Por ejemplo:
export ANNOUNCE_BODY
all:
@echo "$$ANNOUNCE_BODY"
Tenga en cuenta el uso de $$ANNOUNCE_BODY
, que indica una referencia de variable de entorno de shell, en lugar de $(ANNOUNCE_BODY)
, que sería una referencia de variable make regular. También asegúrese de usar comillas alrededor de su referencia de variable, para asegurarse de que las líneas nuevas no sean interpretadas por el propio shell.
Por supuesto, este truco en particular puede ser sensible a la plataforma y al shell. Lo probé en Ubuntu Linux con GNU bash 3.2.13; YMMV.
export ANNOUNCE_BODY
solo establece la variable dentro de las reglas; no permite hacer referencia a $$ ANNOUNCE_BODY para definir otras variables.ANNOUNCE_BODY
en otras definiciones de variables, simplemente haga referencia a él como cualquier otra variable make. Por ejemploOTHER=The variable ANNOUNCE_BODY is $(ANNOUNCE_BODY)
,. Por supuesto, aún necesitará elexport
truco si quiereOTHER
salir en un comando.Otro enfoque para 'sacar su variable multilínea del archivo MAKE' (señalada por Eric Melski como 'la parte complicada'), es planificar el uso de la
subst
función para reemplazar las nuevas líneas introducidasdefine
en su cadena multilínea con\n
. Luego usa -e conecho
para interpretarlos. Es posible que deba configurar .SHELL = bash para obtener un eco que haga esto.Una ventaja de este enfoque es que también coloca otros caracteres de escape en su texto y los respeta.
Este tipo de sintetiza todos los enfoques mencionados hasta ahora ...
Terminas con:
Tenga en cuenta que las comillas simples en el eco final son cruciales.
fuente
=
despuésdefine ANNOUNCE_BODY
para que funcionara.Suponiendo que solo desea imprimir el contenido de su variable en la salida estándar, existe otra solución:
fuente
make: 'do-echo' is up to date.
. Al usar un comando "no op" y pude silenciarlo:@: $(info $(YOUR_MULTILINE_VAR))
.PHONY
para decirle a su Makefile que no hay nada que verificar para esa regla. Los Makefiles fueron originalmente para compiladores, si no me equivoco, tambiénmake
está haciendo algo de magia que no entiendo para anticipar que la regla no cambiará nada y, como tal, asume que está 'hecho'. Agregar.PHONY do-echo
su archivo le dirámake
que ignore esto y ejecute el código de todos modos.$(info ...)
fuera de una regla de marca. Seguirá generando salida.Si. Escapas de las nuevas líneas con
\
:actualizar
Ah, ¿quieres las nuevas líneas? Entonces no, no creo que haya ninguna forma en Vanilla Make. Sin embargo, siempre puede usar un documento aquí en la parte de comando
[Esto no funciona, vea el comentario de MadScientist]
fuente
Solo una posdata a la respuesta de Eric Melski: puede incluir la salida de los comandos en el texto, pero debe usar la sintaxis de Makefile "$ (shell foo)" en lugar de la sintaxis de shell "$ (foo)". Por ejemplo:
fuente
Esto no da un documento aquí, pero muestra un mensaje de varias líneas de una manera adecuada para tuberías.
=====
=====
También puede utilizar las macros invocables de Gnu:
=====
=====
Aquí está el resultado:
=====
=====
fuente
¿Por qué no utiliza el carácter \ n en su cadena para definir el final de la línea? También agregue la barra invertida adicional para agregarla en varias líneas.
fuente
$(subst \n ,\n,$(TEXT))
aunque desearía que hubiera una mejor manera!GNU `make 'manual, 6.8: Definición de variables multilínea
fuente
echo
.Deberías usar "definir / endef" Make construct:
Entonces debe pasar el valor de esta variable al comando de shell. Pero, si hace esto usando Hacer sustitución de variable, hará que el comando se divida en múltiples:
Qouting tampoco ayudará.
La mejor manera de pasar el valor es pasarlo a través de la variable de entorno:
Aviso:
fuente
En el espíritu de .ONESHELL, es posible acercarse bastante en entornos desafiados por .ONESHELL:
Un ejemplo de uso sería algo como esto:
Eso muestra la salida (asumiendo pid 27801):
Este enfoque permite algunas funciones adicionales:
Estas opciones de shell:
Es probable que surjan otras posibilidades interesantes.
fuente
Me gusta más la respuesta de alhadis. Pero para mantener el formato de columnas, agregue una cosa más.
Salidas:
fuente
make
, generalmente lo hace esperando comenzar un proceso de compilación.No está completamente relacionado con el OP, pero con suerte esto ayudará a alguien en el futuro. (ya que esta pregunta es la que más surge en las búsquedas de google).
En mi Makefile, quería pasar el contenido de un archivo a un comando de compilación de la ventana acoplable, después de mucha consternación, decidí:
vea el ejemplo a continuación.
nb: En mi caso particular, quería pasar una clave ssh, durante la construcción de la imagen, usando el ejemplo de https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ (usando una compilación de docker de múltiples etapas para clonar un repositorio de git, luego suelte la clave ssh de la imagen final en la segunda etapa de la compilación)
Makefile
Dockerfile
fuente
Con GNU Make 3.82 y superior, la
.ONESHELL
opción es su amiga cuando se trata de fragmentos de shell de varias líneas. Al juntar pistas de otras respuestas, obtengo:Al copiar y pegar el ejemplo anterior en su editor, asegúrese de que
<tab>
se conservan todos los caracteres; de lo contrario, elversion
objetivo se romperá.Tenga en cuenta que
.ONESHELL
hará que todos los destinos del Makefile usen un solo shell para todos sus comandos.fuente
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 ...
declaración; parece que las TAB siempre se representan como 4 espacios ....ONESHELL
es nuevo en make 3.82.*** missing separator. Stop.
.No es realmente una respuesta útil, pero solo para indicar que 'definir' no funciona como respondió Axe (no encajaba en un comentario):
Da un error de que no se puede encontrar el comando 'It', por lo que intenta interpretar la segunda línea de ANNOUNCE BODY como un comando.
fuente
Funcionó para mí:
fuente
GNU Makefile puede hacer cosas como las siguientes. Es feo y no diré que debas hacerlo, pero lo hago en ciertas situaciones.
make .profile
crea un archivo .profile si no existe.Esta solución se usó donde la aplicación solo usará GNU Makefile en un entorno de shell POSIX. El proyecto no es un proyecto de código abierto donde la compatibilidad de la plataforma es un problema.
El objetivo era crear un Makefile que facilitara tanto la configuración como el uso de un tipo particular de espacio de trabajo. El Makefile trae consigo varios recursos simples sin requerir cosas como otro archivo especial, etc. Es, en cierto sentido, un archivo de shell. Luego, un procedimiento puede decir cosas como colocar este Makefile en la carpeta para trabajar. Configure su espacio de trabajo
make workspace
, ingrese , luego haga bla, ingresemake blah
, etc.Lo que puede resultar complicado es averiguar qué cotizar. Lo anterior hace el trabajo y se acerca a la idea de especificar un documento aquí en el Makefile. Si es una buena idea para uso general es otra cuestión.
fuente
Creo que la respuesta más segura para el uso multiplataforma sería usar un eco por línea:
Esto evita hacer suposiciones sobre la versión de echo disponible.
fuente
Utilice la sustitución de cadenas :
Luego, en tu receta, pon
Esto funciona porque Make está sustituyendo todas las apariciones de
|
(observe el espacio) y lo intercambia con un carácter de nueva línea ($$'\n'
). Puede pensar en las invocaciones de script de shell equivalentes como algo como esto:Antes de:
Después:
No estoy seguro de si
$'\n'
está disponible en sistemas que no son POSIX, pero si puede obtener acceso a un solo carácter de nueva línea (incluso leyendo una cadena de un archivo externo), el principio subyacente es el mismo.Si tiene muchos mensajes como este, puede reducir el ruido utilizando un macro :
Donde lo invocarías así:
Espero que esto ayude a alguien. =)
fuente
Como alternativa, puede utilizar el comando printf. Esto es útil en OSX u otras plataformas con menos funciones.
Para simplemente generar un mensaje de varias líneas:
Si está intentando pasar la cadena como un argumento a otro programa, puede hacerlo así:
fuente