Wie kann ich eine Variable im laufenden Betrieb aus dem Makefile erstellen, deren Wert den gesamten Inhalt einer anderen Datendatei darstellt?
Antworten:
Ich vermute, dass Sie eine Variable in Ihrem Makefile auf den Inhalt einer anderen Datei setzen möchten:
FILE=test.txt
VARIABLE=`cat $(FILE)`
target:
echo $(VARIABLE)
VARIABLE
ist eine Zeichenfolge cat $(FILE)
(in Anführungszeichen), die nur in einem Rezept von der Shell erweitert wird. Versuchen Sie, den Wert wie folgt zu drucken $(info ${VARIABLE})
.
VARIABLE
als Versprechen betrachten. Dies ist die einzige Version, die mit älteren Versionen von funktioniert make
. Beide :=
und $(shell ...)
sind GNU-Erweiterungen.
cat
jedes Mal ausgeführt , wenn die Regel ausgeführt wird. Dies ist normalerweise nicht beabsichtigt und sollte gewarnt werden, da es langsam ist. Wenn die Datei eine Pipe ist, hat sie außerdem unbeabsichtigte Nebenwirkungen. Die Zuweisung sollte mit erfolgen, :=
damit die Regel nicht ausgewertet wird, wenn die Variable ersetzt wird, sondern wenn die Variable definiert wird. Der Ersetzungswert sollte $(shell cat $(FILE))
so sein, dass der cat
Befehl direkt von make ausgeführt wird, nicht später von den Rezeptregeln.
cat
eher auf komplexe als auf alternative Regeln verlassen, werden Ihre Makefiles viel einfacher zu verstehen und fast genauso portabel oder manchmal portabler.
Angenommen, GNU machen:
file := whatever.txt
variable := $(shell cat ${file})
GNU make Version 4.2 unterstützt das Lesen von Dateien. In Bezug auf Maxim Egorushkins großartige Antwort gibt es jetzt eine optionale Möglichkeit, dieses Problem zu lösen:
FILE := test.txt
variable :=$(file < $(FILE))
cat
existiert unter Windows nicht. Lösung, die für Linux und Windows funktioniert:
cat := $(if $(filter $(OS),Windows_NT),type,cat)
variable := $(shell $(cat) filename)
Erläuterung: Unter Windows scheint immer eine OS
Umgebungsvariable definiert zu sein, die gleich 'Windows_NT' ist. Auf diese Weise wird für Windows der type
Befehl für Nicht-Windows cat
verwendet.
Viel einfacher, da $(file op filename)
hinzugefügt wurde:
VARIABLE = $(file < my_file.txt)
Handbuchseite hier: https://www.gnu.org/software/make/manual/html_node/File-Function.html#index-file_002c-reading-from
Wenn Sie GNU make verwenden, können Sie diesen Effekt auch erzielen, indem Sie ein make "include" eines anderen Makefiles verwenden:
Aus dem Makefile:
include "./MyFile.mak"
Erstellen Sie eine Datei "MyFile.mak" mit Inhalt:
FILE := "my file content"
FILE += "more content 1"
FILE += "more content 2"
Makefile:1: "./MyFile.mak": No such file or directory
make -v
gibtGNU Make 3.81
include ./MyFile
Hier ist eine portablere Lösung, die mit MAKE
Version 3 funktioniert , für die file
keine Direktive verfügbar ist. Der Nachteil ist, dass dabei eine temporäre Datei erstellt werden muss.
$(shell echo define my_variable > file.tmp)
$(shell cat my_file.txt >> file.tmp)
$(shell echo endef >> file.tmp)
include file.tmp
Die Hauptidee ist die Verwendung einer define
Direktive, die speziell zum Deklarieren mehrzeiliger Variablen entwickelt wurde. Natürlich können Sie die Verwendung vermeidenshell
einer temporären Datei wenn Sie den Dateiinhalt explizit für die Verwendung von Makefile schreiben können.
Denken Sie daran, dass Ihre Datei, wenn sie $
Zeichen enthält , MAKE
versucht, diese als Variablen / Anweisungen zu my_variable
erweitern, wenn sie erweitert wird (oder wenn sie zugewiesen ist, von denen Sie sie definieren :=
). Wenn Sie dies vermeiden möchten, müssen Sie sie maskieren, bevor Sie Dateiinhalte einfügen. Zum Beispiel können Sie stattdessen cat
Folgendes tun:
$(shell sed 's/\$$/$$$$/g' my_file.txt >> file.tmp)