2013-01-15 10 views
18

Czy istnieje sposób na wyjście z warunkiem błędu, jeśli plik nie istnieje? Jestem obecnie robi coś takiego:Testowanie, czy plik istnieje w pliku docelowym pliku Makefile i zakończenie, jeśli nie jest dostępny

all: foo 

foo: 
    test -s /opt/local/bin/gsort || echo "GNU sort does not exist! Exiting..." && exit 

Running make biegnie Docelowa all, która biegnie foo.

Oczekiwane jest, że jeśli warunkowe test -s nie powiedzie się, zostaną wykonane instrukcje .

Jednak nawet jeśli istnieje /usr/bin/gsort, otrzymuję wynik instrukcji echo, ale polecenie exit nie działa. Jest to przeciwieństwo tego, co mam nadzieję osiągnąć.

Jaki jest prawidłowy sposób na wykonanie czegoś podobnego?

+0

Gdy próbuję to w wierszu poleceń, mając właściwej strony '' || w nawiasie, aby uzyskać powłokę sub, sprawia, że ​​działa zgodnie z oczekiwaniami. Nie mam pojęcia, czy to jest to samo w pliku Makefile. Bez nawiasu "wyjście" zostanie wykonane, nawet jeśli test będzie pozytywny. – HonkyTonk

Odpowiedz

15

exit sam zwraca status ostatniego wykonanego polecenia. W tym przypadku zwraca zero, co oznacza, że ​​wszystko jest w porządku.

To jest, ponieważ || i && mieć equal precedence, a powłoka interpretuje polecenia tak, jakby były napisane

(test ... || echo ...) && exit 

Jeśli chcesz sygnalizować awarię należy wyjść z braku wartości zero, np exit 1. A jeśli chcesz echo i wyjście, wystarczy umieścić w sekwencji poleceń oddzielonych ;

all: foo 

foo: 
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; } 
5

każdy wiersz polecenia w makijażu prowadzi we własnym sub-shell. Tak więc uruchomienie exit właśnie kończy tę pod-powłokę - a nie plik Makefile jako całość. Domyślnie wykonywanie make zostanie zatrzymane, jeśli dowolna pod-powłoka zwróci nieudany status wyjścia (zgodnie z konwencją 0 oznacza sukces, więc cokolwiek innego zatrzyma wykonywanie). Najprostszą metodą byłoby po prostu użyć kod zakończenia polecenia w test:

all: foo 

foo: 
    test -s /opt/local/bin/gsort 

Drukowanie komunikat diagnostyczny komplikuje się z powodu polecenia jak echo zwróci status wyjścia 0, powodując make się, że wszystko jest w porządku. Aby obejść ten problem, należy uruchomić polecenie po nim, że dadzą sub-shell status niezerowe Wyjście:

all: foo 

foo: 
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; } 

lub nawet tylko

all: foo 

foo: 
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; false; } 
24

Zdaję sobie sprawę, że jest to nieco stary w tym momencie, ale nie musisz nawet używać podpowłoki do sprawdzenia, czy plik istnieje w Make.

To zależy również od tego, jak chcesz/oczekiwać, że będzie działał.

Korzystanie z funkcji wieloznaczny, tak:

all: foo 
foo: 
ifeq (,$(wildcard /opt/local/bin/gsort)) 
    $(error GNU Sort does not exist!) 
endif 

jest jeden dobry sposób, aby to zrobić. Zauważ tutaj, że klauzula ifeq nie jest wcięta, ponieważ jest oceniana przed samym celem.

Jeśli chcesz to się stało bezwarunkowo na każdy cel, można po prostu przenieść go poza cel:

ifeq (,$(wildcard /opt/local/bin/gsort)) 
$(error GNU Sort does not exist!) 
endif 
1

Wystarczy zrobić:

all: /opt/local/bin/gsort 

a jeśli /opt/local/bin/gsort brakuje, to będzie otrzymasz komunikat "brak reguły dla zrobienia celu"/opt/local/bin/gsort "".

Ale jeśli chcesz jakiś miły wyjaśnienie z nim zrobić:

/opt/local/bin/gsort: 
    echo "GNU sort does not exist! Exiting..." 
    false 

W GNU/make jeśli cel nie jest zadeklarowana .PHONEY i nie ma żadnych zależności, reguła zostanie wywołany, jeśli plik dopasowanie tego celu nie istnieje.

Powyższy kod wyzwala komendę false tylko wtedy, gdy /opt/local/bin/gsort nie istnieje, zwróci wartość inną niż 0, a wykonanie zakończy się niepowodzeniem.

+0

Czy istnieje sposób na zrobienie tego, aby make kontynuował sprawdzanie każdego brakującego pliku, a następnie zwracał fałsz? W ten sposób, jeśli komuś brakuje wielu plików, wszystkie pojawią się zamiast pojedynczo. – thepiercingarrow

1

Skoro jesteś sprawdzając czy gsort plik wykonywalny istnieje, można użyć polecenia which lub type powłoki za to, np:

all: foo 
    : 

foo: 
    which gsort || exit 1 
    # or 
    type gsort || exit 1 

Nie trzeba się komunikat o błędzie, ponieważ będzie ona automatycznie druku :

/bin/sh: linia 0: typ: gsort: nie znaleziono

co jest oczywiste.


Alternatywnie można użyć test lub [ (patrz help test/help [ składnią), np

test -x /opt/local/bin/gsort || { echo Error msg; exit 1; } 

który sprawdza, czy podany plik istnieje i jest wykonywalny, w przeciwnym razie wyświetla komunikat i kończy pracę. Nawiasy są ważne, aby zastąpić normalne pierwszeństwo operatorów (od lewej do prawej), grupując polecenia (więcej informacji w sekcji Compound Commands w man bash).


Innym sposobem jest użycie cele w regule, aby sprawdzić, czy plik istnieje i dodać jako zależność do all, np

all: /opt/local/bin/gsort 
    @echo Success. 

/opt/local/bin/gsort: 
    @echo "GNU sort does not exist! Exiting..." 
    exit 1 

Wynik:

$ make 
GNU sort does not exist! Exiting... 
exit 1 
make: *** [/opt/local/bin/gsort] Error 1 
Powiązane problemy