Makefile與Shell的問題

李先靜發表於2020-04-06

MakefileShell的問題

 

大概只要知道Makefile的人,都知道Makefile可以呼叫Shell指令碼。但是在實際使用時,並不那麼簡單,一些模稜兩可的地方可能會讓你抓狂。你若不信,可以先看幾個例子,想象一下這些這些例子會列印什麼內容,記下你想象的結果,然後在計算機上執行這些例子,對照看一下。

 

示例一:

if [ "$(BUILD)" = "debug" ]; then  echo "build debug"; else echo "build release"; fi

all:

    echo "done"

示例二:

all:

    @CC=arm-linux-gcc

    @echo $(CC)

示例三:

CC=arm-linux-gcc

all:

    @echo $(CC)

示例四:

SUBDIR=src example

all:

    @for subdir in $(SUBDIR); /

    do/

        echo "building " $(subdir); /

    done

 

 

說明:

1.         Shell指令碼在target裡才有效,其它地方都被忽略掉了。所以示例一中,”build debug”之類的字串根本列印不出來。示例一的正確寫法是:

示例一:

all:

    if [ "$(BUILD)" = "debug" ]; then  echo "build debug"; else echo "build release"; fi

    echo "done"

 

2.         make把每一行Shell指令碼當作一個獨立的單元,它們在單獨的程式中執行。示例二中,兩行Shell指令碼在兩個莫不相干的程式裡執行,第一個程式把CC設定為arm-linux-gcc,第二個程式是不知道的,所以列印的結果自然不是arm-linux-gcc了。示例二的正確寫法是:

示例二:

all:

    @CC=arm-linux-gcc; echo $(CC)

或者:

all:

@CC=arm-linux-gcc; /

echo $(CC)

 

3.         make在呼叫Shell之前先進行預處理,即展開所有Makefile的變數和函式。這些變數和函式都以$開頭。示例三中,Shell拿的指令碼實際上是echo arm-linux-gcc,所以列印結果正確。

 

4.         make預處理時,所有以$開頭的,它都不會放過。要想引用Shell自己的變數,應該以$$開頭。另外要注意,Shell自己的變數是不需要括號的。示例四的正確寫法是:

示例四:

SUBDIR=src example

all:

    @for subdir in $(SUBDIR); /

    do/

        echo "building " $$subdir; /

    done

 

相關文章