1. 程式人生 > >uboot makefile裡面的兩個all:作用(偽目標,空命令)

uboot makefile裡面的兩個all:作用(偽目標,空命令)

uboot的makefile裡面有兩個all:

第一個all:沒有依賴,也沒有命令。後面接的是兩條include

sinclude $(obj)include/autoconf.mk.dep
sinclude $(obj)include/autoconf.mk

另外一個 all:$(ALL-y) $(SUBDIR_EXAMPLES)

這個all才是我們真正需要執行的

要理解這裡的all 空命令的作用。必須瞭解下面幾個點

1

當makefile中有兩個相同目標的時候,會執行後一個目標。因為後一個目標會過載前一個。

比如

all:

echo all1

all:

echo all2

執行make 會輸出後一個all2

2偽目標

一個使用地方是 當不需要產生一個實際的目標檔案的時候(比如只要執行指令)。

clean:

rm *.o

這樣是不產生檔案。只需要執行指令。如果當前目錄沒有一個檔案叫做clean。執行make clean是正常的 。如果目錄下有一個clean檔案。那麼由於這個clean檔案是最新的,因此就不會執行rm *.o操作。因此需要定義一個偽目標。不管目錄下是否存在這個目標。都會執行clean的操作rm *.o

.PHONY clean

clean:

rm *.o

3空命令

可以存在依賴檔案,但是沒有命令列。

比如 

all:

或者

all: $(obj)

空命令的唯一作用是防止make在執行時,試圖為重建這個目標去查詢隱含命令

這句話暫時不好理解。先看後面的再說。

4makefile的執行規則和include 這個是關鍵點

makefile首先被解析。

遇到include。先去解析include的檔案(假設為inc.mk),解析完畢以後再回頭來解析原makefile。

關鍵點是如果這個inc.mk不存在。make不會退出。而是先提出一個警告,繼續處理原makefile的內容。

等到原makefile的內容處理完畢以後。會嘗試使用規則來重建這個inc.mk檔案,也就是嘗試將這個inc.mk檔案當做一個目標來執行。如果不能重建出這個inc.mk。那麼報告一個錯誤,make退出。如果這個inc.mk重建成功了。那麼將原makefile的狀態重置,重新開始執行這個makefile。

回頭來看uboot的makefile。假定我們成功執行了make xxxx_config。接下來執行了一個make 命令

首先遇到的就是一個

all:

sinclude $(obj)include/autoconf.mk.dep
sinclude $(obj)include/autoconf.mk

我們來看如果沒有第一個all:會是什麼結果。

此時的autoconf.mk.dep 以及 autoconf.mk都是不存在的

但是根據第四條。make不會退出。會先繼續往下執行。執行完整個makefile

再回頭來看include的檔案。

如果在makefile末尾列印一句reach to end,在sinclude $(obj)include/autoconf.mk也列印一句,那麼我們看到的結果是

Makefile:189: "hereis include  autoconf.mk.dep"
Makefile:892: "reach to end"
Generating include/autoconf.mk
Generating include/autoconf.mk.dep
Makefile:189: "hereis include  autoconf.mk.dep"
Makefile:892: "reach to end"
make: `include/autoconf.mk' is up to date.

根據第四條,第一次沒有autoconf.mk 先執行了整個makefile的讀取列印了reach to end。

然後回過頭將include/autoconf.mk以及 include/autoconf.mk.dep當做一個目標執行。因此才會有Generating include/autoconf.mk
Generating include/autoconf.mk.dep的輸出。完畢後重置makefile狀態。重新執行makefile。此時autoconf.mk和autoconf.mk.dep都有了。

為什麼沒有編譯uboot呢? 因為我們執行的命令是make 。後面沒有帶引數,因此makefile會編譯預設遇到的第一個目標。因為我們註釋了第一個all:

所以直接執行了include。開啟autoconf.mk.dep看到第一行就是include/autoconf.mk: include/common.h 。這就是makefile遇到的第一個目標

include/autoconf.mk。因此將include/autoconf.mk當做終極目標執行了。此時的include/autoconf.mk是前一次剛產生的,所以是最新的。makefile認為沒有必要重新執行。

因此什麼都不做,最後輸出了make: `include/autoconf.mk' is up to date.這裡也就理解了前面的第三條 空命令的唯一作用是防止make在執行時,試圖為重建這個目標去查詢隱含命令,這個隱含的命令就是執行第一個遇到的目標。

如果有第一個all:的話。makefile就知道需要執行的終極目標是 all。而不是include的autoconf.mk.dep裡面的include/autoconf.mk。

繼續執行到遇到後面的all: 後面的all將覆蓋前面的all。執行這裡的操作。所以最終執行的是第二個all

因此第一個all:的含義就是

如果你 執行make的時候沒有帶任何其他目標。單獨的一個make。可以避免以autoconf.mk.dep裡面的include/autoconf.mk作為錯誤目標。

如果你執行make的時候帶了目標。這個all:有不有都無所謂。