¿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)
VARIABLEes 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}).
VARIABLEcomo una promesa. Esta es la única versión que funciona con versiones anteriores de make. Ambos :=y $(shell ...)son extensiones GNU.
catcada 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 catcomando se ejecute en el lugar por marca, no más tarde por las reglas de la receta.
catreglas 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))
catno 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 OSuna variable de entorno definida para ser igual a 'Windows_NT'. De esta manera, typese 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 -vdaGNU Make 3.81
include ./MyFile
Aquí hay una solución más portátil, que funciona con la MAKEversión 3, donde la filedirectiva 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 definedirectiva, que está específicamente diseñada para declarar variables de varias líneas. Por supuesto, puede evitar el uso de shellun 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, MAKEintentará expandirlos como variables / directivas cuando my_variablese 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 cathacer esto:
$(shell sed 's/\$$/$$$$/g' my_file.txt >> file.tmp)