一個大的系統,通過一個總的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 |
結果就是,可以正常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: #export carifan_TopMake |
中的目標是“focus_bfin”,然後該目標對應的那些行的代碼,都是make要去執行的動作,對於每一行,都會新啓動一個shell,去執行對應的命令,因此,上面的focus_bfin中的export:
#export carifan_TopMake |
make -f main.mak PLATFORM=Bfin PRODUCT=Focus MAKE_TARGET=focus_bfin |
經過折騰後,對應地,這樣是可以成功導出變量的:
#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 "in same shell line,carifan_TopMake=E516537_in_top_make_global" |
echo "in same shell line,carifan_TopMake=E516537_in_top_make_local" |
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" --> |
截止目前,還是沒搞懂這點。。。
【總結】
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的作用是不同的。