2011-09-06 7 views
13

W pliku make GNU, chciałbym ustawić zmienną wyjściową na jedną wartość (powiedzmy "prawda"), jeśli wejście zmienna jest równa jednej z dwóch wartości i innej wartości ("false"), gdy nie jest.Jak sprawdzić, czy zmienna jest równa jednej z dwóch wartości za pomocą funkcji if/or/i

Dzięki this SO answer dowiedziałem się o funkcjach and i or, a wkrótce potem znalazłem funkcję if. Te funkcje wydają się być dostępne w mojej wersji make, więc chciałbym z nich skorzystać. Chciałbym napisać coś takiego:

TEST_INPUT = `hostname` 
TEST_OUTPUT = $(if $(or $(eq $(TEST_INPUT),hal9000), 
         $(eq $(TEST_INPUT),pipboy)),true,false) 

Niestety nie mogę, bo nie mogłem znaleźć żadnego oczywistą formą spodziewanego eq funkcji. Jestem w stanie osiągnąć to, co chcę używając funkcji filter:

TRUE_HOSTS = hal9000 pipboy 
TEST_OUTPUT = $(if $(filter $(TEST_INPUT),$(TRUE_HOSTS)),true,false) 

lub subst funkcja:

TEST_OUTPUT = $(if $(and $(subst hal9000,,$(TEST_INPUT)), 
         $(subst pipboy,,$(TEST_INPUT))), 
        false,true) 

ale dla mnie to nie jest ładny ani czytelny kod. Czy istnieją rozwiązania bliższe pierwszemu przykładowi (temu, który nie używa funkcji eq)? Może w ogóle nie rozumiem przeznaczenia funkcji if, and i or?

Odpowiedz

18

Rzeczą, która jest dziwna w warunkach warunkowych GNUmake, jest to, że nie ma typu boolowskiego w make - wszystko jest ciągiem znaków. Tak więc wszystkie warianty działają z pustym ciągiem dla "false", a wszystkie niepuste ciągi jako "true".

Z tego powodu brak numeru eq jest irytacją, chociaż niewielką. Zasadniczo możesz uzyskać to, co chcesz, od filter lub findstring, a filter często pozwala przeszukiwać całą listę ciągów, aby dopasować tak, jak w drugim przykładzie.

Jeśli naprawdę potrzebujesz, możesz zdefiniować własną funkcję EQ:

eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1))) 

Którą niestety trzeba użyć jako $(call eq, ... , ... )

+0

Dziękuję za potwierdzenie, że funkcje porównania nie są dostępne. Twoja funkcja "eq" jest również całkiem inteligentna i czytelniejsza niż moje rozwiązania (bezwstydnie z niej skorzystam). Dzięki :) –

4

W zależności od kontekstu, rozważ użycie GMSL (GNU Make Standard Library), która jest zbiorem funkcji w pliku make include "... który zapewnia manipulację listami i ciągami, arytmetykę całkowitą, tablice asocjacyjne, stosy i narzędzia do debugowania." Zobacz http://gmsl.sourceforge.net/

Posiada funkcję „ciąg równe”, SEK, a także szereg innych przydatnych manipulatory

TEST_INPUT = $(shell hostname -s) 
    TEST_OUTPUT = $(if $(or $(call seq,$(TEST_INPUT),hal9000), 
          $(call seq,$(TEST_INPUT),pipboy)),true,false) 

również użyć $ (shell ...) zamiast składni dla backticks lepsza obsługa nowych linii.

7

Odpowiedź Chris Dodd jest dobra, ale istnieje przypadek rogu, dla którego daje nieprawidłowy wynik. Jeśli obie porównywane zmienne są puste (to jest false), zwrócą wartość false. Ulepszona wersja będzie:

eq = $(if $(or $(1),$(2)),$(and $(findstring $(1),$(2)),\ 
           $(findstring $(2),$(1))),1) 

Ta pierwsza sprawdza jeden z argumentów jest niepusty, a jeśli tak, wykorzystuje technikę poprzednią je porównać.W przeciwnym razie zwraca 1, aby wskazać, że wartości są równe, ponieważ oba są puste.

+1

Albo możesz uniknąć tego przypadku 'eq = $ (i $ (findstring x $ (1), x $ (2)), $ (findstring x $ (2), x $ (1)))'. – akim

Powiązane problemy