Tak, możesz użyć słowa kluczowego define, aby zadeklarować zmienną wielowierszową, na przykład:
define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.
It can be downloaded from $(DOWNLOAD_URL).
etc, etc.
endef
Najtrudniejsze jest odzyskanie zmiennej wieloliniowej z pliku makefile. Jeśli po prostu zrobisz oczywistą rzecz, używając "echo $ (ANNOUNCE_BODY)", zobaczysz wynik, który inni opublikowali tutaj - powłoka próbuje obsłużyć drugą i kolejne linie zmiennej jako same polecenia.
Można jednak wyeksportować wartość zmiennej w niezmienionej postaci do powłoki jako zmienną środowiskową, a następnie odwołać się do niej z powłoki jako zmienną środowiskową (NIE zmienną make). Na przykład:
export ANNOUNCE_BODY
all:
@echo "$$ANNOUNCE_BODY"
Zwróć uwagę na użycie $$ANNOUNCE_BODY
, wskazując odwołanie do zmiennej środowiskowej powłoki, a nie $(ANNOUNCE_BODY)
, które byłoby zwykłym odwołaniem do zmiennej make. Upewnij się również, że używasz cudzysłowów wokół odniesienia do zmiennej, aby mieć pewność, że znaki nowej linii nie są interpretowane przez samą powłokę.
Oczywiście ta szczególna sztuczka może być wrażliwa na platformę i powłokę. Przetestowałem go na Ubuntu Linux z GNU bash 3.2.13; YMMV.
export ANNOUNCE_BODY
ustawia zmienną tylko w regułach - nie pozwala na odwoływanie się do $$ ANNOUNCE_BODY w celu zdefiniowania innych zmiennych.ANNOUNCE_BODY
w innych definicjach zmiennych, po prostu odwołaj się do niej jak do każdej innej zmiennej make. Na przykładOTHER=The variable ANNOUNCE_BODY is $(ANNOUNCE_BODY)
. Oczywiście nadal będziesz potrzebowaćexport
sztuczki, jeśli chcesz wyjśćOTHER
na komendę.Innym podejściem do „wyciągnięcia zmiennej wieloliniowej z powrotem z pliku makefile” (co Eric Melski zauważył jako „trudną część”) jest zaplanowanie użycia
subst
funkcji do zastąpienia nowych linii wprowadzonychdefine
w łańcuchu wielowierszowym przez\n
. Następnie użyj -e z,echo
aby je zinterpretować. Może być konieczne ustawienie .SHELL = bash, aby uzyskać echo, które to robi.Zaletą tego podejścia jest to, że umieszczasz w tekście również inne znaki ucieczki i szanujesz je.
Ten rodzaj syntetyzuje wszystkie wspomniane dotychczas podejścia ...
Skończysz z:
Zwróć uwagę, że kluczowe znaczenie mają pojedyncze cudzysłowy na ostatnim echu.
źródło
=
po,define ANNOUNCE_BODY
aby go uruchomić.Zakładając, że chcesz wydrukować zawartość zmiennej tylko na standardowym wyjściu, istnieje inne rozwiązanie:
źródło
make: 'do-echo' is up to date.
. Używając komendy „no op”, udało mi się ją uciszyć:@: $(info $(YOUR_MULTILINE_VAR))
.PHONY
do poinformowania swojego Makefile, że nie ma nic do sprawdzenia tej reguły. Pliki Makefile były pierwotnie dla kompilatorów, jeśli się nie mylę, więcmake
robię trochę magii, której nie rozumiem, aby przewidzieć, że reguła niczego nie zmieni i jako taka zakłada, że zostanie to „zrobione”. Dodanie.PHONY do-echo
do pliku powie,make
aby zignorować to i mimo to uruchomić kod.$(info ...)
poza regułą tworzenia. Nadal będzie generować dane wyjściowe.Tak. Uciekasz przed nowymi liniami za pomocą
\
:aktualizacja
Ach, chcesz nowe linie? Więc nie, nie sądzę, że w waniliowej marce jest jakiś sposób. Jednak zawsze możesz użyć dokumentu tutaj w części poleceń
[To nie działa, zobacz komentarz MadScientist]
źródło
Tylko dopisek do odpowiedzi Erica Melskiego: Możesz dołączyć wynik poleceń do tekstu, ale musisz użyć składni pliku Makefile „$ (shell foo)” zamiast składni powłoki „$ (foo)”. Na przykład:
źródło
To nie daje dokumentu tutaj, ale wyświetla wielowierszowy komunikat w sposób odpowiedni dla potoków.
=====
=====
Możesz także użyć wywoływanych makr Gnu:
=====
=====
Oto wynik:
=====
=====
źródło
Dlaczego nie użyjesz znaku \ n w swoim ciągu do zdefiniowania końca linii? Dodaj także dodatkowy ukośnik odwrotny, aby dodać go w wielu wierszach.
źródło
$(subst \n ,\n,$(TEXT))
chociaż chciałbym, żeby był lepszy sposób!Podręcznik GNU make, 6.8: Definiowanie zmiennych wieloliniowych
źródło
echo
.Powinieneś użyć konstrukcji „define / endef”:
Następnie należy przekazać wartość tej zmiennej do polecenia powłoki. Ale jeśli zrobisz to za pomocą podstawiania zmiennej Make, spowoduje to podzielenie polecenia na wiele:
Qouting też nie pomoże.
Najlepszym sposobem przekazania wartości jest przekazanie jej przez zmienną środowiskową:
Ogłoszenie:
źródło
W duchu .ONESHELL możliwe jest zbliżenie się do trudnych środowisk .ONESHELL:
Przykład użycia mógłby wyglądać następująco:
To pokazuje wynik (zakładając pid 27801):
Takie podejście pozwala na dodatkowe funkcje:
Te opcje powłoki:
Prawdopodobnie nasuną się inne interesujące możliwości.
źródło
Najbardziej podoba mi się odpowiedź Alhadisa. Ale aby zachować formatowanie kolumnowe, dodaj jeszcze jedną rzecz.
Wyjścia:
źródło
make
, zazwyczaj robi to, spodziewając się rozpoczęcia procesu kompilacji.Niezupełnie związane z PO, ale mam nadzieję, że pomoże to komuś w przyszłości. (ponieważ to pytanie pojawia się najczęściej w wyszukiwaniach Google).
W moim Makefile chciałem przekazać zawartość pliku do polecenia docker build, po wielu konsternacjach postanowiłem:
patrz przykład poniżej.
Uwaga: W moim przypadku chciałem przekazać klucz ssh podczas budowania obrazu, korzystając z przykładu z https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ (używając wieloetapowa kompilacja dockera w celu sklonowania repozytorium git, a następnie upuść klucz ssh z ostatecznego obrazu w drugim etapie kompilacji)
Makefile
Dockerfile
źródło
W przypadku GNU Make 3.82 i nowszych,
.ONESHELL
opcja ta jest twoim przyjacielem, jeśli chodzi o wielowierszowe fragmenty powłoki. Łącząc wskazówki z innych odpowiedzi, otrzymuję:Podczas kopiowania i wklejania powyższego przykładu do edytora upewnij się, że wszystkie
<tab>
znaki są zachowane, w przeciwnym razieversion
cel się zepsuje!Zwróć na to uwagę
.ONESHELL
spowoduje to, że wszystkie cele w Makefile będą używać jednej powłoki dla wszystkich swoich poleceń.źródło
make version printf "Version 1.2.3 of foo-bar has been released. /bin/sh: 1: Syntax error: Unterminated quoted string make: *** [version] Error 2
(GNU make 3,81)@printf ...
spacji , przed instrukcją - wygląda na to, że TAB są zawsze renderowane jako 4 spacje ....ONESHELL
to, że to nowość w make 3.82.*** missing separator. Stop.
.Niezbyt pomocna odpowiedź, ale wystarczy wskazać, że `` zdefiniuj '' nie działa tak, jak odpowiedział Ax (nie mieści się w komentarzu):
Daje błąd, że nie można znaleźć polecenia „To”, więc próbuje zinterpretować drugi wiersz ANNOUNCE BODY jako polecenie.
źródło
U mnie zadziałało:
źródło
GNU Makefile może wykonywać następujące czynności. Jest brzydki i nie powiem, że powinieneś to robić, ale robię to w pewnych sytuacjach.
make .profile
tworzy plik .profile, jeśli taki nie istnieje.To rozwiązanie zostało użyte, gdy aplikacja będzie używać GNU Makefile tylko w środowisku powłoki POSIX. Projekt nie jest projektem typu open source, w którym problemem jest kompatybilność platformy.
Celem było stworzenie pliku Makefile, który ułatwi zarówno konfigurację, jak i korzystanie z określonego rodzaju obszaru roboczego. Plik Makefile zawiera różne proste zasoby, nie wymagając takich rzeczy jak inne specjalne archiwum itp. Jest to w pewnym sensie archiwum powłoki. Procedura może wtedy powiedzieć takie rzeczy, jak upuszczenie tego pliku Makefile do folderu do pracy. Skonfiguruj obszar roboczy enter
make workspace
, a następnie wykonaj blah, entermake blah
itp.To, co może być trudne, to ustalenie, co zacytować. Powyższe spełnia swoje zadanie i jest bliskie idei określenia dokumentu w pliku Makefile. To, czy jest to dobry pomysł do ogólnego użytku, to zupełnie inna kwestia.
źródło
Uważam, że najbezpieczniejszą odpowiedzią w przypadku użycia na wielu platformach byłoby użycie jednego echa w wierszu:
Pozwala to uniknąć dokonywania jakichkolwiek założeń dotyczących dostępnej wersji echa.
źródło
Użyj zastępowania ciągów :
Następnie w swoim przepisie umieść
Działa to, ponieważ Make zastępuje wszystkie wystąpienia
|
(zwróć uwagę na spację) i zamienia je na znak nowej linii ($$'\n'
). Możesz myśleć o równoważnych wywołaniach skryptu powłoki jako o czymś takim:Przed:
Po:
Nie jestem pewien, czy
$'\n'
jest dostępny w systemach innych niż POSIX, ale jeśli możesz uzyskać dostęp do pojedynczego znaku nowej linii (nawet czytając ciąg z zewnętrznego pliku), podstawowa zasada jest taka sama.Jeśli masz wiele takich wiadomości, możesz zredukować szum za pomocą makra :
Gdzie można to wywołać w ten sposób:
Mam nadzieję, że to komuś pomoże. =)
źródło
Alternatywnie możesz użyć polecenia printf. Jest to przydatne na OSX lub innych platformach z mniejszą liczbą funkcji.
Aby po prostu wyświetlić wiadomość wielowierszową:
Jeśli próbujesz przekazać łańcuch jako argument do innego programu, możesz to zrobić w następujący sposób:
źródło