Utwórz zmienną w pliku makefile, odczytując zawartość innego pliku

82

Jak mogę utworzyć zmienną w locie z makefile, której wartością byłaby cała zawartość innego pliku danych.

Srinath
źródło

Odpowiedzi:

49

Domyślam się, że chcesz ustawić zmienną w swoim Makefile na zawartość innego pliku:

FILE=test.txt
VARIABLE=`cat $(FILE)`

target:
    echo $(VARIABLE)
pokolenie bb
źródło
3
Właściwie nie mogę umieścić definicji VARIABLE przede wszystkim: ponieważ PATH_TO_MY_DATA_FILE nie istnieje, dopóki nie zostaną uruchomione niektóre polecenia w all: target. Alternatywnie, to, co zrobiłem, to to, że podzieliłem rzeczy na dwa pliki makefile (utworzyłem podmakę) i zadeklarowałem VARIABLE na górze podmarki i teraz działa jak urok.
Srinath,
26
To jest zła odpowiedź. Wartość 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}).
Maxim Egorushkin,
4
@MaximEgorushkin Nie jest źle. Musisz tylko wziąć pod uwagę VARIABLEobietnicę. To jedyna wersja, która działa ze starszymi wersjami make. Zarówno :=i $(shell ...)są rozszerzeniami GNU.
ceving
7
Głosowano w dół. Będzie to wykonywane za 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.
Christian Hujer
2
@antred, make jest częścią standardowego zestawu narzędzi UNIX / POSIX, który zawiera również cat. Jeśli zainstalujesz, to normalne jest zainstalowanie wszystkich innych podstawowych narzędzi i są bardzo rzadkie okoliczności, w których spowoduje to jakiekolwiek trudności. Poleganie 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.
Michael
82

Zakładając, że marka GNU:

file := whatever.txt
variable := $(shell cat ${file})
Maxim Egorushkin
źródło
4
@ceving Używa standardowej marki GNU. Marka Solaris jest aplikacją nieprzenośną.
Maxim Egorushkin
8
Marka Gnu nie jest ani standardowa, ani bardziej przenośna niż marka Solaris. „Popularne” to twoje słowo. Jeśli poważnie myślimy o przenośności i standardowej budowie, trzymaj się posix.
把 友情 留 在 无 盐
3
W tym przypadku wybrałbym "Popularny" - tworzenie innych niż GNU jest po prostu zbyt prymitywne. Jeśli zamierzasz nadal wspierać systemy operacyjne z lat 90., odpowiedzią @ bb-generation jest prawdopodobnie to, czego potrzebujesz (choć w wielu przypadkach spowoduje to kłopoty). We wszystkich innych przypadkach GNU Make jest albo łatwo dostępne, albo - co bardziej prawdopodobne - domyślne, więc proszę z niego korzystać.
Guss,
1
Marka GNU działa wszędzie, więc tak, jest znacznie bardziej przenośna niż jakakolwiek inna marka. „standard” może być subiektywny, przyznany.
MarcH,
28

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))
yurimz
źródło
Naprawiono błąd. W nazwach zmiennych jest rozróżniana wielkość liter. Nazwy „foo”, „FOO” i „Foo” odnoszą się do różnych zmiennych. ( gnu.org/software/make/manual/html_node/Using-Variables.html )
Yaroslav
cudzysłowy również nie są potrzebne, $ (plik <"$ (PLIK)") próbuje otworzyć "test.txt".
Cagney
16

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.

Pavel P.
źródło
4

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"
Bill Moore
źródło
to nie działa, dostajęMakefile:1: "./MyFile.mak": No such file or directory
knocte
to prawdopodobnie oznacza, że ​​używasz make ... lub naprawdę starej wersji GNU make ... spróbuj: "make -v"
Bill Moore
używając make w mac, nie jestem pewien, czy jest dołączony lub zainstalowany przez homebrew, make -vdajeGNU Make 3.81
knocte
czy upewniasz się, że przypadkowo nie przekonwertowałeś znaków TAB na znaki spacji w Makefile? Pod tym względem Make jest prawie denerwujący jak Python.
Bill Moore,
Uruchomiłem to na moim Macu, usuwając cytaty, np .: include ./MyFile
Charlie Tran,
3

Ponieważ platforma nie została określona, ​​wygląda to tak, jak działa na Solarisie:

VERSION:sh = cat VERSION

all:
        echo $(VERSION)
ceving
źródło
0

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)
Thunderbeef
źródło