¿Cómo puedo crear una variable sobre la marcha a partir de un archivo MAKE, cuyo valor sería el contenido completo de otro archivo de datos?
Respuestas:
Supongo que le gusta establecer una variable en su Makefile al contenido de otro archivo:
FILE=test.txt
VARIABLE=`cat $(FILE)`
target:
echo $(VARIABLE)
VARIABLE
es una cadena cat $(FILE)
(entre comillas) que solo se expande en una receta por el shell. Intente imprimir el valor de la misma como $(info ${VARIABLE})
.
VARIABLE
como una promesa. Esta es la única versión que funciona con versiones anteriores de make
. Ambos :=
y $(shell ...)
son extensiones GNU.
cat
cada vez que se ejecute la regla. Por lo general, esto no es una intención y se debe advertir contra ello, porque es lento. Además, si el archivo es una tubería, tiene efectos secundarios no deseados. La asignación debe ser con :=
para que la regla no se evalúe cuando se reemplaza la variable sino cuando se define la variable. El valor de reemplazo debe ser $(shell cat $(FILE))
tal que el cat
comando se ejecute en el lugar por marca, no más tarde por las reglas de la receta.
cat
reglas alternativas en lugar de complejas hará que sus archivos MAKE sean mucho más simples de entender y casi tan portátiles o, a veces, más portátiles.
Suponiendo que GNU haga:
file := whatever.txt
variable := $(shell cat ${file})
GNU make versión 4.2 admite la operación de lectura de archivos, por lo que con respecto a la gran respuesta de Maxim Egorushkin , hay una forma opcional de resolver este problema ahora:
FILE := test.txt
variable :=$(file < $(FILE))
cat
no existe en Windows. Solución que funciona para Linux y Windows:
cat := $(if $(filter $(OS),Windows_NT),type,cat)
variable := $(shell $(cat) filename)
Explicación: Parece que en Windows siempre hay OS
una variable de entorno definida para ser igual a 'Windows_NT'. De esta manera, type
se usa el comando para Windows , para los que no son de Windows cat
.
Mucho más simple desde que $(file op filename)
se agregó:
VARIABLE = $(file < my_file.txt)
Página del manual aquí: https://www.gnu.org/software/make/manual/html_node/File-Function.html#index-file_002c-reading-from
Si está usando GNU make, otra forma de obtener este efecto es usar un make "include" de otro makefile:
Desde Makefile:
include "./MyFile.mak"
Cree un archivo "MyFile.mak" con contenido:
FILE := "my file content"
FILE += "more content 1"
FILE += "more content 2"
Makefile:1: "./MyFile.mak": No such file or directory
make -v
daGNU Make 3.81
include ./MyFile
Aquí hay una solución más portátil, que funciona con la MAKE
versión 3, donde la file
directiva no está disponible. La desventaja es que requiere crear un archivo temporal en el proceso.
$(shell echo define my_variable > file.tmp)
$(shell cat my_file.txt >> file.tmp)
$(shell echo endef >> file.tmp)
include file.tmp
La idea principal es utilizar la define
directiva, que está específicamente diseñada para declarar variables de varias líneas. Por supuesto, puede evitar el uso de shell
un archivo temporal y si puede escribir explícitamente el contenido del archivo para el uso de Makefile.
Tenga en cuenta que, si su archivo contiene $
signos, MAKE
intentará expandirlos como variables / directivas cuando my_variable
se expanda (o cuando se asigne, lo defina con :=
). Si desea evitarlo, debe escapar de ellos antes de incluir el contenido del archivo. Por ejemplo, en lugar de cat
hacer esto:
$(shell sed 's/\$$/$$$$/g' my_file.txt >> file.tmp)