Android7.1.2源碼解析系列】Android編譯系統翻譯------Android_Build_System(/build/core/build-system.html)

Android編譯系統

狀態:草稿(2006年5月18日)

正文:

目的:

編譯android系統工作的主要目的在於:

(1)使得依賴關係工作時更加的值得信賴,即當文件需要重新編譯時可以被正確的執行;

(2)提升編譯系統的表現,即不必要的模塊不需要重新編譯,而且如果很少的或者根本沒有需要重新編譯的文件時,在根目錄下的編譯操作會使用盡可能少的時間。

原則與用例與策略:

根據上述的目的,接下來的這些就是我們會支持的所有原則與用例。但這不是一個非常詳盡的列表。

多個目標:

在android平臺上進行多目標的編譯是需要的,這意味着:

(1)編譯系統將會支持編譯主平臺上的工具,同時包括在編譯過程中自身用到的工具和開發者用到的工具(比如說仿真機);

(2)編譯系統需要能夠在linux(明確包括Goobuntu和Grhat)、MacOS以及一定程度上在Windows上編譯工具;

(3)編譯系統需要能夠在linux上編譯android操作系統,並且在短期內支持Mac。注意停止在windows上編譯android操作系統是一個有主動的決定。我們將會依賴於仿真器(emulator)而不會使用模擬器(simulator)。這是一個要求,因爲仿真器的未來看起來更加的光明。

不可迴歸的編譯:

爲了實現這個目的,編譯系統需要被重寫來使得編譯過程不可迴歸。更多的背景知識在:http://aegis.sourceforge.net/auug97.pdf,非pdf版:http://72.14.203.104/search?q=cache:HwuX7YF2uBIJ:aegis.sourceforge.net/auug97.pdf&hl=en&gl=us&ct=clnk&cd=2&client=firefox。

快速編譯測試:

當開發一個組件時,例如一個c++共享庫,需要能夠簡單地單獨編譯該組件,而不是需要耗費很多時間等待大量的依賴項檢查和不需要的組件的編譯。

環境和配置文件的基本設置:

爲了設置目標和其他的選項,隊伍裏的一些人想要在一個目錄中有一個配置文件這樣他們就不需要運行一個環境配置腳本,而其他人想要一個可運行的環境配置腳本這樣他們就可以在不同的終端進行相同的編譯操作,或者在同一個終端進行回退或者更新。我們對於兩種方式都支持。

目標文件目錄/清除命令(make clean):

目標文件和其他的中間文件需要被整合到同一個在源碼樹中分開的目錄下。清除命令(make clean)的目標是實現和根目錄下的”rm -rf”一樣的功能。這裏主要的目標就是可以簡單地在源碼樹進行檢索,而且使得”make clean”更加值得信賴。

SDK:

SDK將會是一個壓縮包,它允許非操作系統開發者能夠編寫app。實際上app會在第一次編譯SDK時進行編譯,並且在以後通過SDK來編譯app。這將會:

(1)使得編寫app更加的簡單,因爲我們不會總是重新編譯android操作系統,並且我們可以使用支持的java-app開發工具來開發app;

(2)允許我們通過”dog-food”測試來幫助確定SDK的質量。

Cedric建議(而且我認同)通過SDK編譯的app應該用ant來編譯。請關注更多的細節,因爲我們需要明確的指出他們怎麼工作。

依賴關係:

依賴關係應該是自動的。除非有定製的工具被使用了(比如webkit中有一些),動態庫和靜態庫以及c\cpp\h\java\java libraries庫等等的依賴關係都應該在不干預Android.mk文件的前提下工作。

隱藏命令行:

默認條件下編譯系統會在命令行中隱藏編譯過程中的執行步驟。是否隱藏執行命令可以通過命令showcommands來指明需要顯示的目標,也可以通過設置環境變量來修改。

通配符源文件:

通配符源文件會是不被鼓勵的。它可能會在一些情境下有用。當前的目錄被設置到編譯目錄的根目錄時,默認的通配符$(wildcard *)不會起效果。

單目錄中的多個目標:

可能會需要在一個給定的子目錄中生成超過一個目標。比如說,libutils爲目標產生了一個共享庫並且爲主機產生了一個靜態庫。

模塊的Makefile片段:

Android.mk是控制編譯所給出模塊的makefile片段的標準名稱。只有頂層目錄才應該有一個名爲”Makefile”的文件。

使用共享庫:

現在,模擬器(simulator)已經不再被編譯來使用共享庫。這個是應該被修復的,而且現在是一個做這件事的好時機。這暗示着需要將共享庫運行在Mac操作系統上。

很高興能夠擁有這些:

這些東西應該被快樂的擁有着,並且這裏是一個記錄他們的好地方,雖然這裏沒有任何的承諾。

同時編譯:

我們希望可以同時在同一個目錄樹下爲了不同的組合進行兩個編譯,但是這是一個延伸的目標,不是一個要求。不過非同時地在同一個目錄下進行兩個編譯是必須的工作。(更新:看起來我們好像會實現同時同一目錄的編譯功能)

刪除頭文件(或者其他的依賴):

當你刪除一個被”.d”文件中引用到的頭文件時,問題可能就會出現。簡單的處理方式是”make clean”。這裏應該有一個更好的方式來處理它(由fadden提出)。

一個解決的方式是在目錄中介紹依賴。問題是這個方式可能會造成額外的依賴結構並且降低編譯的速度。這是一個取捨。

複合編譯:

表現已知平臺的集合的編譯過程的主要方式。這會更加簡單地在測試一個修改時表現複合平臺的編譯,並且允許一個大規模的”make clean”。現在buildspec.mk或者環境變量需要在每一次的編譯中被更新(fadden提出)。

售後市場的場所和載體(Aftermarket Locales and Carrier):

我們最終會需要爲創建場所和載體的自定義SDK添加支持,但是不會是現在。

使用:

現在你已經閱讀了(或者瀏覽了)所有的編譯系統的動機,並且你想要了解怎麼去使用它。現在就讓我們開始吧。

你的第一次編譯:

編譯文檔(building.html)描述了怎麼進行編譯:

Build/envsetup.sh的功能:

如果你將文件build/envsetup.sh放入你的bash環境當中,你會獲得一些有幫助的shell命令功能:

(1)printconfig------打印當前通過lunch命令以及choosecombo命令設置的配置;

(2)m------從頂層目錄執行make命令。這是很有用的,因爲這樣你就可以在子目錄裏面執行make命令。如果你設置了top這個環境變量,它就會被使用。如果你沒有,它會從當前目錄進行搜索,直到找到目錄的頂部;

(3)croot-----跳轉到目錄的頂部;

(4)sgrep-----通過你提供的正則表達式來過濾當前目錄下所有的c\cpp\h\java\xml文件。

編譯特點/種類:

當編譯一個特殊的產品時,擁有一個鏡像的最終的編譯結果的變量的數據常常是有用的。這裏是一些當前定義了的特徵和種類(我們需要爲他們確定一個真正的名稱)

eng

這是默認的特徵. 一個簡單的”make”等同於”make eng”. droid 是 eng的別名.

· 安裝標記爲: eng, debug, user, 以及/或者 development的模塊。

· 安裝沒有特殊標籤的非apk模塊。

· 通過產品定義的文件安裝未標記的apk.

· ro.secure=0

· ro.debuggable=1

· ro.kernel.android.checkjni=1

· Adb默認開啓。

user

“make user”

這是最終成爲release版本的代碼的特徵。

· 安裝標籤爲user的模塊.

· 安裝沒有特殊標籤的非apk模塊。

· 通過產品定義文件安裝apk; 對於apk模塊來說標籤是被忽略的。

· ro.secure=1

· ro.debuggable=0

· Adb默認關閉。

userdebug

“make userdebug”

與user相同, 除了:

· 也安裝標籤爲 debug的模塊。

· ro.debuggable=1

· Adb默認開啓。

如果你編譯了一個特徵然後接着編譯另一個,你應該在兩次編譯之間運行”make installclean”命令來確認你沒有選擇上一個特徵時安裝的文件。”make clean”命令也可以,不過會耗費大量額外的時間。

更多的僞目標:

有時候你只想要編譯一個小部分。下列的僞目標可以使你更加方便:

(1)droid------make droid是通常的編譯方式。這個目標在這是因爲默認的目標必須要有一個名稱。

(2)All-----make all編譯了每一個make droid編譯的文件,而且編譯了每一個LOCAL_MODULE_TAGS中沒有包含”droid”標籤的文件。編譯服務運行這個命令是爲了確定每一個源碼樹中有Android.mk文件的模塊都被編譯了。

(3)Clean-(LOCALMODULE)clean(LOCAL_MODULE)以及clean-(LOCAL_PACKAGE_NAME)-----使你可選擇地清除一個目標。比如,你可以使用make clean-libutils命令然後它將會刪除libutils.so以及所有的中間文件,或者你可以使用make clean-Home命令然後它就會清除Home app。

(4)Clean-----make clean刪除當前配置的輸出和中間文件。這個命令等同於rm -rf out//

(5)Clobber-----make clobber刪除所有配置當中的輸出以及中間文件。這個命令等同於rm -rf out/。

(6)Dataclean-----make dataclean刪除在當前組合目錄中的數據目錄內容。這個命令對於仿真器(emulator)和模擬器(simulator)特別地有用,因爲其中的數據會在多次編譯中持久的保存。

(7)Showcommands-----showcommands是一個可修改的目標,它會造成編譯系統顯示編譯步驟當中的實際命令行。更多的人喜歡看到明確的描述而不是命令行,因爲命令行相當長而且很難閱讀,但如果你抱着debug的目的,你可以把showcommands加入到你要編譯的目標當中。比如說make showcommands會編譯默認的android配置,而make runtime showcommands只會編譯runtime以及它依賴的目標並且顯示命令行,請記住這裏有一些命令行不顯示的地方。這被認爲是bug,而且應該被修復,但是他們通常很難被追蹤。如果你找到了,請告知android編譯小隊。

(8)LOCAL_MODULE-----任何在Android.mk當中被你選中來作爲一個LOCAL_MODULE的對象都會被編譯到一個僞目標當中。

(9)Targets------make targets 會打印一個你能編譯的LOCAL_MODULE的所有名稱列表。

怎樣添加一個組件到Android.mk的編譯模塊當中:

你有一個新的庫、app或者一個新的可執行文件。對於每一個模板中的通用種類,都有一個在模板目錄當中與之對應的文件。通常複製其中之一併且填入你自己的值就已經夠了。一些更加少用的值沒有被包含到模塊當中,但通過文檔進行了替代,正如文檔中記錄了用自定義的工具來生成文件的方法。

通常的,你可以通過查看模塊中的TODO註釋並且按照它的內容來做。請記住完成後刪除TODO註釋來保證文件集的乾淨整潔。模塊有着最小的文檔說明,因爲他們可能會被複制到其他地方,這樣當文檔變得過時需要更新的時候,複製的內容卻不會得到更新。所以請繼續閱讀…

Apps:

使用 templates/apps 文件。

這個模板相當的自解釋。看下面的變量來了解更多的細節。

Java 庫:

使用templates/java_library文件

有意思的事是這裏LOCAL_MODULE的值成爲了jar文件的名稱。(事實上現在我們還沒有編譯jar文件,僅僅編譯了.class文件的目錄,但是目錄是通過你放在LOCAL_MODULE中的內容來命名的)這個名稱會放到對應模塊的LOCAL_JAVA_LIBRARIES當中,它們依賴於你的java庫。

C/C++ 可執行文件:

使用templates/executable文件,或者templates/executable_host文件。

這個模板有一些你平常不需要的額外的選項。請刪除掉你不需要的部分,並且移除掉TODO註釋。這使得剩下的部分更加容易閱讀,而且你總是可以在需要他們的時候再次使用這些模板。

默認的,在target當中的c/c++可執行文件被編譯到/system/bin當中,host當中的被編譯到/host/bin當中。這些可以通過設置LOCAL_MODULE_PATH或者LOCAL_MODUL_RELATIVE_PATH來進行修改。查看Putting targets elsewhere(build-system.html#moving-targets文件)來獲取更多信息。

共享庫:

使用templates/shared_library文件或者templates/shared_library_host文件。

記住在這個目標當中,我們使用了共享庫,並且在主機中,我們使用了靜態庫,因爲發行後可執行文件的大小不是固定的,而且它簡化了在SDK中的介紹。

使用自定義工具:

如果你有一個爲你自己生成源文件的工具,使得這個編譯系統爲你的工具獲取正確的依賴關係。這裏有一些例子。$@在編譯當中的含義是“當前的目標”。紅色的部分是你需要修改的部分。

你需要把這個流程放到你已經明確了LOCAL_PATH以及LOCAL_MODULE之後,因爲(localgeneratedsourcesdir)(local-generated-sources-dir)和(local-host-generated-sources-dir)大量地使用到這兩個變量來指明把文件放到哪裏。

例子1:

這裏有一個已經生成的文件,叫做chartables.c,它並不依賴於任何文件。而且是被編譯在$(HOST_OUT_EXEUTABLES)/dftables的文件編譯的。把依賴於工具的信息記錄到倒數第二行。

intermediates:= $(local-generated-sources-dir)

GEN := $(intermediates)/chartables.c

$(GEN): PRIVATE_CUSTOM_TOOL = $(HOST_OUT_EXECUTABLES)/dftables $@

$(GEN): $(HOST_OUT_EXECUTABLES)/dftables

$(transform-generated-source)

LOCAL_GENERATED_SOURCES += $(GEN)

例子2:

這裏有一個假定的例子,我們使用cat命令來傳遞一個文件。假定它做了一些有用的事。記錄我們使用了一個目標明確的名爲PRIVATE_INPUT_FILE的變量來存儲輸入文件的名稱。

intermediates:= $(local-generated-sources-dir)

GEN := $(intermediates)/file.c

$(GEN): PRIVATE_INPUT_FILE := $(LOCAL_PATH)/input.file

$(GEN): PRIVATE_CUSTOM_TOOL = cat $(PRIVATE_INPUT_FILE) > $@

$(GEN): $(LOCAL_PATH)/file.c

$(transform-generated-source)

LOCAL_GENERATED_SOURCES += $(GEN)

例子3:

如果你有一些名字類似的文件,並且使用了相同的工具,你可以把他們組合起來。(這裏的*.lut.h文件是生成的文件,*.cpp文件是輸入的文件)

intermediates:= $(local-generated-sources-dir)

GEN := $(addprefix $(intermediates)/kjs/, \

        array_object.lut.h \

        bool_object.lut.h \

    )

$(GEN): PRIVATE_CUSTOM_TOOL = perl libs/WebKitLib/WebKit/JavaScriptCore/kjs/create_hash_table $< -i > $@

$(GEN): $(intermediates)/%.lut.h : $(LOCAL_PATH)/%.cpp

$(transform-generated-source)

LOCAL_GENERATED_SOURCES += $(GEN)

平臺的特殊環境:

有時候你需要爲不同的平臺設置特別的標籤。這裏有一個已定義的變量將被設置到的編譯系統的值的列表和一些例子。

編譯一個硬件的時候,TARGET_OS是linux(我們在使用linux),並且TARGET_ARCH是arm。

編譯一個模擬器的時候,TARGET_OS和TARGET_ARCH被設置爲和HOST_OS一樣而且HOST_ARCH取決於你的平臺。TARGET_PRODUCT是你正在編譯的hardware/product目標的名稱。sim的值被用於模擬器。我們還沒有考慮過在這裏會發生的全流程定製,但是似乎這裏會有額外的針對性的UI配置。

HOST_OS
linux
darwin
(cygwin)

HOST_ARCH
x86

HOST_BUILD_TYPE
release
debug

TARGET_OS
linux
darwin
(cygwin)

TARGET_ARCH
arm
x86

TARGET_BUILD_TYPE
release
debug

TARGET_PRODUCT
sim
dream
sooner

一些例子:

ifeq ($(TARGET_BUILD_TYPE),release)

LOCAL_CFLAGS += -DNDEBUG=1

endif

from libutils

ifeq ($(TARGET_OS),linux)

Use the futex based mutex and condition variable

implementation from android-arm because it’s shared mem safe

LOCAL_SRC_FILES += futex_synchro.c

LOCAL_LDLIBS += -lrt -ldl

endif

把模塊放到其他地方:

如果你有在一些地方能正常使用的模塊,並且你需要讓它們在其他地方進行編譯,閱讀接下來的內容。

如果你有一些需要運行在它們本來的位置的子目錄的模塊,比如說HAL模塊需要被運行在/system/lib/hw或者/vendor/lib/hw裏面,在你的Android.mk文件中對LOCAL_MODUL_RELATIVE_PATH進行設置,比如:

LOCAL_MODUL_RELATIVE_PATH := hw

如果你有一些需要在完全不同的位置運行的模塊,比如不是在/system中的根文件系統,把這些行加入到你的Android.mk文件當中:

LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)

LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)

對於可執行文件以及庫文件,如果你明確了一個LOCAL_MODULE_PATH,你需要指明一個LOCAL_UNSTRIPPED_PATH位置,因爲在目標編譯中,我們保持了未剝離的可執行文件,所以GDB可以找到這些記號。LOCAL_UNSTRIPPED_PATH不是必要的,如果你只是指明瞭LOCAL_MODULE_RELATIVE_PATH。

查看config/envsetup.make 來得到所有定義了需要編譯文件的位置的變量。

FYI:如果你正在安裝一個可執行文件到/bin目錄下,你可能也想要把LOCAL_FORCE_STATIC_EXCUTABLE := true設置到你的Android.mk文件當中,這會強制連接器只接受靜態庫。

Android.mk 變量

這些是你會常常在Android.mk文件當中看到的變量,按照字母順序進行了列舉。

但是首先,是變量的名稱:

(1)LOCAL_------這些變量在每個模塊中都被設置。他們被命令include $(CLEAR_VARS)清理,所以你可以在包含include $(CLEAR_VARS)命令後,相信他們是空的。在你會使用的大多數的模塊中的大多數變量都是LOCAL_變量。

(2)PRIVATE_------這些變量是編譯指定目標的變量。那意味着他們只在特定模塊的命令當中是有用的。這也意味着他們不太可能在你所包含的模塊結束後發生改變。這個鏈接與編譯的文檔(http://www.gnu.org/software/make/manual/make.html#Target_002dspecific)描述了更多的指定目標的變量。請記住有些源碼樹中的私有變量沒有以PRIVATE_作爲前綴。這是安全的,並且他們會在他們被發現的時候被修復。對於造成的疑惑道歉。

(3)INTERNAL_------這些變量是對編譯系統的功能至關重要的,所以你不應該創建以這個作爲前綴的變量,並且你也許也並不應該在你的makefile文件中弄亂這些變量。

(4)HOST_和TARGET_------這些變量包含了明確指向主機以及目標的目錄以及定義。不要在你的makefile文件當中設置以HOST_或者TARGET開始的變量。

(5)BUILD_和CLEAR_VARS------這些變量包含了需要包含的定義好的模板makefile文件。一些例子是CLEAR_VARS和BUILD_HOST_PACKAGE。

(6)任何在你的Android.mk文件當中的其他名稱的使用都是公平的。然而,記住這是一個不可迴歸的編譯系統,所以你的變量可能會被另一個更晚包含的Android.mk文件修改,並且在你的規則或者模塊的命令執行時變得不一樣。

LOCAL_ASSET_FILES:

在Android.mk文件當中include $(BUILD_PACKAGE)將下面的句子設置到了你想要設置到的你的app的文件集合當中,通常是:

LOCAL_ASSET_FILES += $(call find-subdir-assets)

當我們選擇ant作爲app的編譯系統時,這個可能會改變。

LOCAL_CC:

如果你想要在模塊當中使用一個不同的C編譯器,設置LOCAL_CC爲編譯器的路徑。如果LOCAL_CC是空白的,適合的默認編譯器將被使用。

LOCAL_CXX:

如果你想要在模塊中使用一個不一樣的C++編譯器,把LOCAL_CXX設置爲編譯器的路徑。如果LOCAL_CXX是空白的,適合的默認編譯器將被使用。

LOCAL_CFLAGS:

如果你有額外的標籤來傳遞到C/C++編譯器,把他們加到這裏。比如說:

LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1

LOCAL_CPPFLAGS:

如果你有隻傳遞給C++編譯器的額外標籤,把他們加到這。比如說:

LOCAL_CPPFLAGS += -ffriend-injection

LOCAL_CPPFLAGS 被保證會放在LOCAL_CFLAGS的編譯行之後,所以你可以使用它來覆蓋LOCAL_CFLAGS列表中的標籤。

LOCAL_CPP_EXTENSION:

如果你的C++文件以非”.cpp”來結尾,你可以在這裏指明自定義擴展名;現在混合不同的擴展名是不可能的。

LOCAL_NO_DEFAULT_COMPILER_FLAGS:

通常的,這條編譯命令在C/C++文件中包含了全局包含路徑和全局CFLAGS。如果LOCAL_NO_DEFAULT_COMPILER_FLAGS非空,當前模塊模塊的C/C++文件的編譯時沒有默認的包含或者標籤會被使用。LOCAL_C_INCLUDES,LOCAL_CFLAGS,和LOCAL_CPPFLAGS依然會載這個模塊中被使用,同時任何在模塊中被定義的DEBUG_CFLAGS也都會被使用。

LOCAL_COPY_HEADERS:

即將被移除

需要被複制到安裝的包含樹的文件集合。你同時也必須要支持LOCAL_COPY_HEADERS_TO。

此變量將被移除的原因是複製頭文件使得錯誤信息變得混亂,並且可能會導致人們編輯那些不正確的頭文件。這也會導致系統中更容易出現錯誤的層級,這是我們想要避免的。我們也沒有在製作一個C/C++ SDK,所以這裏沒有一個複製任何頭文件的根本需求。

LOCAL_COPY_HEADERS_TO

即將被移除

一個把LOCAL_COPY_HEADER中列舉的頭文件所複製到的目錄。

此變量將被移除的原因是複製頭文件使得錯誤信息變得混亂,並且可能會導致人們編輯那些不正確的頭文件。這也會導致系統中更容易出現錯誤的層級,這是我們想要避免的。我們也沒有在製作一個C/C++ SDK,所以這裏沒有一個複製任何頭文件的根本需求。

LOCAL_C_INCLUDES:

額外的目錄來通知C/C++編譯器在其中尋找頭文件。這些路徑起始於源代碼樹的根目錄。如果你想要把你自己的子目錄加入到包含路徑當中,使用LOCAL_PATH變量。比如說:

LOCAL_C_INCLUDES += extlibs/zlib-1.2.3

LOCAL_C_INCLUDES += $(LOCAL_PATH)/src

但是你不應該把包含的子目錄再加入到LOCAL_C_INCLUDES當中,同時你應該把那些文件引用到他們的子目錄中的#include狀態當中。比如說:

#include <utils/KeyedVector.h>

而不是 #include <KeyedVector.h>

有一些組件在處理這個變量時是錯誤的,並且應當被清除。

LOCAL_REQUIRED_MODULES:

用任何以空白分開的模塊名設置LOCAL_REQUIRED_MODULES,比如”libblah”或者”Email”。如果這個模塊被安裝了,所有它需求的模塊都會被安裝。這個變量可以被用來確認當一個給予的app安裝時必要的共享庫或者提供者被安裝了。

LOCAL_FORCE_STATIC_EXECUTABLE:

如果你的可執行文件需要被靜態鏈接,設置LOCAL_FORCE_STATOC_EXECUTABLE:=true。有一個我們採用靜態模式執行的非常小的庫的列表(現在只有libc)。這個變量只被用於根目錄下的/sbin的可執行文件。

LOCAL_GENERATED_SOURCES:

被添加到LOCAL_GENERATED_SOURCES當中的文件會在你的模塊被編譯的時候自動的生成並鏈接。閱讀自定義工具(build-system.html#custom-tools)模塊中的makefile文件來獲取一個例子。

LOCAL_JAVACFLAGS:

如果你有要傳遞給javac編譯器的額外的標籤,把他們加到這裏。比如說:

LOCAL_JAVACFLAGS += -Xlint:deprecation

LOCAL_JAVA_LIBRARIES:

當鏈接Java apps和庫的時候,LOCAL_JAVA_LIBRARIES明確了需要包含的java類集合。現在這些集合有兩個:core和framework。在大多數的場合,它會看起來像接下來的東西:

LOCAL_JAVA_LIBRARIES := core framework

記住在通過”include $(BUILD_PACKAGE)”編譯一個APK時設置LOCAL_JAVA_LIBRARIES是不必要的(同時也是不允許的)。適合的庫會被自動的包含。

LOCAL_LDFLAGS:

你可以通過設置LOCAL_LDFLAGS來把額外的標籤傳遞給連接器。記住參數的順序對於ld是十分重要的,所以不管你做了什麼,在所有的平臺上進行測試。

LOCAL_LDLIBS:

LOCAL_LDLIBS允許你指明不屬於你的可執行文件或者庫的編譯部分的額外的庫。用-lxxx的形式來指明你想要的庫;他們會被直接傳遞到鏈接的命令行。然而,記住不會有任何的依賴產生到這些庫上面。當你想要使用一個在主機上預先安裝的庫來編譯一個仿真機的時候,這個變量將會非常有用。連接器是一個非常挑剔的老頑固,所以有時候傳遞一些其他的標籤到這裏會變得非常重要,如果你在做一些鬼鬼祟祟的小動作的話。比如說:

LOCAL_LDLIBS += -lcurses -lpthread

LOCAL_LDLIBS += -Wl, -z, origin

LOCAL_NO_MANIFEST:

如果你的包不包含一個manifest(AndroidManigest.xml),那麼設置LOCAL_NO_MANIFEST := true。普通的資源包這麼做了。

LOCAL_PACKAGE_NAME:

LOCAL_PACKAGE_NAME是app的名字。比如說,Dialer,Contacts,等等。它可能

會改變或者消失,當我們切換到一個基於ant的app編譯系統時。

LOCAL_PATH:

你的Android.mk文件所在的目錄。你可以通過把接下來的內容放到你的Android.mk文件的第一行來設置它:

LOCAL_PATH := $(my-dir)

my-dir大量地使用了MAKEFILE_LIST(http://www.gnu.org/software/make/manual/make.html#MAKEFILE_005fLIST-Variable)文件中的變量,所以在你包含任何其他的makefile文件前調用它。同時,

考慮到你包含的任何子目錄都可能重置LOCAL_PATH,所以在包含他們之前設置好這些內容。這同樣也意味着如果你想要寫入幾行include來引用LOCAL_PATH,它不會生效,因爲那些引用到的makefile文件可能會重置LOCAL_PATH。

LOCAL_POST_PROCESS_COMMAND:

對於可執行的主機文件,你可以指定一個命令行使得一個模塊被鏈接後直接運行。你可能不得不經過一些曲折的道路來使得變量名正確,由於一些或早或晚的變量診斷:

module := (HOSTOUTEXECUTABLES)/(HOST_OUT_EXECUTABLES)/(LOCAL_MODULE)

LOCAL_POST_PROCESS_COMMAND := /Developer/Tools/Rez -d DARWIN -t APPL\

   -d __WXMAC__ -o $(module) Carbon.r

LOCAL_PREBUILT_EXECUTABLES:

當包含(BUILDPREBUILT)(BUILD_PREBUILT)或者(BUILD_HOST_PREBUILT)的時候,把這些設置到你想要複製的可執行文件裏。他們會自動的置入到正確的bin目錄下。

LOCAL_PREBUILT_LIBS:

當包含(BUILDPREBUILT)(BUILD_PREBUILT)或者(BUILD_HOST_PREBUILT)的時候,把這些庫設置到你想要複製的可執行文件裏。他們會自動的置入到正確的bin目錄下。

LOCAL_SHARED_LIBRAIES:

這些是你將要直接鏈接的庫。你不需要過渡性的傳遞包含的庫。不加後綴的指明這些文件:

LOCAL_SHARED_LIBRARIES := \

 libutils \

libui \

 libaudio \

 libexpat \

 libsgl

LOCAL_SRC_FILES:

編譯系統通過查看LOCAL_SRC_FILES來知道哪些源文件需要被編譯-----.cpp/.c/.y/.l/.java。對於lex和yacc文件,他知道如何正確的自動進行.h/和.c/.cpp文件的中轉。如果文件是在一個包含了Android.mk的子目錄當中,在他們前面加上目錄的名稱:

LOCAL_SRC_FILES := \

 file1.cpp \

  dir/file2.cpp

LOCAL_STATIC_LIBRARIES:

這些是你想要加入到你的模塊當中的靜態庫。總的來說,我們使用共享庫,但是有些地方,比如bin目錄下的可執行文件以及主機可執行文件,我們使用了靜態庫來替代。

LOCAL_STATIC_LIBRARIES := \

 libutils \

  libtinyxml

LOCAL_MODULE:

LOCAL_MODULE是被期望於產生在你的Android.mk當中(編譯後生成)的名字。比如說,對於libkjs,LOCAL_MODULE是”libkjs”(編譯系統添加了合適的後綴------.so/.dylib/.dll)。對於app模塊,使用LOCAL_PACKAGE_NAME而不是LOCAL_MODULE。我們正在計劃切換到ant來編譯app,所以這個還是值得討論的。

LOCAL_MODULE_PATH:

通知編譯系統來將模塊放置到對於它的類型不是通常要放到的地方。如果你覆寫了這個變量,確定你也設置了LOCAL_UNSTRIPPED_PATH,因爲如果它不是一個可執行文件或者共享庫,至少這個未拆開的二進制有地方來進行存放。如果你忘記了設置LOCAL_UNSTRIPPED_PATH,一個錯誤會被報出來。

閱讀本文的把模塊放到其他地方來獲取更多信息。

LOCAL_MODULE_RELATIVE_PATH:

通知編譯系統來將一個模塊放置到它的類型通常需要放到的目錄的子目錄下。如果你設置了這個,你就可以不需要設置LOCAL_UNSTRIPPED_PATH,未拆分的二進制文件也會使用關聯的路徑。

閱讀本文的把模塊放到其他地方來獲取更多信息。

LOCAL_UNSTRIPPED_PATH:

通知編譯系統來把未明確版本的模塊來放到對於它的版本不通常放到的地方。通常的,你覆寫了這個是因爲你爲了一個可執行文件或者共享庫修改了LOCAL_MODULE_PATH變量。如果你覆寫了LOCAL_MODULE_PATH變量,但是沒有覆寫LOCAL_UNSTRIPPED變量,一個錯誤將會發生。

閱讀本文的把模塊放到其他地方來獲取更多信息。

LOCAL_WHOLE_STATIC_LIBRARIES:

這些是一些你想要在不允許連接器刪除掉過時的代碼的情況下包含到你的模塊中的靜態庫。它最有用的地方是當你想要把一個靜態庫加入到共享庫而且使得這個靜態庫的內容暴露給共享庫時。

LOCAL_WHOLE_STATIC_LIBRARIES := \

Libsqlite3_android

LOCAL_YACCFLAGS:

任何傳遞給你的模塊的yacc調用。這裏一個已知的限制是你的模塊中的所有YACC的調用都是相同的。這個可以被修復。如果你曾經希望它變成這樣,只需要問我們。

LOCAL_YACCFLAGS := -o kjsyy

實現細節:

除非你正在添加一個新的平臺、工具或者添加新的特性到編譯系統,你永遠也不應該接觸到配置目錄中的任何內容。總的來說,在你走入android編譯系統的泥潭前,請先請教編譯系統的擁有者(android編譯小隊mailto:android-build-team)。也就是說,這裏有一些在表面之下的筆記。

環境配置/buildspec.mk 版本:

爲了使得人們能夠更簡單地修改編譯系統,當改變buildspec.mk或者重新運行環境配置腳本變得必要時,他們在BUILD_ENV_SEQUENCE_NUMBER當中包含了一個版本號。如果這個變量並不與編譯系統預期的相對應,編譯就會失敗並打印出錯誤信息來解釋發生了什麼。如果你做了一個需要更新的改動,你需要更新兩個地方,然後消息纔會被打印。

(1)在config/envsetup.make中,增長CORRECT_BUILD_ENV_SEQUENCE_NUMBER的定義。

(2)在buildspec.mk.default中,更新BUILD_ENV_SEQUENCE_DUMBER定義來與config/envsetup.make中的其中一個進行對應。

自動化腳本從編譯系統當中取得值,所以他們也會觸發警告。

額外的makefile變量:

你也許不應該使用這些變量。在使用他們之前請去請教android編譯小隊。這些主要是爲了其他重大問題的工作或者是並沒有完全正確運行的東西。

LOCAL_ADDITIONAL_DEPENDENCIES:

如果你的模塊需要依賴於任何並不在其中編譯的東西,你可以把這些編譯目標加入到LOCAL_ADDITIONAL_DEPENDENCIES當中。通常的這是一個爲了一些非自動化創建的依賴關係工作的工作區。

LOCAL_BUILT_MODULE:

當一個模塊被編譯時,這個模塊被創建到一箇中間目錄然後複製到最終的位置。LOCAL_BUILT_MODULE是中間文件的全路徑。查看LOCAL_INSTALLED_MODULE來了解模塊的最終安裝位置的路徑。

LOCAL_HOST:

通過host_xxx.make的包含關係的設置來告訴base_rules.make和其他的我們正在爲主機編譯的包含文件。Kenneth把這個做成了openbinder的一部分,並且我更喜歡將它清空所以規則、包含關係和定義不會在主機和目標之間重複。

LOCAL_INSTALLED_MODULE:

模塊最終所處的位置的路徑的全稱。查看LOCAL_BUILT_MODULE來了解中間文件的位置,這些文件實際表明了變異規則構造的方式。

LOCAL_REPLACE_VARS:

用於一些遺留的openbinder的特殊值集合的編譯腳本的資料。

LOCAL_SCRIPTS:

用於一些openbinder編譯系統中我們也許會發現方便的腳本文件。

LOCAL_MODULE_CLASS:

這是一種模塊。這個變量被用於創建其他的用來放置模塊的其他變量名。查看base_rules.make和envsetup.make。

LOCAL_MODULE_NAME:

設置爲LOCAL_BUILT_MODULE的葉名字。我不確定,但是看起來它被用在WHO_AM_I變量來確定漂亮的打印出什麼在被編譯。

LOCAL_MODULE_SUFFIX:

後綴會被追加到LOCAL_MODULE來形成LOCAL_MODULE_NAME。比如說,.so/.a/.dylib。

LOCAL_STRIP_MODULE:

通過在base_rules.make文件中計算來指明是否這個模塊應該真正的被剝離,基於是否LOCAL_STRIPPABLE_MODULE被設置,以及是否這個組合在曾經的剝離模塊當中被配置。在Iliyan的剝離工具中,這個可能會改變。

LOCAL_STRIPPABLE_MODULE:

通過包含makefile文件來設置,如果模塊是可剝離的。可執行文件和共享庫都是這樣。

LOCAL_SYSTEM_SHARED_LIBRARIES:

當編譯基本庫:libc、libm、libdl時被使用。通常它被設置爲”none”,正如在$(CLEAR_VARS)中。當編譯這些庫的時候,它被設置爲他們鏈接的目標。比如說,libc,libstdc++和libdl並不和其他任何東西鏈接,並且libm鏈接到libc。通常的,當值爲none的時候,這些變量會自動的鏈接到可執行文件和庫,所以你不需要手動的指明他們。

原文:

Android Build System
Status: Draft (as of May 18, 2006)

Contents

Objective
The primary goals of reworking the build system are (1) to make dependencies work more reliably, so that when files need to rebuilt, they are, and (2) to improve performance of the build system so that unnecessary modules are not rebuilt, and so doing a top-level build when little or nothing needs to be done for a build takes as little time as possible.

Principles and Use Cases and Policy
Given the above objective, these are the overall principles and use cases that we will support. This is not an exhaustive list.

Multiple Targets
It needs to be possible to build the Android platform for multiple targets. This means:

· The build system will support building tools for the host platform, both ones that are used in the build process itself, and developer tools like the simulator.

· The build system will need to be able to build tools on Linux (definitely Goobuntu and maybe Grhat), MacOS, and to some degree on Windows.

· The build system will need to be able to build the OS on Linux, and in the short-term, MacOS. Note that this is a conscious decision to stop building the OS on Windows. We are going to rely on the emulator there and not attempt to use the simulator. This is a requirement change now that the emulator story is looking brighter.

Non-Recursive Make
To achieve the objectives, the build system will be rewritten to use make non-recursively. For more background on this, readRecursive Make Considered Harmful. For those that don’t want PDF, here is theGoogle translated version.

Rapid Compile-Test Cycles
When developing a component, for example a C++ shared library, it must be possible to easily rebuild just that component, and not have to wait more than a couple seconds for dependency checks, and not have to wait for unneeded components to be built.

Both Environment and Config File Based Settings
To set the target, and other options, some people on the team like to have a configuration file in a directory so they do not have an environment setup script to run, and others want an environment setup script to run so they can run builds in different terminals on the same tree, or switch back and forth in one terminal. We will support both.

Object File Directory / make clean
Object files and other intermediate files will be generated into a directory that is separate from the source tree. The goal is to have make clean be "rm -rf " in the tree root directory. The primary goals of this are to simplify searching the source tree, and to make “make clean” more reliable.

SDK
The SDK will be a tarball that will allow non-OS-developers to write apps. The apps will actually be built by first building the SDK, and then building the apps against that SDK. This will hopefully (1) make writing apps easier for us, because we won’t have to rebuild the OS as much, and we can use the standard java-app development tools, and (2) allow us to dog-food the SDK, to help ensure its quality. Cedric has suggested (and I agree) that apps built from the SDK should be built with ant. Stay tuned for more details as we figure out exactly how this will work.

Dependecies
Dependencies should all be automatic. Unless there is a custom tool involved (e.g. the webkit has several), the dependencies for shared and static libraries, .c, .cpp, .h, .java, java libraries, etc., should all work without intervention in the Android.mk file.

Hiding command lines
The default of the build system will be to hide the command lines being executed for make steps. It will be possible to override this by specifying the showcommands pseudo-target, and possibly by setting an environment variable.

Wildcard source files
Wildcarding source file will be discouraged. It may be useful in some scenarios. The default $(wildcard *) will not work due to the current directory being set to the root of the build tree.

Multiple targets in one directory
It will be possible to generate more than one target from a given subdirectory. For example, libutils generates a shared library for the target and a static library for the host.

Makefile fragments for modules
Android.mk is the standard name for the makefile fragments that control the building of a given module. Only the top directory should have a file named “Makefile”.

Use shared libraries
Currently, the simulator is not built to use shared libraries. This should be fixed, and now is a good time to do it. This implies getting shared libraries to work on Mac OS.

Nice to Have
These things would be nice to have, and this is a good place to record them, however these are not promises.

Simultaneous Builds
The hope is to be able to do two builds for different combos in the same tree at the same time, but this is a stretch goal, not a requirement. Doing two builds in the same tree, not at the same time must work. (update: it’s looking like we’ll get the two builds at the same time working)

Deleting headers (or other dependecies)
Problems can arise if you delete a header file that is referenced in “.d” files. The easy way to deal with this is “make clean”. There should be a better way to handle it. (from fadden)

One way of solving this is introducing a dependency on the directory. The problem is that this can create extra dependecies and slow down the build. It’s a tradeoff.

Multiple builds
General way to perform builds across the set of known platforms. This would make it easy to perform multiple platform builds when testing a change, and allow a wide-scale “make clean”. Right now the buildspec.mk or environment variables need to be updated before each build. (from fadden)

Aftermarket Locales and Carrier
We will eventually need to add support for creating locales and carrier customizations to the SDK, but that will not be addressed right now.

Usage
You’ve read (or scrolled past) all of the motivations for this build system, and you want to know how to use it. This is the place.

Your first build
The Building document describes how do do builds.

build/envsetup.sh functions
If you source the file build/envsetup.sh into your bash environment, . build/envsetup.shyou’ll get a few helpful shell functions:

· printconfig - Prints the current configuration as set by the lunch and choosecombo commands.

· m - Runs make from the top of the tree. This is useful because you can run make from within subdirectories. If you have the TOP environment variable set, it uses that. If you don’t, it looks up the tree from the current directory, trying to find the top of the tree.

· croot - cd to the top of the tree.

· sgrep - grep for the regex you provide in all .c, .cpp, .h, .java, and .xml files below the current directory.

Build flavors/types
When building for a particular product, it’s often useful to have minor variations on what is ultimately the final release build. These are the currently-defined “flavors” or “types” (we need to settle on a real name for these).

eng

This is the default flavor. A plain “make” is the same as “make eng”. droid is an alias for eng.

· Installs modules tagged with: eng, debug, user, and/or development.

· Installs non-APK modules that have no tags specified.

· Installs APKs according to the product definition files, in addition to tagged APKs.

· ro.secure=0

· ro.debuggable=1

· ro.kernel.android.checkjni=1

· adb is enabled by default.

user

“make user”

This is the flavor intended to be the final release bits.

· Installs modules tagged with user.

· Installs non-APK modules that have no tags specified.

· Installs APKs according to the product definition files; tags are ignored for APK modules.

· ro.secure=1

· ro.debuggable=0

· adb is disabled by default.

userdebug

“make userdebug”

The same as user, except:

· Also installs modules tagged with debug.

· ro.debuggable=1

· adb is enabled by default.

If you build one flavor and then want to build another, you should run “make installclean” between the two makes to guarantee that you don’t pick up files installed by the previous flavor. “make clean” will also suffice, but it takes a lot longer.

More pseudotargets
Sometimes you want to just build one thing. The following pseudotargets are there for your convenience:

· droid - make droid is the normal build. This target is here because the default target has to have a name.

· all - make all builds everything make droid does, plus everything whose LOCAL_MODULE_TAGS do not include the “droid” tag. The build server runs this to make sure that everything that is in the tree and has an Android.mk builds.

· clean-(LOCALMODULE)andclean(LOCAL_MODULE) and clean-(LOCAL_PACKAGE_NAME) - Let you selectively clean one target. For example, you can type make clean-libutils and it will delete libutils.so and all of the intermediate files, or you can type make clean-Home and it will clean just the Home app.

· clean - make clean deletes all of the output and intermediate files for this configuration. This is the same as rm -rf out//

· clobber - make clobber deletes all of the output and intermediate files for all configurations. This is the same as rm -rf out/.

· dataclean - make dataclean deletes contents of the data directory inside the current combo directory. This is especially useful on the simulator and emulator, where the persistent data remains present between builds.

· showcommands - showcommands is a modifier target which causes the build system to show the actual command lines for the build steps, instead of the brief descriptions. Most people don’t like seeing the actual commands, because they’re quite long and hard to read, but if you need to for debugging purposes, you can add showcommands to the list of targets you build. For example make showcommands will build the default android configuration, and make runtime showcommands will build just the runtime, and targets that it depends on, while displaying the full command lines. Please note that there are a couple places where the commands aren’t shown here. These are considered bugs, and should be fixed, but they’re often hard to track down. Please let android-build-team know if you find any.

· LOCAL_MODULE - Anything you specify as a LOCAL_MODULE in an Android.mk is made into a pseudotarget. For example, make runtime might be shorthand for make out/linux-x86-debug/system/bin/runtime (which would work), and make libkjs might be shorthand for make out/linux-x86-debug/system/lib/libkjs.so (which would also work).

· targets - make targets will print a list of all of the LOCAL_MODULE names you can make.

How to add another component to the build - Android.mk templates
You have a new library, a new app, or a new executable. For each of the common types of modules, there is a corresponding file in the templates directory. It will usually be enough to copy one of these, and fill in your own values. Some of the more esoteric values are not included in the templates, but are instead just documented here, as is the documentation on using custom tools to generate files.

Mostly, you can just look for the TODO comments in the templates and do what it says. Please remember to delete the TODO comments when you’re done to keep the files clean. The templates have minimal documentation in them, because they’re going to be copied, and when that gets stale, the copies just won’t get updated. So read on…

Apps
Use the templates/apps file.

This template is pretty self-explanitory. See the variables below for more details.

Java Libraries
Use the templates/java_library file.

The interesting thing here is the value of LOCAL_MODULE, which becomes the name of the jar file. (Actually right now, we’re not making jar files yet, just directories of .class files, but the directory is named according to what you put in LOCAL_MODULE). This name will be what goes in the LOCAL_JAVA_LIBRARIES variable in modules that depend on your java library.

C/C++ Executables
Use the templates/executable file, or the templates/executable_host file.

This template has a couple extra options that you usually don’t need. Please delete the ones you don’t need, and remove the TODO comments. It makes the rest of them easier to read, and you can always refer back to the templates if you need them again later.

By default, on the target these are built into /system/bin, and on the host, they’re built into /host/bin. These can be overridden by setting LOCAL_MODULE_PATH or LOCAL_MODULE_RELATIVE_PATH. SeePutting targets elsewhere for more.

Shared Libraries
Use the templates/shared_library file, or the templates/shared_library_host file.

Remember that on the target, we use shared libraries, and on the host, we use static libraries, since executable size isn’t as big an issue, and it simplifies distribution in the SDK.

Static Libraries
Use the templates/static_library file, or the templates/static_library_host file.

Remember that on the target, we use shared libraries, and on the host, we use static libraries, since executable size isn’t as big an issue, and it simplifies distribution in the SDK.

Using Custom Tools
If you have a tool that generates source files for you, it’s possible to have the build system get the dependencies correct for it. Here are a couple of examples. $@ is the make built-in variable for “the current target.” Thered parts are the parts you’ll need to change.

You need to put this after you have declared LOCAL_PATH and LOCAL_MODULE, because the $(local-generated-sources-dir) and $(local-host-generated-sources-dir) macros use these variables to determine where to put the files.

Example 1
Here, there is one generated file, called chartables.c, which doesn’t depend on anything. And is built by the tool built to $(HOST_OUT_EXECUTABLES)/dftables. Note on the second to last line that a dependency is created on the tool.

intermediates:= $(local-generated-sources-dir)

GEN := $(intermediates)/chartables.c

$(GEN): PRIVATE_CUSTOM_TOOL = $(HOST_OUT_EXECUTABLES)/dftables $@

$(GEN): $(HOST_OUT_EXECUTABLES)/dftables

$(transform-generated-source)

LOCAL_GENERATED_SOURCES += $(GEN)

Example 2
Here as a hypothetical example, we use use cat as if it were to transform a file. Pretend that it does something useful. Note how we use a target-specific variable called PRIVATE_INPUT_FILE to store the name of the input file.

intermediates:= $(local-generated-sources-dir)

GEN := $(intermediates)/file.c

$(GEN): PRIVATE_INPUT_FILE := $(LOCAL_PATH)/input.file

$(GEN): PRIVATE_CUSTOM_TOOL = cat $(PRIVATE_INPUT_FILE) > $@

$(GEN): $(LOCAL_PATH)/file.c

$(transform-generated-source)

LOCAL_GENERATED_SOURCES += $(GEN)

Example 3
If you have several files that are all similar in name, and use the same tool, you can combine them. (here the *.lut.h files are the generated ones, and the *.cpp files are the input files)

intermediates:= $(local-generated-sources-dir)

GEN := $(addprefix $(intermediates)/kjs/, \

        array_object.lut.h \

        bool_object.lut.h \

    )

$(GEN): PRIVATE_CUSTOM_TOOL = perl libs/WebKitLib/WebKit/JavaScriptCore/kjs/create_hash_table $< -i > $@

$(GEN): $(intermediates)/%.lut.h : $(LOCAL_PATH)/%.cpp

$(transform-generated-source)

LOCAL_GENERATED_SOURCES += $(GEN)

Platform specific conditionals
Sometimes you need to set flags specifically for different platforms. Here is a list of which values the different build-system defined variables will be set to and some examples.

For a device build, TARGET_OS is linux (we’re using linux!), and TARGET_ARCH is arm.

For a simulator build, TARGET_OS and TARGET_ARCH are set to the same as HOST_OS and HOST_ARCH are on your platform. TARGET_PRODUCT is the name of the target hardware/product you are building for. The value sim is used for the simulator. We haven’t thought through the full extent of customization that will happen here, but likely there will be additional UI configurations specified here as well.

HOST_OS
linux
darwin
(cygwin)

HOST_ARCH
x86

HOST_BUILD_TYPE
release
debug

TARGET_OS
linux
darwin
(cygwin)

TARGET_ARCH
arm
x86

TARGET_BUILD_TYPE
release
debug

TARGET_PRODUCT
sim
dream
sooner

Some Examples
ifeq ($(TARGET_BUILD_TYPE),release)

LOCAL_CFLAGS += -DNDEBUG=1

endif

from libutils

ifeq ($(TARGET_OS),linux)

Use the futex based mutex and condition variable

implementation from android-arm because it’s shared mem safe

LOCAL_SRC_FILES += futex_synchro.c

LOCAL_LDLIBS += -lrt -ldl

endif

Putting modules elsewhere
If you have modules that normally go somewhere, and you need to have them build somewhere else, read this.

If you have modules that need to go in a subdirectory of their normal location, for example HAL modules that need to go in /system/lib/hw or /vendor/lib/hw, set LOCAL_MODULE_RELATIVE_PATH in your Android.mk, for example:

LOCAL_MODULE_RELATIVE_PATH := hw

If you have modules that need to go in an entirely different location, for example the root filesystem instead of in /system, add these lines to your Android.mk:

LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)

LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)

For executables and libraries, you need to specify a LOCAL_UNSTRIPPED_PATH location if you specified a LOCAL_MODULE_PATH, because on target builds, we keep the unstripped executables so GDB can find the symbols. LOCAL_UNSTRIPPED_PATH is not necessary if you only specified LOCAL_MODULE_RELATIVE_PATH.

Look in config/envsetup.make for all of the variables defining places to build things.

FYI: If you’re installing an executable to /sbin, you probably also want to set LOCAL_FORCE_STATIC_EXCUTABLE := true in your Android.mk, which will force the linker to only accept static libraries.

Android.mk variables
These are the variables that you’ll commonly see in Android.mk files, listed alphabetically.

But first, a note on variable naming:

· LOCAL_ - These variables are set per-module. They are cleared by the include $(CLEAR_VARS) line, so you can rely on them being empty after including that file. Most of the variables you’ll use in most modules are LOCAL_ variables.

· PRIVATE_ - These variables are make-target-specific variables. That means they’re only usable within the commands for that module. It also means that they’re unlikely to change behind your back from modules that are included after yours. This link to the make documentation describes more about target-specific variables. Please note that there are a couple of these laying around the tree that aren’t prefixed with PRIVATE_. It is safe, and they will be fixed as they are discovered. Sorry for the confusion.

· INTERNAL_ - These variables are critical to functioning of the build system, so you shouldn’t create variables named like this, and you probably shouldn’t be messing with these variables in your makefiles.

· HOST_ and TARGET_ - These contain the directories and definitions that are specific to either the host or the target builds. Do not set variables that start with HOST_ or TARGET_ in your makefiles.

· BUILD_ and CLEAR_VARS - These contain the names of well-defined template makefiles to include. Some examples are CLEAR_VARS and BUILD_HOST_PACKAGE.

· Any other name is fair-game for you to use in your Android.mk. However, remember that this is a non-recursive build system, so it is possible that your variable will be changed by another Android.mk included later, and be different when the commands for your rule / module are executed.

LOCAL_ASSET_FILES
In Android.mk files that include $(BUILD_PACKAGE) set this to the set of files you want built into your app. Usually:

LOCAL_ASSET_FILES += $(call find-subdir-assets)

This will probably change when we switch to ant for the apps’ build system.

LOCAL_CC
If you want to use a different C compiler for this module, set LOCAL_CC to the path to the compiler. If LOCAL_CC is blank, the appropriate default compiler is used.

LOCAL_CXX
If you want to use a different C++ compiler for this module, set LOCAL_CXX to the path to the compiler. If LOCAL_CXX is blank, the appropriate default compiler is used.

LOCAL_CFLAGS
If you have additional flags to pass into the C or C++ compiler, add them here. For example:

LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1

LOCAL_CPPFLAGS
If you have additional flags to pass into only the C++ compiler, add them here. For example:

LOCAL_CPPFLAGS += -ffriend-injection

LOCAL_CPPFLAGS is guaranteed to be after LOCAL_CFLAGS on the compile line, so you can use it to override flags listed in LOCAL_CFLAGS.

LOCAL_CPP_EXTENSION
If your C++ files end in something other than “.cpp”, you can specify the custom extension here. For example:

LOCAL_CPP_EXTENSION := .cc

Note that all C++ files for a given module must have the same extension; it is not currently possible to mix different extensions.

LOCAL_NO_DEFAULT_COMPILER_FLAGS
Normally, the compile line for C and C++ files includes global include paths and global cflags. If LOCAL_NO_DEFAULT_COMPILER_FLAGS is non-empty, none of the default includes or flags will be used when compiling C and C++ files in this module. LOCAL_C_INCLUDES, LOCAL_CFLAGS, and LOCAL_CPPFLAGS will still be used in this case, as will any DEBUG_CFLAGS that are defined for the module.

LOCAL_COPY_HEADERS
This will be going away.

The set of files to copy to the install include tree. You must also supply LOCAL_COPY_HEADERS_TO.

This is going away because copying headers messes up the error messages, and may lead to people editing those headers instead of the correct ones. It also makes it easier to do bad layering in the system, which we want to avoid. We also aren’t doing a C/C++ SDK, so there is no ultimate requirement to copy any headers.

LOCAL_COPY_HEADERS_TO
This will be going away.

The directory within “include” to copy the headers listed in LOCAL_COPY_HEADERS to.

This is going away because copying headers messes up the error messages, and may lead to people editing those headers instead of the correct ones. It also makes it easier to do bad layering in the system, which we want to avoid. We also aren’t doing a C/C++ SDK, so there is no ultimate requirement to copy any headers.

LOCAL_C_INCLUDES
Additional directories to instruct the C/C++ compilers to look for header files in. These paths are rooted at the top of the tree. Use LOCAL_PATH if you have subdirectories of your own that you want in the include paths. For example:

LOCAL_C_INCLUDES += extlibs/zlib-1.2.3
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src

You should not add subdirectories of include to LOCAL_C_INCLUDES, instead you should reference those files in the #include statement with their subdirectories. For example:

#include <utils/KeyedVector.h>
not #include <KeyedVector.h>

There are some components that are doing this wrong, and should be cleaned up.

LOCAL_MODULE_TAGS
Set LOCAL_MODULE_TAGS to any number of whitespace-separated tags. If the tag list is empty or contains droid, the module will get installed as part of a make droid. Otherwise, it will only get installed by running make or with the make all pseudotarget.

LOCAL_REQUIRED_MODULES
Set LOCAL_REQUIRED_MODULES to any number of whitespace-separated module names, like “libblah” or “Email”. If this module is installed, all of the modules that it requires will be installed as well. This can be used to, e.g., ensure that necessary shared libraries or providers are installed when a given app is installed.

LOCAL_FORCE_STATIC_EXECUTABLE
If your executable should be linked statically, set LOCAL_FORCE_STATIC_EXECUTABLE:=true. There is a very short list of libraries that we have in static form (currently only libc). This is really only used for executables in /sbin on the root filesystem.

LOCAL_GENERATED_SOURCES
Files that you add to LOCAL_GENERATED_SOURCES will be automatically generated and then linked in when your module is built. See theCustom Tools template makefile for an example.

LOCAL_JAVACFLAGS
If you have additional flags to pass into the javac compiler, add them here. For example:

LOCAL_JAVACFLAGS += -Xlint:deprecation

LOCAL_JAVA_LIBRARIES
When linking Java apps and libraries, LOCAL_JAVA_LIBRARIES specifies which sets of java classes to include. Currently there are two of these: core and framework. In most cases, it will look like this:

LOCAL_JAVA_LIBRARIES := core framework

Note that setting LOCAL_JAVA_LIBRARIES is not necessary (and is not allowed) when building an APK with “include $(BUILD_PACKAGE)”. The appropriate libraries will be included automatically.

LOCAL_LDFLAGS
You can pass additional flags to the linker by setting LOCAL_LDFLAGS. Keep in mind that the order of parameters is very important to ld, so test whatever you do on all platforms.

LOCAL_LDLIBS
LOCAL_LDLIBS allows you to specify additional libraries that are not part of the build for your executable or library. Specify the libraries you want in -lxxx format; they’re passed directly to the link line. However, keep in mind that there will be no dependency generated for these libraries. It’s most useful in simulator builds where you want to use a library preinstalled on the host. The linker (ld) is a particularly fussy beast, so it’s sometimes necessary to pass other flags here if you’re doing something sneaky. Some examples:

LOCAL_LDLIBS += -lcurses -lpthread
LOCAL_LDLIBS += -Wl,-z,origin

LOCAL_NO_MANIFEST
If your package doesn’t have a manifest (AndroidManifest.xml), then set LOCAL_NO_MANIFEST:=true. The common resources package does this.

LOCAL_PACKAGE_NAME
LOCAL_PACKAGE_NAME is the name of an app. For example, Dialer, Contacts, etc. This will probably change or go away when we switch to an ant-based build system for the apps.

LOCAL_PATH
The directory your Android.mk file is in. You can set it by putting the following as the first line in your Android.mk:

LOCAL_PATH := $(my-dir)

The my-dir macro uses the MAKEFILE_LIST variable, so you must call it before you include any other makefiles. Also, consider that any subdirectories you inlcude might reset LOCAL_PATH, so do your own stuff before you include them. This also means that if you try to write several include lines that reference LOCAL_PATH, it won’t work, because those included makefiles might reset LOCAL_PATH.

LOCAL_POST_PROCESS_COMMAND
For host executables, you can specify a command to run on the module after it’s been linked. You might have to go through some contortions to get variables right because of early or late variable evaluation:

module := (HOSTOUTEXECUTABLES)/(HOST_OUT_EXECUTABLES)/(LOCAL_MODULE)
LOCAL_POST_PROCESS_COMMAND := /Developer/Tools/Rez -d DARWIN -t APPL
-d WXMAC -o $(module) Carbon.r

LOCAL_PREBUILT_EXECUTABLES
When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to executables that you want copied. They’re located automatically into the right bin directory.

LOCAL_PREBUILT_LIBS
When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to libraries that you want copied. They’re located automatically into the right lib directory.

LOCAL_SHARED_LIBRARIES
These are the libraries you directly link against. You don’t need to pass transitively included libraries. Specify the name without the suffix:

LOCAL_SHARED_LIBRARIES :=
libutils
libui
libaudio
libexpat
libsgl

LOCAL_SRC_FILES
The build system looks at LOCAL_SRC_FILES to know what source files to compile – .cpp .c .y .l .java. For lex and yacc files, it knows how to correctly do the intermediate .h and .c/.cpp files automatically. If the files are in a subdirectory of the one containing the Android.mk, prefix them with the directory name:

LOCAL_SRC_FILES :=
file1.cpp
dir/file2.cpp

LOCAL_STATIC_LIBRARIES
These are the static libraries that you want to include in your module. Mostly, we use shared libraries, but there are a couple of places, like executables in sbin and host executables where we use static libraries instead.

LOCAL_STATIC_LIBRARIES :=
libutils
libtinyxml

LOCAL_MODULE
LOCAL_MODULE is the name of what’s supposed to be generated from your Android.mk. For exmample, for libkjs, the LOCAL_MODULE is “libkjs” (the build system adds the appropriate suffix – .so .dylib .dll). For app modules, use LOCAL_PACKAGE_NAME instead of LOCAL_MODULE. We’re planning on switching to ant for the apps, so this might become moot.

LOCAL_MODULE_PATH
Instructs the build system to put the module somewhere other than what’s normal for its type. If you override this, make sure you also set LOCAL_UNSTRIPPED_PATH if it’s an executable or a shared library so the unstripped binary has somewhere to go. An error will occur if you forget to.

See Putting modules elsewhere for more.

LOCAL_MODULE_RELATIVE_PATH
Instructs the build system to put the module in a subdirectory under the directory that is normal for its type. If you set this you do not need to set LOCAL_UNSTRIPPED_PATH, the unstripped binaries will also use the relative path.

See Putting modules elsewhere for more.

LOCAL_UNSTRIPPED_PATH
Instructs the build system to put the unstripped version of the module somewhere other than what’s normal for its type. Usually, you override this because you overrode LOCAL_MODULE_PATH for an executable or a shared library. If you overrode LOCAL_MODULE_PATH, but not LOCAL_UNSTRIPPED_PATH, an error will occur.

See Putting modules elsewhere for more.

LOCAL_WHOLE_STATIC_LIBRARIES
These are the static libraries that you want to include in your module without allowing the linker to remove dead code from them. This is mostly useful if you want to add a static library to a shared library and have the static library’s content exposed from the shared library.

LOCAL_WHOLE_STATIC_LIBRARIES :=
libsqlite3_android

LOCAL_YACCFLAGS
Any flags to pass to invocations of yacc for your module. A known limitation here is that the flags will be the same for all invocations of YACC for your module. This can be fixed. If you ever need it to be, just ask.

LOCAL_YACCFLAGS := -p kjsyy

Implementation Details
You should never have to touch anything in the config directory unless you’re adding a new platform, new tools, or adding new features to the build system. In general, please consult with the build system owner(s) (android-build-team) before you go mucking around in here. That said, here are some notes on what’s going on under the hood.

Environment Setup / buildspec.mk Versioning
In order to make easier for people when the build system changes, when it is necessary to make changes to buildspec.mk or to rerun the environment setup scripts, they contain a version number in the variable BUILD_ENV_SEQUENCE_NUMBER. If this variable does not match what the build system expects, it fails printing an error message explaining what happened. If you make a change that requires an update, you need to update two places so this message will be printed.

· In config/envsetup.make, increment the CORRECT_BUILD_ENV_SEQUENCE_NUMBER definition.

· In buildspec.mk.default, update the BUILD_ENV_SEQUENCE_DUMBER definition to match the one in config/envsetup.make

The scripts automatically get the value from the build system, so they will trigger the warning as well.

Additional makefile variables
You probably shouldn’t use these variables. Please consult android-build-team before using them. These are mostly there for workarounds for other issues, or things that aren’t completely done right.

LOCAL_ADDITIONAL_DEPENDENCIES
If your module needs to depend on anything else that isn’t actually built in to it, you can add those make targets to LOCAL_ADDITIONAL_DEPENDENCIES. Usually this is a workaround for some other dependency that isn’t created automatically.

LOCAL_BUILT_MODULE
When a module is built, the module is created in an intermediate directory then copied to its final location. LOCAL_BUILT_MODULE is the full path to the intermediate file. See LOCAL_INSTALLED_MODULE for the path to the final installed location of the module.

LOCAL_HOST
Set by the host_xxx.make includes to tell base_rules.make and the other includes that we’re building for the host. Kenneth did this as part of openbinder, and I would like to clean it up so the rules, includes and definitions aren’t duplicated for host and target.

LOCAL_INSTALLED_MODULE
The fully qualified path name of the final location of the module. See LOCAL_BUILT_MODULE for the location of the intermediate file that the make rules should actually be constructing.

LOCAL_REPLACE_VARS
Used in some stuff remaining from the openbinder for building scripts with particular values set,

LOCAL_SCRIPTS
Used in some stuff remaining from the openbinder build system that we might find handy some day.

LOCAL_MODULE_CLASS
Which kind of module this is. This variable is used to construct other variable names used to locate the modules. See base_rules.make and envsetup.make.

LOCAL_MODULE_NAME
Set to the leaf name of the LOCAL_BUILT_MODULE. I’m not sure, but it looks like it’s just used in the WHO_AM_I variable to identify in the pretty printing what’s being built.

LOCAL_MODULE_SUFFIX
The suffix that will be appended to LOCAL_MODULE to form LOCAL_MODULE_NAME. For example, .so, .a, .dylib.

LOCAL_STRIP_MODULE
Calculated in base_rules.make to determine if this module should actually be stripped or not, based on whether LOCAL_STRIPPABLE_MODULE is set, and whether the combo is configured to ever strip modules. With Iliyan’s stripping tool, this might change.

LOCAL_STRIPPABLE_MODULE
Set by the include makefiles if that type of module is strippable. Executables and shared libraries are.

LOCAL_SYSTEM_SHARED_LIBRARIES
Used while building the base libraries: libc, libm, libdl. Usually it should be set to “none,” as it is in $(CLEAR_VARS). When building these libraries, it’s set to the ones they link against. For example, libc, libstdc++ and libdl don’t link against anything, and libm links against libc. Normally, when the value is none, these libraries are automatically linked in to executables and libraries, so you don’t need to specify them manually.

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