2011-09-06 12 views
13

在GNU makefile中,如果輸入中有一個輸入變量爲一個值(假設爲「true」),當它不是時,變量等於兩個值中的一個,並等於另一個值(「false」)。如何使用if /或/和函數檢查變量是否等於兩個值中的一個

感謝this SO answer我已經瞭解了andor函數,不久之後我發現了if函數。這些函數似乎在我的make版本中可用,所以我想使用它們。我想編寫類似的東西:

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

可惜我不能,因爲我無法找到預期eq功能的任何明顯的形式。我能夠實現我想用什麼filter功能:

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

subst功能:

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

但對我來說不是一個很好看的也不是可讀的代碼。是否有更接近第一個例子的解決方案(使用不存在eq函數的解決方案)?也許我不明白ifandor函數的目的?

回答

18

關於GNUmake條件的奇怪之處在於make中沒有布爾類型 - 一切都是字符串。所以條件都適用於'false'的空字符串和所有非空字符串'true'。

這就是說,eq缺失的事實是一個煩惱,雖然是一個小問題。通常,您可以從filterfindstring中獲得所需的內容,而filter通常允許您搜索要在第二個示例中匹配的所有字符串列表。

如果你真的需要它,你可以定義自己的EQ功能:

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

你不幸有作爲$(call eq,使用... , ... )

+0

感謝您確認我沒有提供比較功能的感覺。你的'eq'函數也比我的解決方案更聰明,更易讀(我會無恥地使用它)。謝謝:) –

4

根據你的情況下,考慮使用GMSL(GNU Make標準庫),它是make include文件中的函數集合「...提供列表和字符串操作,整數算術,關聯數組,堆棧和調試工具。」見http://gmsl.sourceforge.net/

它有一個「字符串等於」功能,SEQ,以及其他一些有用的機械手:

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

此外,使用$(殼...)語法,而不是用於反引號更好地處理換行符。

7

克里斯多德的答案是好的,但有一個角落的情況下,它提供了一個不正確的結果。如果兩個被比較的變量都是空的(即false),那麼它將返回false。一種改進版本是:

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

這首先檢查其中一個參數都非空,如果是使用以前的技術來比較它們。否則,它返回1,表示這些值是相等的,因爲它們都是空的。

+1

或者你可以避免這種情況'eq = $(和$(findstring x $(1),x $(2)),$(findstring x $(2),x $(1)))''。 – akim

相關問題