2016-08-29 100 views
1

使用make的''Remaking Makefiles''功能我使用include指令(請參閱Makefile: defining rules and prerequisites in recipes)生成部分makefile。現在我一直無法看到如何表達包含的makefile之間的依賴關係。他們似乎都是一次全部評估。Makefile:聲明包含文件之間的依賴關係

考慮以下簡單的Makefile,說明我的問題:

all: 

-include foo.make 
-include bar.make 

foo.make: Makefile 
    echo FOO:=blub bla baz > foo.make 

bar.make: Makefile foo.make 
    echo BAR:=$(FOO) > bar.make 

如果我現在運行make我會得到:

$ cat foo.make 
FOO:=blub bla baz 
$ cat bar.make 
BAR:= 

爲什麼?由於bar.make取決於foo.make,因此bar.make的評估不應等到它成功包含foo.make

如何解決此問題並確保bar.make要麼稍後重新評估,要麼僅評估一次foo.make存在,已包含並可定義變量BAR

我不能結合foo.makebar.make成一個單一的生成文件和規則的原因有兩方面:

首先,我真正的設置,bar.make取決於這又傳遞地依賴於foo.make多箇中間目標。因此,在創建foo.make時,bar.make的內容仍不能創建。

其次,在我的真實設置中,foo.makebar.make不只是定義變量,而且還包括eval()define/endef塊。所以我必須寫:

-include makefile_with_prerequisite_variables 
define MYDEF 
sometarget-$1: $(TARGET_$1_PREREQUISITES) 
    [...] 
endf 
-include makefile_with_eval_call_statements 

makefile_with_prerequisite_variablesmakefile_with_eval_call_statements內容不能去到一個單一的makefile片段:

  • 如果我把makefile_with_eval_call_statements以上MYDEFmakefile_with_prerequisite_variables然後在$eval($call(MYDEF))語句組合在一起它不會工作,因爲MYDEF僅在之後被宣佈。
  • 如果我把makefile_with_prerequisite_variables下面MYDEFmakefile_with_eval_call_statements在一起,然後在MYDEF定義的食譜不會有正確的prerequisits因爲$(TARGET_$1_PREREQUISITES)變量,然後由makefile_with_prerequisite_variables聲明之後

總之,我需要包含兩個不同的makefile,其中一個取決於另一個。我不知道如何表達這種關係,以至於只有在其他makefile是最新的並且包含在主makefile中後纔會創建一個makefile的內容。

回答

1

首先,通過轉義$(FOO)的值,可以很容易地修復在此簡單示例中創建的生成文件,以便在創建bar.make時不會擴展它,而是延遲到讀入爲止。所以:

bar.make: Makefile foo.make 
     echo 'BAR:=$$(FOO)' > [email protected] 

然而,這可能不是你的更復雜的現實生活中的makefile就足夠了。

GNU使這樣的工作:首先解析所有的makefile。然後,對於每個包含的makefile,將其視爲目標並嘗試構建它(例如,就像用戶調用make include1.mk include2.mk include3.mk ...一樣)。然後在最後,如果任何包含的makefile被重建,重新自行執行並從頭開始整個過程​​。

GNU make does NOT像這樣工作:解析makefiles,嘗試重建第一個包含的makefile,如果重建,重新執行;如果它不被重建在去下包含makefile文件等

一個簡單的技巧,如果你必須有這種類型的順序,你可以用的是把包括bar.makefoo.make

all: 

-include foo.make 

foo.make: Makefile 
     printf -- '-include bar.make' > [email protected] 
     echo FOO:=blub bla baz >> [email protected] 

bar.make: Makefile foo.make 
     echo 'BAR:=$$(FOO)' > [email protected] 

通過這樣做,您可以確保如果foo.make不存在,make將看不到bar.make的包含,因此它不會嘗試構建它。只有在第一次重新執行後,纔會看到bar.make的包含並嘗試構建它。有一件事:如果你得到最新版本的GNU讓你不再需要使用-include這個技巧。即使使用生成的makefile,您也可以使用include

+0

你又一次拯救了我的一天!如果我能給你更多的讚揚,我會。你的建議都非常有價值。非常感謝! – josch