編寫Android.mk中的LOCAL_SRC_FILES的終極技巧

來源:互聯網
上載者:User

標籤:包括   開頭   使用   檔案夾   --   android   不同的   shell   pre   

轉自:http://blog.csdn.net/fu_zk/article/details/12836431問題的引入

在使用NDK編譯C/C++項目的過程中,免不了要編寫Android.mk檔案,其中最重要的就是LOCAL_SRC_FILES源檔案清單.
考慮有如下源檔案分布的情況:

cpp檔案全部位於android項目下的jni檔案夾下,結構如下    jni      |---1.cpp     |---2.cpp     |---Android.mk     |---Application.mk     |---ndk_test.cpp     |---src         |    |---core     |    |    |---core1.cpp     |    |    |---core2.cpp     |    |---src1.cpp     |    |---src2.cpp

按照通常的寫法,在android.mk中,應該寫入

LOCAL_SRC_FILES := ndk_test.cpp                 1.cpp                 2.cpp                 src/src1.cpp                 src/src2.cpp                 src/core/core1.cpp                 src/core/core2.cpp

繁瑣不堪!

初步解法:一句話引入單個目錄(不包括子目錄)下的所有cpp源檔案

繼續上面的情況為例,我可以這樣寫

MY_CPP_LIST := $(wildcard $(LOCAL_PATH)/*.cpp)MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/*.cpp)MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/core/*.cpp)LOCAL_SRC_FILES := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%)

問題解決. 簡單解釋一下上面的幾句話

  1. MY_CPP_LIST := $(wildcard $(LOCAL_PATH)/*.cpp),這句話的意思是使用wildcard函數擷取$(LOCAL_PATH)目錄也就是jni目錄下的所有尾碼名為cpp的檔案,並把結果放到變數MY_CPP_LIST裡.我們知道$(LOCAL_PATH)指的是當前Android.mk檔案所在目錄,所以通過這句話,MY_CPP_LIST中的值應該是jni/1.cpp jni/2.cpp jni/ndk_test.cpp.
  2. MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/*.cpp), 擷取jni/src目錄下的源檔案,並追加到變數MY_CPP_LIST
  3. MY_CPP_LIST += $(wildcard $(LOCAL_PATH)/src/core/*.cpp),同上,擷取jni/src/core目錄下的源檔案
  4. 通過以上幾步,得到MY_CPP_LIST中內容是jni/1.cpp jni/2.cpp jni/ndk_test.cpp jni/src/src1.cpp jni/src/src2.cpp jni/src/core/core1.cpp jni/src/core/core2.cpp
  5. LOCAL_SRC_FILES := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%),前面我們擷取的檔案都是以jni開頭的,而真正編譯所需要的檔案都應該是直接從jni目錄開始的,所以我們使用模式替換把所有檔案名稱前面的jni/去掉.

這裡我解釋一下$(MY_CPP_LIST:$(LOCAL_PATH)/%=%)的文法含義,它的意思是對MY_CPP_LIST中每一項,應用冒號後面的規則,規則是什麼呢?規則是$(LOCAL_PATH)/%=%,意思是,尋找所有$(LOCAL_PATH)/開頭的項,並截取後面部分

最後一句話也可以使用subst函數寫成:

#替換每一項中的 "$(LOCAL_PATH)/" 為 ""(空)LOCAL_SRC_FILES := $(subst $(LOCAL_PATH)/, , $(MY_CPP_LIST))  

或使用patsubst函數寫成

#同模式替換,這裡使用patsubst函數LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%, %, $(MY_CPP_LIST))  

具體文法請參考:Functions for String Substitution and Analysis

實際使用中,可以把代碼放在jni目錄以外的目錄裡,這時只要修改wildcard函數裡的相對路徑就可以了,甚至也可以使用絕對路徑,只要你願意.

以上代碼已經足以應付大多數情況了,不過人的懶惰是無極限的,像上面的情況我的所有源檔案都在jni目錄下,為什麼還要把每個子目錄都寫一行呢,不太優雅呀,最好能寫一句話把jni目錄下的所有源檔案都引入.

進階:引入單個目錄(包括子目錄)下的所有cpp源檔案

為了達到引入目錄下的所有源檔案,包括子目錄這個目標,我在android.mk中這樣寫

#聲明一個變數MY_CPP_PATH表示源碼目錄MY_CPP_PATH := $(LOCAL_PATH)/ #擷取目錄下的所有檔案 My_All_Files := $(shell find $(MY_CPP_PATH)/.)My_All_Files := $(My_All_Files:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%)#從My_All_Files中再次提取所有的cpp檔案,這裡也可以使用filter函數MY_CPP_LIST := $(foreach c_file,$(My_All_Files), $(wildcard $(c_file)/*.cpp) ) MY_CPP_LIST := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%)LOCAL_SRC_FILES := $(MY_CPP_LIST)

通過以上幾行,成功得到了jni目錄包含它的子目錄下的所有cpp源檔案,並正確編譯.實際使用中,代碼不一定存放在jni目錄下,修改MY_CPP_PATH就可以了,注意:MY_CPP_PATH最好使用以$(LOCAL_PATH)開頭的相對目錄

這種寫法極大的方便了項目的開發,以前在源碼目錄下建立cpp源檔案,建立目錄都不需要再來修改android.mk檔案了.

還有一個問題,上面代碼裡只是引入cpp檔案,如果源碼檔案夾下還有c檔案呢,怎麼辦?再多寫幾行?

進階2.0:引入單個目錄(包括子目錄)下的所有*.cpp和*.c源檔案

這裡,我直接給出代碼

MY_CPP_PATH  := $(LOCAL_PATH)/My_All_Files := $(shell find $(MY_CPP_PATH)/.)My_All_Files := $(My_All_Files:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%)MY_CPP_LIST  := $(filter %.cpp %.c,$(My_All_Files)) MY_CPP_LIST  := $(MY_CPP_LIST:$(LOCAL_PATH)/%=%)LOCAL_SRC_FILES := $(MY_CPP_LIST)

代碼中用到了filter函數.

還不滿足?如果項目的源碼有多個目錄放在不同的地方,而且有多個尾碼,怎麼辦?

終極進階:引入多個目錄(包括子目錄)下的多個尾碼名的源檔案

上代碼(2013年10月9日修正):

# 掃描目錄下的所有源檔案MY_FILES_PATH  :=  $(LOCAL_PATH)                    $(LOCAL_PATH)/../../ClassesMY_FILES_SUFFIX := %.cpp %.c %.ccMy_All_Files := $(foreach src_path,$(MY_FILES_PATH), $(shell find "$(src_path)" -type f) ) My_All_Files := $(My_All_Files:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%)MY_SRC_LIST  := $(filter $(MY_FILES_SUFFIX),$(My_All_Files)) MY_SRC_LIST  := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)LOCAL_SRC_FILES := $(MY_SRC_LIST)

以上代碼中,變數MY_FILES_PATH儲存源檔案所在目錄,MY_FILES_SUFFIX儲存源檔案的尾碼名

原創文章,轉載請註明,謝謝!

PS:如何debug 一個android.mk檔案

有一個辦法,那就是在編譯過程輸出android.mk檔案中變數的值,就可以觀察分析問題所在了,使用代碼

$(warning $(LOCAL_SRC_FILES))

就可以在編譯過程中從終端視窗中觀察到變數LOCAL_SRC_FILES的值

編寫Android.mk中的LOCAL_SRC_FILES的終極技巧(轉)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.