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)
VARIABLEjest 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}).
VARIABLEobietnicę. To jedyna wersja, która działa ze starszymi wersjami make. Zarówno :=i $(shell ...)są rozszerzeniami GNU.
catkaż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 catpolecenie było wykonywane w miejscu przez producenta, a nie później według reguł receptury.
catraczej 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))
catnie 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 OSzdefiniowano zmienną środowiskową równą „Windows_NT”. W ten sposób dla systemu Windows typeużywane jest polecenie, dla innych niż Windows catjest 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 -vdajeGNU Make 3.81
include ./MyFile
Oto bardziej przenośne rozwiązanie, które działa z MAKEwersją 3, w której filedyrektywa 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 definedyrektywy, która jest specjalnie zaprojektowana do deklarowania zmiennych wielowierszowych. Oczywiście możesz uniknąć używania shelli pliku tymczasowego, jeśli możesz jawnie zapisać zawartość pliku na użytek Makefile.
Pamiętaj, że jeśli twój plik zawiera $znaki, MAKEspróbuje rozwinąć je jako zmienne / dyrektywy, gdy my_variablezostanie 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 catciebie możesz to zrobić:
$(shell sed 's/\$$/$$$$/g' my_file.txt >> file.tmp)