使用外部命令
最簡單的方法是調用shell外部命令。首先,我們指定要搜索的源文件的根目錄,並將其設置為變量SRC_ROOT。LOCAL_C_INCLUDES變量直接使用find
完整的代碼如下:
#警告:使用了Shell命令,它僅在類似UNIX的操作系統上有效。
#如果要在Windows上運行,請用Makefile規則替換它。
SRC_SUFFIX := *。cpp *。c
SRC_ROOT := $(LOCAL_PATH)/../../類別
ALL _ FILES:= $(shell find $(SRC _ ROOT)-type f)
SRC_FILES := $(filter $(subst *,%,$(SRC\_SUFFIX)),$(ALL_FILES))
LOCAL _ SRC _ FILES:= hello CPP/main . CPP
LOCAL _ SRC _ FILES+= $(SRC \ _ FILES:$(LOCAL _ PATH)/% = %)
SRC _ DIRS:= $(shell find $(SRC _ ROOT)-type d)
LOCAL_C_INCLUDES := $(SRC_DIRS)
使用純Makefile語法
使用外部命令是最簡單也是最實用的解決方案,但正如上面代碼註釋中提到的,這種方法只能在Unix系統上使用,跨平臺應用仍然需要純Makefile語法。
我們知道,Makefile的通配符命令可以部分實現類似find的功能。例如,$(通配符*。c)可用於查找。當前目錄下的c文件。不幸的是,通配符畢竟不夠強大,該命令的結果不包括。子目錄下的c文件。要實現這個功能,可以借用大神在StackOverflow上用純Makefile語法寫的遞歸通配符:
#遞歸通配符
Rwildcard = $ (foreach d,$(通配符$1 \ *),$(調用Rwildcard,$ d/,$2) $ (filter $ (subst *,%,$2),$ d))rwildcard命令傳入兩個參數,第壹個。該命令首先使用$(通配符$1*)獲取目錄中的所有文件和壹級子目錄,然後再次遍歷:對於當前$d變量為目錄的情況,遞歸調用rwildcard到$d/目錄;對於$d是普通文件的情況,會因為$(通配符$d/*)找不到匹配而終止遞歸調用,然後調用filter函數過濾$2的模式。
完整的代碼如下:
SRC_SUFFIX := *。cpp *。c
SRC_ROOT := $(LOCAL_PATH)/../../類別
#遞歸通配符
rwildcard = $(foreach d,$(通配符$1\*),$(調用rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)))
SRC_FILES := $(調用rwildcard,$(SRC_ROOT)/,$(SRC_SUFFIX))
LOCAL _ SRC _ FILES:= hello CPP/main . CPP
LOCAL _ SRC _ FILES+= $(SRC \ _ FILES:$(LOCAL _ PATH)/% = %)
過濾掉不需要編譯的源代碼文件。
上面描述的方法有壹個適用的前提,就是$SRC_ROOT下的每壹個源代碼文件都需要編譯。有時候這個條件不成立。比如這個項目中使用了壹些外部庫,這些庫的源代碼不需要編譯(比如Asio庫設置為ASIO_HEADER_ONLY)。這時候妳需要把這部分源代碼從LOCAL_SRC_FILES中排除掉。
第壹種方法:過濾
第壹種方法是使用Makefile的filter-out命令:
# ASIO庫被設置為ASIO _頭_唯壹,所以它將被排除在源代碼之外
EXCLUDE _ SRC _ FILES:= $(SRC _ ROOT)/3rd party/Asio/Asio/impl/%。卡片打印處理機(Card Print Processor的縮寫)
EXCLUDE:= $(filter $(EXCLUDE _ SRC _ FILES),$(SRC_FILES))
src _ files:= $(filter-out $(exclude _ src _ files),$ (src _ files))雖然這個方法可行,但是filter-out不能用於多級目錄的模式匹配,所以這個方法暴露了太多關於外部庫的源代碼路徑的細節。是否可以指定要排除的庫名或關鍵字,然後根據這些信息篩選出匹配的源代碼文件?
第二種方法:改進rwildcard
第二種方式是給rwildcard添加壹個判斷進行過濾:如果當前目錄/文件名與要過濾的關鍵字匹配,則不做任何處理;否則,繼續遞歸調用並執行filter命令。
# ASIO庫被設置為ASIO _頭_唯壹,所以它將被排除
排除_LIB := Asio
#遞歸通配符
rwildcard = $(foreach d,$(通配符$1\*),$(if $(findstring $(EXCLUDE_LIB),$d),,$(調用rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)))
Src _ files: = $ (call rwildcard,$ (src _ root)/,$ (src _ suffix))這個方法比較好,遞歸通配符搜索時直接排除,但是rwildcard變得比較復雜,可讀性差。
第三種方法:FILTER_OUT_PATTERN
最後壹種方法也來自於StackOverflow用純Makefile語法修改的filter-out,但本質上和第二種方法的實現差不多,這裏就不詳細解釋了:
# ASIO庫被設置為ASIO _頭_唯壹,所以它將被排除在源代碼之外
EXCLUDE_SRC_PATTERN := asio
FILTER_OUT_PATTERN = $(foreach v,$(2),$(if $(findstring $(1),$(v)),$(v))
SRC_FILES := $(調用過濾器\_OUT\_PATTERN,$(排除_SRC_PATTERN),$(SRC_FILES))