Android編譯系統中頭文件搜索路徑的順序問題
今天在編譯一個代碼時發現Android編譯系統在設置頭文件搜索路徑的順序上好像有些問題。Android編譯系統本身設置了一堆公共的頭文件搜索路徑(參見pathmap.mk中pathmap_INCL的定義),然后允許每個項目在自己的Android.mk中通過LOCAL_C_INCLUSES 來添加獨特的搜索路徑。按照一般的想法,在最后的編譯參數中,項目自己獨特的搜索路徑應該放在公共搜索路徑之前,這樣,一旦出現頭文件名沖突的情況,會優 先使用項目自己指定的頭文件。但是在Android的編譯系統中情況并非如此,項目自定義的頭文件搜索路徑反而被放在了最后。參見 definitions.mk文件里的下面這個定義:
- define transform-cpp-to-o
- @mkdir -p $(dir $@)
- @echo "target $(PRIVATE_ARM_MODE) C++: $(PRIVATE_MODULE) <= $<"
- $(hide) $(PRIVATE_CXX) \
- $(foreach incdir, \
- $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
- $(TARGET_PROJECT_INCLUDES) \
- $(TARGET_C_INCLUDES) \
- ) \
- $(PRIVATE_C_INCLUDES) \
- , \
- -I $(incdir) \
- ) \
- -c \
- $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
- $(TARGET_GLOBAL_CFLAGS) \
- $(TARGET_GLOBAL_CPPFLAGS) \
- $(PRIVATE_ARM_CFLAGS) \
- ) \
- -fno-rtti \
- $(PRIVATE_CFLAGS) \
- $(PRIVATE_CPPFLAGS) \
- $(PRIVATE_DEBUG_CFLAGS) \
- -MD -o $@ $<
- $(hide) $(transform-d-to-p)
- endef
這個定義就是編譯C++文件使用的命令行。注意紅字部分,PRIVATE_C_INCLUDES中包含了項目的LOCAL_C_INCLUDES的定義 (參見binary.mk)。明顯項目自定義的搜索路徑被放在了最后。后面還有C文件的編譯命令行的定義(define transform-c-or-s-to-o-no-deps)也同樣如此。
不知道Android這樣設計是出于什么考慮。我嘗試把順序調整一下,看是否會影響Android的編譯。上述定義調整之后如下:
- define transform-cpp-to-o
- @mkdir -p $(dir $@)
- @echo "target $(PRIVATE_ARM_MODE) C++: $(PRIVATE_MODULE) <= $<"
- $(hide) $(PRIVATE_CXX) \
- $(foreach incdir, \
- $(PRIVATE_C_INCLUDES) \
- $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
- $(TARGET_PROJECT_INCLUDES) \
- $(TARGET_C_INCLUDES) \
- ) \
- , \
- -I $(incdir) \
- ) \
- -c \
- $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
- $(TARGET_GLOBAL_CFLAGS) \
- $(TARGET_GLOBAL_CPPFLAGS) \
- $(PRIVATE_ARM_CFLAGS) \
- ) \
- -fno-rtti \
- $(PRIVATE_CFLAGS) \
- $(PRIVATE_CPPFLAGS) \
- $(PRIVATE_DEBUG_CFLAGS) \
- -MD -o $@ $<
- $(hide) $(transform-d-to-p)
- endef
對define transform-c-or-s-to-o-no-deps也做類似調整。重新編譯后發現只有webkit的編譯有問題。原因在于webkit的代碼中 包含了幾個STL的頭文件(WebKit/android/stl),特別是其中的strings與bionic定義的頭文件沖突,在調整頭文件搜索順序 后,優先選擇了這個文件。這個strings文件其實是一個空文件(除了注釋沒有任何語句),干脆刪除了它,果然編譯順利進行了,一直到編譯完成再也沒有 出現問題。看來上述調整時可行的。我用的android源代碼版本是2.0,其它版本沒有試過不知道怎么樣。BTW,如果想在編譯時打印出編譯命令,在make的參數中加上SHOW_COMMANDS=1即可。


























