我所認識的GNU make(5) -- make是如何處理Makefile的

通常情況下Makefile的內容就是告訴make如何去編譯和鏈接生成一個程序。並且默認情況下,make會以在Makefile中尋找到的目標作爲這次執行make程序的最終目標,所以和最終目標不相干的規則make將忽略掉,不會去執行。或者你也可以在輸入make命令的時候指明具體的目標。

你可以通過使用inclide指令將其他的makefile包含進來,如果你在include其他的makefile的時候沒有指定其路徑,那麼make會到當前的目錄裏去找,如果沒有找到指定的makefile,並且你在輸入make命令的時候沒有指定-I或者--include-dir選項,那麼make還會去一下這些目錄裏面尋找:/usr/local/include,/usr/gun/include,/usr/local/include,/usr/include。

有時候Makefile可以從其他的文件生成,在這種情況下,爲了能夠得到最新的Makefile,每當make讀取Makefile的時候就會將當前的Makefile也當作是一個目標(target)然後去嘗試更新。如果make能夠找到如何更新Makefile的方法,不管是顯式規則還是隱含規則,那麼make就會嘗試着去更新Makefile,如果Makefile可以被更新,那麼make就會先更新Makefile,然後將make當前的狀態清零,再重新將Makefile讀進來。

GNU make處理Makefile文件分爲兩大步:

1. 讀進所有的Makefile,初始化所有的變量,隱含規則和顯式規則,建立一張依賴表,該表包含所有的target和prerequisite,在這一步中,make會對Makefile中的變量進行展開,即使用變量的值(字符串)替代原來變量所在的位置;

2. make利用上一步建立的依賴表決定哪些target需要重建,然後將相應的recipe傳給shell,讓shell執行這些recipe。

第一步變量的展開中,有時候我們並不希望某些變量在規則中的target,prerequisite確定之前或者其他變量賦值之前就展開,那樣就無法得到我們想要的值,這個時候就需要對這個Makefile進行二次展開,就是說make程序在第一次解析完Makefile後,再次對Makefile進行解析,對一些推遲展開的變量進行展開。如正常情況下,自動變量是隻能在recipe中使用的,因爲第一次展開之前make是無法知道這些自動變量的值的,當時等到第一次展開之後,所有的自動變量的值都已經確定,這時候就可以讓make進行二次展開,這樣就可以在recipe之外對自動變量進行使用了,這樣就能夠徹底地將自動變量從recipe的範圍中釋放出來。

如果要讓make知道需要對某個Makefile進行二次展開的話,那麼就需要在Makefile中定義.SECONDEXPANSION這個特殊的目標,一般情況下只需要寫明這個目標,然後prerequisite和recipe都可以放空。那麼怎麼讓某一個變量在二次展開的時候才生效呢?主要有兩種方式:

1. 在變量定義的時候,將變量定義爲循環展開變量而不是直接展開變量,即使用=或者?=對變量進行定義,而不是:=或::=(這是直接展開變量的定義方式),循環展開變量中如果不包含有其他的變量引用的話則跟直接展開變量是沒有區別的,否則,make對Makefile進行第一次展開的時候,make只會將定義循環展開變量時的那一個字符串填充到變量位置,而不對循環展開變量中對其他變量的引用進行展開,等到第二次make對Makefile進行解析的時候纔會看到那個原本在循環展開變量定義中被引用的變量,然後再對其進行展開;

2. 更簡單的方法就是在變量引用的時候再多加一個$符號,就是說變量名前面有兩個連續的$符號,例如$$var,所以如果在二次展開使能的情況下,如果你想要在prerequisite中使用一個$符號的時候,這時候你就需要寫連續的四個$符號,即$$$$,因爲在Makefile中都是以$符號作爲變量引用的開始,在每一次解析中,需要連續兩個$符號,make纔會知道那是一個$字符。

其實這兩種方法的本質是一樣的,都是變量的嵌套引用。


寫這個是本着大家一起學習探討的目的,閱過的請留下您的寶貴意見,我會及時回覆。

--The Magic That Brings Hardware To Life.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章