W pliku Makefile deploy
reguła wymaga ustawienia zmiennej środowiskowej, ENV
aby poprawnie się wykonywała, podczas gdy innych to nie obchodzi, np .:
ENV =
.PHONY: deploy hello
deploy:
rsync . $(ENV).example.com:/var/www/myapp/
hello:
echo "I don't care about ENV, just saying hello!"
Jak mogę się upewnić, że ta zmienna jest ustawiona, np .: czy istnieje sposób na zadeklarowanie tej zmiennej makefile jako warunku wstępnego reguły wdrażania, na przykład:
deploy: make-sure-ENV-variable-is-set
?
Dziękuję Ci.
make
go ustawić, ostrzegać lub generować błąd krytyczny?make ENV=dev
ale jeśli zapomniENV=dev
,deploy
przepis się nie powiedzie ...Odpowiedzi:
Spowoduje to fatalny błąd, jeśli
ENV
jest niezdefiniowany i coś tego potrzebuje (w każdym razie w GNUMake).(Zauważ, że ifndef i endif nie są wcięte - kontrolują to, co sprawia, że "widzi" , działając przed uruchomieniem pliku Makefile. "$ (Błąd" jest wcięty za pomocą tabulatora, więc działa tylko w kontekście reguły).
źródło
ENV is undefined
podczas uruchamiania zadania, które nie ma warunku wstępnego check-env.check-env
regule; Make nie rozwinie tego, chyba że / do czasu wykonania reguły. Jeśli nie zaczyna się od TAB (jak w przykładzie @ rane), Make interpretuje go jako nie będącego w regule i ocenia go przed uruchomieniem jakiejkolwiek reguły, niezależnie od celu.Możesz utworzyć niejawny cel ochronny, który sprawdza, czy zmienna w rdzeniu jest zdefiniowana, na przykład:
Następnie dodajesz
guard-ENVVAR
cel w dowolnym miejscu, w którym chcesz potwierdzić, że zmienna jest zdefiniowana, na przykład:Jeśli zadzwonisz
make change-hostname
bez dodawaniaHOSTNAME=somehostname
wywołania, pojawi się błąd, a kompilacja się nie powiedzie.źródło
if [ -z '${${*}}' ]; then echo 'Environment variable $* not set' && exit 1; fi
Wariant Inline
W moich plikach makefile zwykle używam wyrażenia takiego jak:
Powody:
Nie zapomnij komentarza, który jest ważny przy debugowaniu:
... zmusza cię do wyszukania Makefile podczas ...
... wyjaśnia bezpośrednio, co się stało
Wariant globalny (dla kompletności, ale bez pytania)
Oprócz pliku Makefile możesz również napisać:
Ostrzeżenia:
clean
cel nie powiedzie się, jeśli ENV nie jest ustawiony. W przeciwnym razie zobacz odpowiedź Hudona, która jest bardziej złożonaźródło
@
. -> gnu.org/software/make/manual/make.html#Echoing@test -n "$(name)" || (echo 'A name must be defined for the backup. Ex: make backup name=xyz' && exit 1)
Jednym z możliwych problemów z dotychczas udzielonymi odpowiedziami jest to, że kolejność zależności w make nie jest zdefiniowana. Na przykład bieganie:
when
target
ma kilka zależności, nie gwarantuje, że będą one działać w dowolnej kolejności.Rozwiązaniem tego problemu (aby zagwarantować, że ENV zostanie sprawdzone przed wybraniem receptury) jest sprawdzenie ENV podczas pierwszego przejścia marki, poza jakąkolwiek recepturą:
Możesz przeczytać o różnych funkcjach / zmiennych używanych tutaj i
$()
jest to tylko sposób na wyraźne stwierdzenie, że porównujemy z „niczym”.źródło
Uważam, że z najlepszą odpowiedzią nie można użyć jako wymagania, z wyjątkiem innych celów PHONY. Jeśli jest używany jako zależność dla celu, który jest rzeczywistym plikiem, użycie
check-env
wymusi odbudowanie tego celu pliku.Inne odpowiedzi są globalne (np. Zmienna jest wymagana dla wszystkich celów w Makefile) lub używają powłoki, np. Gdyby brakowało ENV, make zakończy działanie niezależnie od celu.
Rozwiązaniem obu problemów, które znalazłem, jest
Wynik wygląda jak
value
ma kilka przerażających zastrzeżeń, ale w przypadku tego prostego zastosowania uważam, że jest to najlepszy wybór.źródło
Jak widzę, samo polecenie potrzebuje zmiennej ENV, więc możesz to sprawdzić w samym poleceniu:
źródło
deploy
niekoniecznie jest to jedyny przepis, który wymaga tej zmiennej. Przy takim rozwiązaniu muszę przetestować stanENV
każdego z nich ... podczas gdy chciałbym traktować to jako jeden (rodzaj) warunek wstępny.Wiem, że to jest stare, ale pomyślałem, że wtrącę się z własnymi doświadczeniami dla przyszłych gości, ponieważ jest trochę schludniejszy IMHO.
Zwykle
make
użyjesh
powłoki domyślnej ( ustawianej przez specjalnąSHELL
zmienną ). Wsh
i jego pochodne, to trywialny wyjść z komunikatem o błędzie podczas pobierania zmiennej środowiskowej, jeśli nie jest ustawiona lub null, wykonując:${VAR?Variable VAR was not set or null}
.Rozszerzając to, możemy napisać make target wielokrotnego użytku, który może być użyty do zawodzenia innych celów, jeśli zmienna środowiskowa nie została ustawiona:
Uwagi:
$$
) jest wymagany do odroczenia rozwinięcia do powłoki zamiast do wewnątrzmake
test
jest tylko po to, aby zapobiec próbom wykonania przez powłokę zawartościVAR
(nie służy to żadnemu innemu znaczącemu celowi).check-env-vars
można w trywialny sposób rozszerzyć, aby sprawdzić więcej zmiennych środowiskowych, z których każda dodaje tylko jedną linię (np.@test $${NEWENV?Please set environment variable NEWENV}
)źródło
ENV
zawiera spacje, wydaje się, że zawodzi (przynajmniej dla mnie)Możesz użyć
ifdef
zamiast innego celu.źródło
deploy
nie jest to jedyny przepis, który musi sprawdzaćENV
zmienną stanu..PHONY: deploy
ideploy:
przed blokiem ifdef i usuń duplikację. (przy okazji poprawiłem odpowiedź, aby odzwierciedlić poprawną metodę)