Jak mogę utworzyć zmienną w locie z makefile, której wartością byłaby cała zawartość innego pliku danych.
Odpowiedzi:
Domyślam się, że chcesz ustawić zmienną w swoim Makefile na zawartość innego pliku:
FILE=test.txt
VARIABLE=`cat $(FILE)`
target:
echo $(VARIABLE)
VARIABLE
jest ciągiem znaków cat $(FILE)
(w cudzysłowach), który w przepisie jest interpretowany tylko przez powłokę. Spróbuj wydrukować jego wartość $(info ${VARIABLE})
.
VARIABLE
obietnicę. To jedyna wersja, która działa ze starszymi wersjami make
. Zarówno :=
i $(shell ...)
są rozszerzeniami GNU.
cat
każdym razem, gdy reguła zostanie wykonana. Zwykle nie jest to zamierzone i należy go ostrzec, ponieważ jest powolne. Poza tym, jeśli plik jest potokiem, ma niezamierzone efekty uboczne. Przypisanie powinno być z, :=
aby reguła nie była oceniana, gdy zmienna jest zastępowana, ale gdy zmienna jest zdefiniowana. Wartość zastępcza powinna być $(shell cat $(FILE))
taka, aby cat
polecenie było wykonywane w miejscu przez producenta, a nie później według reguł receptury.
cat
raczej na skomplikowanych regułach alternatywnych sprawi, że pliki makefile będą znacznie prostsze do zrozumienia i będą prawie tak przenośne, a czasem bardziej przenośne.
Zakładając, że marka GNU:
file := whatever.txt
variable := $(shell cat ${file})
GNU make w wersji 4.2 obsługuje operacje odczytu plików, więc w odniesieniu do świetnej odpowiedzi Maxima Egorushkina istnieje opcjonalny sposób rozwiązania tego problemu teraz:
FILE := test.txt
variable :=$(file < $(FILE))
cat
nie istnieje w systemie Windows. Rozwiązanie, które działa w systemach Linux i Windows:
cat := $(if $(filter $(OS),Windows_NT),type,cat)
variable := $(shell $(cat) filename)
Objaśnienie: Wygląda na to, że w systemie Windows zawsze OS
zdefiniowano zmienną środowiskową równą „Windows_NT”. W ten sposób dla systemu Windows type
używane jest polecenie, dla innych niż Windows cat
jest używane.
Znacznie prostsze, odkąd $(file op filename)
dodano:
VARIABLE = $(file < my_file.txt)
Strona podręcznika tutaj: https://www.gnu.org/software/make/manual/html_node/File-Function.html#index-file_002c-reading-from
Jeśli używasz programu GNU make, innym sposobem uzyskania tego efektu jest użycie make „include” innego pliku makefile:
Z Makefile:
include "./MyFile.mak"
Utwórz plik „MyFile.mak” z zawartością:
FILE := "my file content"
FILE += "more content 1"
FILE += "more content 2"
Makefile:1: "./MyFile.mak": No such file or directory
make -v
dajeGNU Make 3.81
include ./MyFile
Oto bardziej przenośne rozwiązanie, które działa z MAKE
wersją 3, w której file
dyrektywa nie jest dostępna. Wadą jest to, że wymaga utworzenia tymczasowego pliku w procesie.
$(shell echo define my_variable > file.tmp)
$(shell cat my_file.txt >> file.tmp)
$(shell echo endef >> file.tmp)
include file.tmp
Głównym pomysłem jest użycie define
dyrektywy, która jest specjalnie zaprojektowana do deklarowania zmiennych wielowierszowych. Oczywiście możesz uniknąć używania shell
i pliku tymczasowego, jeśli możesz jawnie zapisać zawartość pliku na użytek Makefile.
Pamiętaj, że jeśli twój plik zawiera $
znaki, MAKE
spróbuje rozwinąć je jako zmienne / dyrektywy, gdy my_variable
zostanie rozwinięty (lub gdy zostanie przypisany, zdefiniujesz go :=
). Jeśli chcesz tego uniknąć, musisz uciec przed dołączeniem zawartości pliku. Na przykład zamiast cat
ciebie możesz to zrobić:
$(shell sed 's/\$$/$$$$/g' my_file.txt >> file.tmp)