Android build system note

很是有用的記錄,感謝做者!
=======================================html

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
====================
java

相關文章
相關標籤/搜索