Android build system note

來源:互聯網
上載者:User
關鍵字: Android , build system

非常有用的記錄,感謝作者!
=======================================

1. Android編譯系統分析
編譯指令碼及系統變數
build/envsetup.sh指令碼分析
在編譯原始碼之前通常需要在android原始碼頂層目錄執行 . ./build/envsetup.sh 目的是為了使用
指令碼 envsetup.sh 裡面定義了一些函數:
function help()
function get_abs_build_var()
function get_build_var()
function check_product()
function check_variant()
function setpaths()
function printconfig()
function set_stuff_for_environment()
function set_sequence_number()
function settitle()
function choosetype()
function chooseproduct()
function choosevariant()
function tapas()
function choosecombo()
function print_lunch_menu()
function lunch()
function gettop
function m()
function findmakefile()
function mm()
function mmm()
function croot()
function pid()
function gdbclient()
function jgrep()
function cgrep()
function resgrep()
function getprebuilt
function tracedmdump()
function runhat()
function getbugreports()
function startviewserver()
function stopviewserver()
function isviewserverstarted()
function smoketest()
function runtest()
function runtest_py()
function godir ()

choosecombo 命令分析:
function choosecombo()
{
choosesim $1
echo
echo
choosetype $2

echo
echo
chooseproduct $3

echo
echo
choosevariant $4

echo
set_stuff_for_environment
printconfig
}
會依次進行如下選擇:
Build for the simulator or the device?
1. Device
2. Simulator
Which would you like? [1] 

Build type choices are:
1. release
2. debug
Which would you like? [1] 

Product choices are:
1. emulator
2. generic
3. sim
4. littleton
You can also type the name of a product if you know it.
Which would you like? [littleton] 

Variant choices are:
1. user
2. userdebug
3. eng
Which would you like? [eng] user
預設選擇以後會出現:
TARGET_PRODUCT=littleton
TARGET_BUILD_VARIANT=user
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=
==========
function chooseproduct()函數分析:
choices=(`/bin/ls build/target/board/*/BoardConfig.mk vendor/*/*/BoardConfig.mk 2> /dev/null`)
讀取 build/target/board/* 目錄下的板設定檔:BoardConfig.mk
讀取 vendor/*/*/目錄下的板設定檔:BoardConfig.mk
choices 的值為:
build/target/board/emulator/BoardConfig.mk
build/target/board/generic/BoardConfig.mk
build/target/board/sim/BoardConfig.mk
vendor/marvell/littleton/BoardConfig.mk
經過:
for choice in ${choices[@]}
do
# The product name is the name of the directory containing
# the makefile we found, above.
prodlist=(${prodlist[@]} `dirname ${choice} | xargs basename`)
done
的處理,prodlist的值為:
emulator generic sim littleton
所以選擇菜單為:
Product choices are:
1. emulator
2. generic
3. sim
4. littleton
如果選擇 4,那麼 TARGET_PRODUCT 被賦值為: littleton。

board_config_mk := /
$(strip $(wildcard /
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk /
vendor/*/$(TARGET_DEVICE)/BoardConfig.mk /
))

怎樣添加一個模組
LOCAL_PATH:= $(call my-dir)
#編譯靜態庫
include $(CLEAR_VARS)
LOCAL_MODULE = libhellos
LOCAL_CFLAGS = $(L_CFLAGS)
LOCAL_SRC_FILES = hellos.c
LOCAL_C_INCLUDES = $(INCLUDES)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_COPY_HEADERS_TO := libhellos
LOCAL_COPY_HEADERS := hellos.h
include $(BUILD_STATIC_LIBRARY)

#編譯動態庫
include $(CLEAR_VARS)
LOCAL_MODULE = libhellod
LOCAL_CFLAGS = $(L_CFLAGS)
LOCAL_SRC_FILES = hellod.c
LOCAL_C_INCLUDES = $(INCLUDES)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_COPY_HEADERS_TO := libhellod
LOCAL_COPY_HEADERS := hellod.h
include $(BUILD_SHARED_LIBRARY)

BUILD_TEST=true
ifeq ($(BUILD_TEST),true)
#使用靜態庫
include $(CLEAR_VARS)
LOCAL_MODULE := hellos
LOCAL_STATIC_LIBRARIES := libhellos
LOCAL_SHARED_LIBRARIES :=
LOCAL_LDLIBS += -ldl
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := mains.c
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)

#使用動態庫
include $(CLEAR_VARS)
LOCAL_MODULE := hellod
LOCAL_MODULE_TAGS := debug
LOCAL_SHARED_LIBRARIES := libc libcutils libhellod
LOCAL_LDLIBS += -ldl
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := maind.c
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)
endif # ifeq ($(WPA_BUILD_SUPPLICANT),true)

########################
#local_target_dir := $(TARGET_OUT)/etc/wifi
#include $(CLEAR_VARS)
#LOCAL_MODULE := wpa_supplicant.conf
#LOCAL_MODULE_TAGS := user
#LOCAL_MODULE_CLASS := ETC
#LOCAL_MODULE_PATH := $(local_target_dir)
#LOCAL_SRC_FILES := $(LOCAL_MODULE)
#include $(BUILD_PREBUILT)
########################
系統變數解析
LOCAL_MODULE - 編譯的目標對象
LOCAL_SRC_FILES - 編譯的源檔案
LOCAL_C_INCLUDES - 需要包含的標頭檔目錄
LOCAL_SHARED_LIBRARIES - 連結時需要的外部庫
LOCAL_PRELINK_MODULE - 是否需要prelink處理
BUILD_SHARED_LIBRARY - 指明要編譯成動態庫

LOCAL_PATH - 編譯時間的目錄
$(call 目錄,目錄….) 目錄引入操作符
如該目錄下有個檔案夾名稱 src,則可以這樣寫 $(call src),那麼就會得到 src 目錄的完整路徑

include $(CLEAR_VARS) -清除之前的一些系統變數
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
在 build/core/config.mk 定義 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
通過include 包含自訂的.mk檔案(即是自訂編譯規則)或是引用系統其他的.mk檔案(系統定義的編譯規則)。

LOCAL_SRC_FILES - 編譯的源檔案
可以是.c, .cpp, .java, .S(彙編檔案)或是.aidl等格式
不同的檔案用空格隔開。如果編譯目錄子目錄,採用相對路徑,如子目錄/檔案名稱。也可以通過$(call 目錄),指明編譯某目錄
下所有.c/.cpp/.java/.S/ .aidl檔案.追加檔案 LOCAL_SRC_FILES += 檔案

LOCAL_C_INCLUDES - 需要包含的標頭檔目錄
可以是系統定義路徑,也可以是相對路徑. 如該編譯目錄下有個include目錄,寫法是include/*.h

LOCAL_SHARED_LIBRARIES - 連結時需要的外部共用庫
LOCAL_STATIC_LIBRA RIES - 連結時需要的外部外部靜態
LOCAL_JAVA_LIBRARIES 加入jar包

LOCAL_MODULE - 編譯的目標對象
module 是指系統的 native code,通常針對c,c++代碼
./system/core/sh/Android.mk:32:LOCAL_MODULE:= sh
./system/core/libcutils/Android.mk:71:LOCAL_MODULE := libcutils
./system/core/cpio/Android.mk:9:LOCAL_MODULE := mkbootfs
./system/core/mkbootimg/Android.mk:8:LOCAL_MODULE := mkbootimg
./system/core/toolbox/Android.mk:61:LOCAL_MODULE:= toolbox
./system/core/logcat/Android.mk:10:LOCAL_MODULE:= logcat
./system/core/adb/Android.mk:65:LOCAL_MODULE := adb
./system/core/adb/Android.mk:125:LOCAL_MODULE := adbd
./system/core/init/Android.mk:20:LOCAL_MODULE:= init
./system/core/vold/Android.mk:24:LOCAL_MODULE:= vold
./system/core/mountd/Android.mk:13:LOCAL_MODULE:= mountd

LOCAL_PACKAGE_NAME 
Java 應用程式的名字用該變數定義
./packages/apps/Music/Android.mk:9:LOCAL_PACKAGE_NAME := Music
./packages/apps/Browser/Android.mk:14:LOCAL_PACKAGE_NAME := Browser
./packages/apps/Settings/Android.mk:8:LOCAL_PACKAGE_NAME := Settings
./packages/apps/Stk/Android.mk:10:LOCAL_PACKAGE_NAME := Stk
./packages/apps/Contacts/Android.mk:10:LOCAL_PACKAGE_NAME := Contacts
./packages/apps/Mms/Android.mk:8:LOCAL_PACKAGE_NAME := Mms
./packages/apps/Camera/Android.mk:8:LOCAL_PACKAGE_NAME := Camera
./packages/apps/Phone/Android.mk:11:LOCAL_PACKAGE_NAME := Phone
./packages/apps/VoiceDialer/Android.mk:8:LOCAL_PACKAGE_NAME := VoiceDialer

BUILD_SHARED_LIBRARY - 指明要編譯成動態庫。
編譯的目標,用include 操作符
UILD_STATIC_LIBRARY來指明要編譯成靜態庫。
如果是java檔案的話,會用到系統的編譯指令碼host_java_library.mk,用BUILD_PACKAGE來指明。三個編譯
-------------------
include $(BUILD_STATIC_LIBRARY)
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
-------------------
include $(BUILD_SHARED_LIBRARY)
./build/core/config.mk:50:BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
-------------------
include $(BUILD_HOST_SHARED_LIBRARY)
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
-------------------
include $(BUILD_EXECUTABLE)
build/core/config.mk:51:BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
-------------------
include $(BUILD_HOST_EXECUTABLE)
./build/core/config.mk:53:BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
-------------------
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
-------------------
BUILD_JAVA_LIBRARY
./build/core/config.mk:58:BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
------------------
BUILD_STATIC_JAVA_LIBRARY 編譯靜態JAVA庫
./build/core/config.mk:59:BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
------------------
BUILD_HOST_JAVA_LIBRARY 編譯本機用的JAVA庫
./build/core/config.mk:60:BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
------------------

BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
BUILD_KEY_CHAR_MAP := $(BUILD_SYSTEM)/key_char_map.mk

============
LOCAL_PRELINK_MODULE
Prelink利用事先連結代替運行時連結的方法來加速共用庫的載入,它不僅可以加快起動速度,還可以減少部分記憶體開銷,
是各種Linux架構上用於減少程式載入時間、縮短系統啟動時間和加快應用程式啟動的很受歡迎的一個工具。程式運行時的
動態連結尤其是重定位(relocation)的開銷對於大型系統來說是很大的。
動態連結和載入的過程開銷很大,並且在大多數的系統上, 函數庫並不會常常被更動, 每次程式被執行時所進行的連結
動作都是完全相同的,對於嵌入式系統來說尤其如此。因此,這一過程可以改在運行時之前就可以預先處理好,即花一些時間
利用Prelink工具對動態共用程式庫和可執行檔進行處理,修改這些二進位檔案並加入相應的重定位等資訊,節約了本來在程式
啟動時的比較耗時的查詢函數地址等工作,這樣可以減少程式啟動的時間,同時也減少了記憶體的耗用。 
Prelink的這種做法當然也有代價:每次更新動態共用程式庫時,相關的可執行檔都需要重新執行一遍Prelink才能保
證有效,因為新的共用庫中的符號資訊、地址等很可能與原來的已經不同了,這就是為什麼 android framework代碼一改動,
這時候就會導致相關的應用程式重新被編譯。
這種代價對於嵌入式系統的開發人員來說可能稍微帶來一些複雜度,不過好在對使用者來說幾乎是可以忽略的。
--------------------
變數設定為false那麼將不做prelink操作
LOCAL_PRELINK_MODULE := false
預設是需要prlink的,同時需要在 build/core/prelink-linux-arm.map 中加入
libhellod.so 0x96000000
這個map檔案好像是制定動態庫的地址的,在前面注釋上面有一些位址範圍的資訊,注意庫與庫之間的間隔數,
如果指定不好的話編譯的時候會提示說地址空間衝突的問題。另外,注意排序,這裡要把數大的放到前面去,
按照大小降序排序。
解析 LOCAL_PRELINK_MODULE 變數
build/core/dynamic_binary.mk:94:ifeq ($(LOCAL_PRELINK_MODULE),true)
ifeq ($(LOCAL_PRELINK_MODULE),true)
$(prelink_output): $(prelink_input) $(TARGET_PRELINKER_MAP) $(APRIORI)
$(transform-to-prelinked)
transform-to-prelinked定義:
./build/core/definitions.mk:1002:define transform-to-prelinked
define transform-to-prelinked
@mkdir -p $(dir $@)
@echo "target Prelink: $(PRIVATE_MODULE) ($@)"
$(hide) $(APRIORI) /
--prelinkmap $(TARGET_PRELINKER_MAP) /
--locals-only /
--quiet /
$< /
--output $@
endef
./build/core/config.mk:183:APRIORI := $(HOST_OUT_EXECUTABLES)/apriori$(HOST_EXECUTABLE_SUFFIX)
prelink工具不是常用的prelink而是apriori,其原始碼位於” <your_android>/build/tools/apriori”
參考文檔:
動態庫最佳化——Prelink(預串連)技術
http://www.eefocus.com/article/09-04/71629s.html

===============
LOCAL_ARM_MODE := arm
目前Android大部分都是基於Arm處理器的,Arm指令用兩種模式Thumb(每條指令兩個位元組)和arm指令(每條指令四個位元組)

LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
通過設定編譯器操作,最佳化層級,-O0表示沒有最佳化,-O1為預設值,-O3最佳化層級最高
LOCAL_CFLAGS += -W -Wall
LOCAL_CFLAGS += -fPIC -DPIC
LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -DSH_HISTORY
LOCAL_CFLAGS += -DUSEOVERLAY2
根據條件選擇相應的編譯參數
ifeq ($(TARGET_ARCH),arm)
LOCAL_CFLAGS += -DANDROID_GADGET=1
LOCAL_CFLAGS := $(PV_CFLAGS)
endif
ifeq ($(TARGET_BUILD_TYPE),release)
LOCAL_CFLAGS += -O2
endif

LOCAL_LDLIBS := -lpthread
LOCAL_LDLIBS += -ldl

ifdef USE_MARVELL_MVED
LOCAL_WHOLE_STATIC_LIBRARIES += lib_il_mpeg4aspdecmved_wmmx2lnx lib_il_h264decmved_wmmx2lnx
LOCAL_SHARED_LIBRARIES += libMrvlMVED
else
LOCAL_WHOLE_STATIC_LIBRARIES += lib_il_h264dec_wmmx2lnx lib_il_mpeg4aspdec_wmmx2lnx
endif
====================

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.