[轉] Makefile的條件執行

來源:互聯網
上載者:User

標籤:

條件陳述式可以根據一個變數的值來控制make執行或者忽略Makefile的特定部分。條件陳述式可以是兩個不同變數、或者變數和常量值的比較。要注意的是:條件陳述式只能用於控制make實際執行的makefile檔案部分,它不能控制規則的shell命令執行過程。Makefile中使用條件控制可以做到處理的靈活性和高效性。

7 .1      一個例子

首先我們來看一個使用條件判斷的Makefile例子;對變數“CC”進行判斷,其值如果是“gcc”那麼在程式串連時使用庫“libgnu.so”或者“libgnu.a”,否則不連結任何庫。Makefile中的條件判斷部分如下:

……

libs_for_gcc = -lgnu

normal_libs =

 

……

 

foo: $(objects)

 

ifeq ($(CC),gcc)

$(CC) -o foo $(objects) $(libs_for_gcc)

else

$(CC) -o foo $(objects) $(normal_libs)

endif

……

 

例子中,條件陳述式中使用到了三個關鍵字:“ifeq”、“else”和“endif”。其中:

1.        “ifeq”表示條件陳述式的開始,並指定了一個比較條件(相等)。之後是用圓括弧括包圍的、使用逗號“,”分割的兩個參數,和關鍵字“ifeq”用空格分開。參數中的變數引用在進行變數值比較時被展開。“ifeq”之後就是當條件滿足make需要執行的,條件不滿足時忽略。

2.        “else”之後就是當條件不滿足時的執行部分。不是所有的條件陳述式都需要此部分。

3.        “endif”表示一個條件陳述式的結束,任何一個條件運算式都必須以“endif”結束。

通過上邊的例子我們可以瞭解到。Makefile中,條件運算式工作於文本層級(條件判斷處理為文本層級的處理過程),條件的解析是由make來完成的。make是在讀取並解析Makefile時根據條件運算式忽略條件運算式中的某一個文本行,解析完成後保留的只有運算式滿足條件所需要執行的文本行。上例,make處理條件的過程:

當變數“CC”的值為“gcc”時,整個條件運算式等效於:

foo: $(objects)

$(CC) -o foo $(objects) $(libs_for_gcc)

 

當變數“CC”值不等於“gcc”時等效於:

foo: $(objects)

$(CC) -o foo $(objects) $(normal_libs)

 

上面的例子,一種更簡潔實現方式:

libs_for_gcc = -lgnu

normal_libs =

 

ifeq ($(CC),gcc)

libs=$(libs_for_gcc)

else

libs=$(normal_libs)

endif

 

foo: $(objects)

$(CC) -o foo $(objects) $(libs)

7 .2      條件判斷的基本文法

一個簡單的不包含“else”分支的條件判斷語句的文法格式為:

CONDITIONAL-DIRECTIVE

TEXT-IF-TRUE

endif

運算式中“TEXT-IF-TRUE”可以是若干任何文本行,當條件為真時它就將被make作為需要執行的一部分。當條件為假時,不作為需要執行的一部分。

包含“else”的複雜一點的文法格式為:

CONDITIONAL-DIRECTIVE

TEXT-IF-TRUE

else

TEXT-IF-FALSE

endif

 

表示了如果條件為真,則將“TEXT-IF-TRUE”作為執行Makefile的一部分,否則將“TEXT-IF-FALSE”作為執行的Makefile的一部分。和“TEXT-IF-TRUE”一樣,“TEXT-IF-FALSE”可以是若干任何文本行。

條件判斷語句中“CONDITIONAL-DIRECTIVE”對於上邊的兩種格式都是同樣的。可以是以下四種用於測試不同條件的關鍵字。

7.2.1       關鍵字“ifeq”

此關鍵字用來判斷參數是否相等,格式如下:

`ifeq (ARG1, ARG2)‘

`ifeq ‘ARG1‘ ‘ARG2‘‘

`ifeq "ARG1" "ARG2"‘

`ifeq "ARG1" ‘ARG2‘‘

`ifeq ‘ARG1‘ "ARG2"‘

 

替換展開“ARG1”和“ARG1”後,對它們的值進行比較。如果相同則(條件為真)將“TEXT-IF-TRUE”作為make要執行的一部分,否則將“TEXT-IF-FALSE”作為make要執行的一部分(上邊的第二種格式)。

通常我們會使用它來判斷一個變數的值是否為空白(不是任何字元)。參數值可能是通過引用變數或者函數得到的,因而在展開過程中可能造成參數值中包含Null 字元(空格等)。一般在這種情況時我們使用make的“strip”函數來對它變數的值進行處理,去掉其中的Null 字元。格式為:

 

ifeq ($(strip $(foo)),)

TEXT-IF-EMPTY

endif

 

這樣,即就是在“$(foo)”中存在若干前置和結尾空格,“TEXT-IF-EMPTY”也會被作為Makefile需要執行的一部分。

7.2.2       關鍵字“ifneq”

此關鍵字是用來判斷參數是否不相等,格式為:

`ifneq (ARG1, ARG2)‘

`ifneq ‘ARG1‘ ‘ARG2‘‘

`ifneq "ARG1" "ARG2"‘

`ifneq "ARG1" ‘ARG2‘‘

`ifneq ‘ARG1‘ "ARG2"‘

 

關鍵字“ifneq”實現的條件判斷語句和“ifeq”相反。首先替換並展開“ARG1”和“ARG1”,對它們的值進行比較。如果不相同(條件為真)則將“TEXT-IF-TRUE”作為make要執行的一部分,否則將“TEXT-IF-FALSE”作為make要執行的一部分。

7.2.3       關鍵字“ifdef”

關鍵字“ifdef”用來判斷一個變數是否已經定義。格式為:

`ifdef VARIABLE-NAME‘

如果變數“VAEIABLE_NAME”的值非空(在Makefile中沒有定義的變數的值為空白),那麼運算式為真,將“TEXT-IF-TRUE”作為make要執行的一部分。否則,運算式為假,如果存在“TEXT-IF-FALSE”,就將它作為make要執行一部分。當一個變數沒有被定義時,它的值為空白。“VARIABLE-NAME”可以是變數或者函數的引用。

對於“ifdef”需要說明的是:ifdef只是測試一個變數是否有值,不會對變數進行替換展開來判斷變數的值是否為空白。對於變數“VARIABLE-NAME”,除了“VARIABLE-NAME=”這種情況以外,使用其它方式對它的定義都會使“ifdef”返回真。就是說,即使我們通過其它方式(比如,定義它的值引用了其它的變數)給它賦了一個空值,“ifdef”也會返回真。我們來看一個例子

例1:

bar =

foo = $(bar)

ifdef foo

frobozz = yes

else

frobozz = no

endif

 

例2:

foo =

ifdef foo

frobozz = yes

else

frobozz = no

endif

 

例1中的結果是:“frobozz = yes”;而例2的結果是:“frobozz = no”。其原因就是在例1中,變數“foo”的定義是“foo = $(bar)”。雖然變數“bar”的值為空白,但是“ifdef”判斷的結果是真。因此當我們需要判斷一個變數的值是否為空白的情況時,需要使用“ifeq”(或者“ifneq”)而不是“ifdef”。可參考前兩個小節的內容。

7.2.4       關鍵字“ifndef”

關鍵字“ifndef”實現的功能和“ifdef”相反。格式為:

`ifdef VARIABLE-NAME‘

這個就不詳細討論了,它的功能就是實現了和“ifdef”相反的條件判斷。

 

在“CONDITIONAL-DIRECTIVE”這一行上,可以以若干個空格開始,make處理時會被忽略這些空格。但不能以[Tab]字元做為開始(不然就被認為是命令)。條件判斷語句中,在除關鍵字(包括“endif”)之前、條件運算式參數中之外的其他任何地方都可以使用多個空格或[Tab]字元,它不會影響條件判斷語句的功能。同樣行尾也可以使用注釋(“#”開始直到一行的結束)。“else”和“endif”也是條件判斷語句的一部分。在書寫時它們都是沒有任何參數的,可以以多個空格開始(同樣不能以[Tab]字元開始)多個空格或[Tab]字元結束。行尾同樣可以有注釋內容。

在make讀取makefile檔案時計算運算式的值,並根據運算式的值決定判斷語句中那一部分被作為此Makefile所要執行的內容(選擇合格語句)。因此在條件運算式中不能使用自動化變數,自動化變數在規則命令執行時才有效。更不能將一個完整的條件判斷語句分寫在兩個不同的makefile檔案中,在一個makefile檔案使用指示符“include”包含另外一個makefile檔案。

7 .3      標記測試的條件陳述式

我們可以使用條件判斷語句、變數“MAKEFLAGS”和函數“findstring”,實現對make命令列選項的測試。看一個例子:

archive.a: ...

ifneq (,$(findstring t,$(MAKEFLAGS)))

+touch archive.a

+ranlib -t archive.a

else

ranlib archive.a

endif

 

這個條件陳述式判斷make的命令列參數中是否包含“-t”(用來更新目標檔案的時間戳記)。根據命令列參數情況完成對“archive.a”執行不同的操作。命令列前的“+”的意思是告訴make,即使make使用了“-t”參數,“+”之後的命令都需要被執行。

[轉] Makefile的條件執行

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.