一個makefile中export出來的變量在另外一個makefile中無法訪問

【問題背景】

一個大的系統,通過一個總的make控制整個項目編譯過程。

具體make的流程是,在/make下面直接make,會先去make uboot,再去make kernel,然後去make其他的,比如drivers等等。

遇到的問題是,由於是使用交叉編譯器,對應的交叉編譯器的路徑,是在uboot中定義的,所以uboot是可以正常交叉編譯的。

但是編譯完uboot,轉去編譯kernel的時候,卻出錯,說是找不到交叉編譯器。

即問題的現象是,找不到交叉編譯器:

/bin/sh: bfin-uclinux-gcc: command not found
【解決過程】

現象看起來很簡單,就是具體的交叉編譯器的路徑,沒有正確配置。

但是具體爲何沒有添加對應交叉編譯器的路徑,去找原因,最後卻發現根本原因是,對應交叉編譯器的路徑,是在uboot中配置的,然後通過export CROSS_COMPILE導出該變量,供後續編譯其他部分代碼所使用。

剛開始,自己的理解有誤,以爲整個邏輯是,在make之後,由於是先make uboot,再make kernel,所以交叉編譯器的變量的值,是通過在uboot中配置好,然後export出來給後續的kernel,drivers等部分編譯的時候使用。

但是後來才發現,自己理解錯誤。

因爲uboot和kernel,兩者的MAKELEVEL(可以通過echo $(MAKELEVEL)查看當前makefile的level)是同一級的,MAKELEVEL都是2,對應的最開始的make的MAKELEVEL是0.

所以,經過測試,發現通過export出來的變量,在MAKELEVEL=0的make中,是可以傳遞給子makefile(sub-make)中的uboot的,而通過同一級的makefile,即兩者的MAKELEVEL相同,是沒法用export傳遞變量的。

即uboot和kernel,uboot中export出來的變量,是不能傳遞給kernel的。

而如果uboot中設置的CROSS_COMPILE的變量無法傳遞給kernel,那麼此項目,之前的人,是如何正常編譯的呢?最後通過問別人才得知,原來,就是最簡單的,把交叉編譯器的變量,加到.bash_profile中的$PATH中去,如此而已。這樣,就可以在編譯kernel的時候,找到對應的交叉編譯器了。而不是通過在uboot中export出來CROSS_COMPILE來獲得交叉編譯器路徑的。

此問題,前後花了很長時間去debug,中間,不知道什麼原因,導致我測試在總的make,即MAKELEVEL=0的makefile中,傳遞變量到MAKELEVEL=2的uboot中,結果卻發現正常傳遞參數,搞得很是鬱悶,但是後來再次測試,卻又正常了,即可以通過上層的makefile,export出來變量給sub makefile中了。真是無語了。

另外,關於在makefile中export出來的變量,可以傳遞給sub make中,網上很多資料介紹這方面內容的,比如:

http://www.gnu.org/s/hello/manual/make/Variables_002fRecursion.html#Variables_002fRecursion

但是對於同級makefile通過export傳遞變量,沒有看到人討論過,此處經過自己的測試,發現的確是無法傳遞的。

 

【makefile中的export和shell中的export】

對於測試,在上層makefile中,用export導出變量,傳遞給子makefile時,看看子makefile中是否可以訪問該變量。

其中,在最上層的makefile中,這樣測試的:

 carifan_TopMake=E516537_in_top_make
#export carifan_TopMake
focus_bfin
:
        echo current make MAKELEVEL=$(MAKELEVEL)
        export carifan_TopMake
        echo *****************test Value in Top Makefile=$(carifan_TopMake)
        make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin
   

然後make focus_bfin後,發現在focus_bfin下面,export出來的carifan_TopMake,在子makefile中打印出來的是空的,即實際上該變量沒有被export出來。

而後來無意間,用下面這樣的方式測試:

 carifan_TopMake=E516537_in_top_make
export carifan_TopMake
focus_bfin
:
        echo current make MAKELEVEL=$(MAKELEVEL)

        #export carifan_TopMake
        echo *****************test Value in Top Makefile=$(carifan_TopMake)
        make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

   
結果就是,可以正常export出來變量,然後子makefile中,可以得到該變量的值。

所以,對此現象,經過後來的折騰,發現不是所謂什麼makefile中變量的作用域之類的問題,

而是在makefile中的export和shell中的export作用不同:

在focus_bfin上面那行的“export carifan_TopMake”,

是makefile中的export,其作用是導出一個變量,使得子makefile,即當前makefile所派生的的makefile,即通過如下某種形式:

make XXX

make -f XXX.mak

include XXX.mak

而相關的子makefile。

focus_bfin:
        echo current make MAKELEVEL=$(MAKELEVEL)

        #export carifan_TopMake
        echo *****************test Value in Top Makefile=$(carifan_TopMake)
        make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

  

中的目標是“focus_bfin”,然後該目標對應的那些行的代碼,都是make要去執行的動作,對於每一行,都會新啓動一個shell,去執行對應的命令,因此,上面的focus_bfin中的export:

 #export carifan_TopMake
和下面的那行的make:

      make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin
 是沒有關係的,是分別屬於兩個shell的。

經過折騰後,對應地,這樣是可以成功導出變量的:

 #export carifan_TopMake

#carifan_TopMake=E516537_in_top_make_global

focus_bfin:

        echo current make MAKELEVEL=$(MAKELEVEL)

        echo "*****************test Value in Top Makefile=$(carifan_TopMake)"; \

        carifan_TopMake=E516537_in_top_make_local;export carifan_TopMake; make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

 

【疑問】

不過,雖然理解了上面的makefile中的export和shell中的export是不同的,但是對於下面的這樣的例子:

 carifan_TopMake=E516537_in_top_make_global

focus_bfin:

        echo current make MAKELEVEL=$(MAKELEVEL)

        echo "*****************test Value in Top Makefile=$(carifan_TopMake)"; \

        export carifan_TopMake=E516537_in_top_make_local; echo "in same shell line,carifan_TopMake=$(carifan_TopMake)"; make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin

 其echo輸出的內容,卻是   
 echo "in same shell line,carifan_TopMake=E516537_in_top_make_global"
   而不是我所期望的:

 echo "in same shell line,carifan_TopMake=E516537_in_top_make_local"
   而看到別人有關於makefile中的$XXX的解釋,說makefile會去自動將$XXX替換爲相應的內容,所以對於上面的內容:

 echo "in same shell line,carifan_TopMake=$(carifan_TopMake)";

其自動會替換成:

 echo "in same shell line,carifan_TopMake=E516537_in_top_make_global";

   所以就相當於在shell中執行:

 export carifan_TopMake=E516537_in_top_make_local; echo "in same shell line,carifan_TopMake=E516537_in_top_make_global";

但是,我去嘗試:

 echo "in same shell line,carifan_TopMake=$carifan_TopMake";

或者 

 echo "in same shell line,carifan_TopMake=$$carifan_TopMake";

 輸出的結果,都無法實現想要的:

 echo "in same shell line,carifan_TopMake=E516537_in_top_make_local";

 而相對的,在shell中執行類似的動作,是可以echo出來對應的變量的:

 export carifan_TopMake=E516537_in_top_make_local ; echo "$carifan_TopMake"

-->
E516537_in_top_make_local

   而此處卻始終無法實現像shell中一樣的結果,顯示我的E516537_in_top_make_local的值。

截止目前,還是沒搞懂這點。。。

 

【總結】

1.在(parent,上層的)makefile中export出來變量,子makefile(sub make)中,是可以訪問的。

2. 而同一級別的makefile(可通過makefile中內置變量MAKELEVEL查看得知當前makefile的levlel),是無法通過export來傳遞變量的,即一個makefile中export出來一個變量,同一級的另外一個makefile中,是無法訪問/得到的。

3.makefile中的export是導出變量到子makfile,而目標對應執行的動作中的export,是屬於shell中的export,其作用是導出變量到當前shell。此兩個export的作用是不同的。

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