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.

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)

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})

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))

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.



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"

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)

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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.