Android 編譯之a(chǎn)ndroid.mk

引言

Android編譯知識的梳理文章共三篇:

本文是第二篇焰坪,主要介紹android.mk。

1. android系統(tǒng)源碼的編譯流程

來回顧一下常見的編譯步驟:
source build/envsetup.sh
lunch xxx
make -j8 2>&1 | tee build.log
這三步究竟做了什么呢躺苦?我們來逐步分析一下痢掠。

1.1 source build/envsetup.sh

build/envsetup.sh這個文件中定義了一些變量和函數(shù),執(zhí)行source build/envsetup.sh之后砖瞧,envsetup.sh中的變量成了全局變量息堂,而其中的函數(shù)也可以直接在當前終端命令行中使用了。這些函數(shù)可以幫助我們切換目錄块促,查找文件荣堰,可以使我們在編譯源碼時更方便。這些函數(shù)可通過hmm函數(shù)來查看竭翠,下面列出了一些常用的函數(shù):

  • lunch: lunch <product_name>-<build_variant> (選擇要編譯的目標產(chǎn)品和版本)
  • tapas: tapas [<App1> <App2> ...] [arm|x86|mips|armv5] [eng|userdebug|user]
  • croot: Changes directory to the top of the tree.(切換到源碼的頂層目錄)
  • m: Makes from the top of the tree.(從頂層目錄build整個系統(tǒng))
  • mm: Builds all of the modules in the current directory, but not their dependencies.(構(gòu)建當前目錄下所有的模塊振坚,但不包括它們的依賴)
  • mmm: Builds all of the modules in the supplied directories, but not their dependencies.(構(gòu)建指定目錄下所有的模塊,但不包括它們的依賴)
  • mma: Builds all of the modules in the current directory, and their dependencies.(構(gòu)建當前目錄下所有的模塊以及它們所依賴的模塊)
  • mmma: Builds all of the modules in the supplied directories, and their dependencies.(構(gòu)建指定目錄下所有的模塊以及它們所依賴的模塊)
  • provision: Flash device with all required partitions. Options will be passed on to fastboot.(將設備所有需要的分區(qū)刷入斋扰,選項將傳遞給fastboot)
  • cgrep: Greps on all local C/C++ files.(在C渡八,C++文件中搜索指定關鍵字)
  • ggrep: Greps on all local Gradle files.(在gradle文件中搜索指定關鍵字)
  • jgrep: Greps on all local Java files.(在java文件中搜索指定關鍵字)
  • resgrep: Greps on all local res/*.xml files.(在資源xml文件中搜索指定關鍵字)
  • mangrep: Greps on all local AndroidManifest.xml files.(在AndroidManifest.xml文件中搜索指定關鍵字)
  • mgrep: Greps on all local Makefiles files.(在Makefiles和android.mk文件中搜索指定關鍵字)
  • sepgrep: Greps on all local sepolicy files.(在sepolicy文件中搜索指定關鍵字)
  • sgrep: Greps on all local source files.(在所有本地文件中搜索指定關鍵字)
  • godir: Go to the directory containing a file.(切換到包含某個文件的目錄下)

除了hmm提示的這些,還有一些方法传货,具體可以直接查看build/envsetup.sh文件:

  • cproj: 向上切換到最近包含Android.mk的目錄下
  • findmakefile: 打印當前目錄所在工程的Android.mk的文件路徑
  • getsdcardpath: 獲取Sd卡路徑
  • getscreenshotpath: 獲取屏幕截圖的路徑
  • getlastscreenshot: 獲取最后一張截圖,導出到當前目錄下
  • getbugreports: 將bug報告從設備上導出到本地屎鳍,bug報告存放于目錄/sdcard/bugreports
  • gettop: 獲取Android源碼根目錄
  • pid: pid processname 查看某個可執(zhí)行程序?qū)倪M程id
  • key_back: 模擬按返回鍵
  • key_home: 模擬按Home鍵
  • key_menu: 模擬按菜單鍵

envsetup.sh中還定義了add_lunch_combo函數(shù),并且多次執(zhí)行了add_lunch_combo函數(shù)问裕,將自身定義的所有product添加到LUNCH_MENU_CHOICES中:

# Clear this variable.  It will be built up again when the vendorsetup.sh
# files are included at the end of this file.
unset LUNCH_MENU_CHOICES
function add_lunch_combo()
{
    local new_combo=$1
    local c
    for c in ${LUNCH_MENU_CHOICES[@]} ; do
        if [ "$new_combo" = "$c" ] ; then
            return
        fi
    done
    LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
}

# add the default one here
add_lunch_combo aosp_arm-eng
add_lunch_combo aosp_arm64-eng
add_lunch_combo aosp_mips-eng
add_lunch_combo aosp_mips64-eng
add_lunch_combo aosp_x86-eng
add_lunch_combo aosp_x86_64-eng

最后逮壁,envsetup.sh中還遍歷并執(zhí)行vendor和device目錄下的所有vendorsetup.sh文件:

# Execute the contents of any vendorsetup.sh files we can find.
for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
         `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
         `test -d product && find -L product -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort`
do
    echo "including $f"
    . $f
done
unset f

這些vendorsetup.sh中也定義了的一些product,執(zhí)行這些vendorsetup.sh后粮宛,也會將它們當中定義的product添加到LUNCH_MENU_CHOICES中:

add_lunch_combo full_k63v2_64_bsp-eng
add_lunch_combo full_k63v2_64_bsp-user
add_lunch_combo full_k63v2_64_bsp-userdebug

在此之后窥淆,我們就可以在命令行用lunch函數(shù)從LUNCH_MENU_CHOICES中選擇需要編譯的product卖宠。

1.2 lunch

執(zhí)行l(wèi)unch函數(shù)時,如果用戶指定了product祖乳,獲取指定的product逗堵。如果用戶未指定product,調(diào)用print_lunch_menu函數(shù)輸出上一步生成的lunch menu choices讓用戶選擇眷昆。如用戶指定了product或者提示后選擇了product蜒秤,會獲取用戶指定的product,并提取$product和$variant亚斋。然后檢查是否支持product作媚,如不支持,提示不支持并退出帅刊。如支持纸泡,接著會調(diào)用set_stuff_for_environment函數(shù)設置一系列環(huán)境變量,還會調(diào)用printconfig輸出相關變量和配置信息赖瞒。

function lunch()
{
    local answer

    if [ "$1" ] ; then
        answer=$1
    else
        print_lunch_menu
        echo -n "Which would you like? [aosp_arm-eng] "
        read answer
    fi

    local selection=

    if [ -z "$answer" ]
    then
        selection=aosp_arm-eng
    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
    then
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
        then
            selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
        fi
    else
        selection=$answer
    fi

    export TARGET_BUILD_APPS=

    local product variant_and_version variant version

    product=${selection%%-*} # Trim everything after first dash
    variant_and_version=${selection#*-} # Trim everything up to first dash
    if [ "$variant_and_version" != "$selection" ]; then
        variant=${variant_and_version%%-*}
        if [ "$variant" != "$variant_and_version" ]; then
            version=${variant_and_version#*-}
        fi
    fi

    if [ -z "$product" ]
    then
        echo
        echo "Invalid lunch combo: $selection"
        return 1
    fi

    TARGET_PRODUCT=$product \
    TARGET_BUILD_VARIANT=$variant \
    TARGET_PLATFORM_VERSION=$version \
    build_build_var_cache
    if [ $? -ne 0 ]
    then
        return 1
    fi

    export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT)
    export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT)
    if [ -n "$version" ]; then
      export TARGET_PLATFORM_VERSION=$(get_build_var TARGET_PLATFORM_VERSION)
    else
      unset TARGET_PLATFORM_VERSION
    fi
    export TARGET_BUILD_TYPE=release

    echo

    set_stuff_for_environment
    printconfig
    destroy_build_var_cache
}

1.3 make -j8 2>&1 | tee build.log

  • -j8是用于指定編譯的cpu核心女揭,如果編譯服務器配置好,可以略為改大一些栏饮。
  • 2>&1 | tee build.log則是同時輸出編譯的提示吧兔、異常信息到終端和build.log文件中。
  • make則是執(zhí)行make命令袍嬉,尋找源碼根目錄下的Makefile境蔼,解析Makefile并開始整個源碼的編譯。

接下來我們就從源碼根目錄下的Makefile開始逐步解析伺通。

2. android的Makefile和android.mk

執(zhí)行make之后箍土,從源碼根目錄下的Makefile開始逐步解析。該Makefile的內(nèi)容很少罐监,只是導入了build/make/core/main.mk吴藻。
Makefile:

### DO NOT EDIT THIS FILE ###
include build/make/core/main.mk
### DO NOT EDIT THIS FILE ###

main.mk中有兩個最重要的部分,一個是導入build/make/core/config.mk和build/make/core/definitions.mk笑诅。
main.mk:

......
BUILD_SYSTEM := $(TOPDIR)build/make/core
......
# Set up various standard variables based on configuration
# and host information.
include $(BUILD_SYSTEM)/config.mk
......
# Bring in standard build system definitions.
include $(BUILD_SYSTEM)/definitions.mk
......

config.mk中定義了一系列編譯需要用到的變量调缨,比如常用的CLEAR_VARS、BUILD_PACKAGE吆你。這些變量實際上是每一個變量導入另一個.mk文件。每一個被導入的.mk完成一個基本功能俊犯,比如妇多,CLEAR_VARS對應的build/make/core/clear_vars.mk是清除編譯的臨時變量,BUILD_PACKAGE對應的build/make/core/package.mk是編譯APK燕侠。
config.mk:

# Set up efficient math functions which are used in make.
# Here since this file is included by envsetup as well as during build.
include $(BUILD_SYSTEM)/math.mk

# Various mappings to avoid hard-coding paths all over the place
include $(BUILD_SYSTEM)/pathmap.mk

# Allow projects to define their own globally-available variables
include $(BUILD_SYSTEM)/project_definitions.mk

# ###############################################################
# Build system internal files
# ###############################################################

BUILD_COMBOS:= $(BUILD_SYSTEM)/combo

CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.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_HEADER_LIBRARY:= $(BUILD_SYSTEM)/header_library.mk
BUILD_AUX_STATIC_LIBRARY:= $(BUILD_SYSTEM)/aux_static_library.mk
BUILD_AUX_EXECUTABLE:= $(BUILD_SYSTEM)/aux_executable.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk
BUILD_RRO_PACKAGE:= $(BUILD_SYSTEM)/build_rro_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_APIDIFF:= $(BUILD_SYSTEM)/apidiff.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
BUILD_NATIVE_BENCHMARK := $(BUILD_SYSTEM)/native_benchmark.mk
BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
BUILD_FUZZ_TEST := $(BUILD_SYSTEM)/fuzz_test.mk
BUILD_HOST_FUZZ_TEST := $(BUILD_SYSTEM)/host_fuzz_test.mk

BUILD_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/shared_test_lib.mk
BUILD_HOST_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/host_shared_test_lib.mk
BUILD_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/static_test_lib.mk
BUILD_HOST_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/host_static_test_lib.mk

BUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mk
BUILD_HOST_DALVIK_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_java_library.mk
BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_static_java_library.mk

BUILD_HOST_TEST_CONFIG := $(BUILD_SYSTEM)/host_test_config.mk
BUILD_TARGET_TEST_CONFIG := $(BUILD_SYSTEM)/target_test_config.mk

而definitions.mk中用define也定義了一系列變量者祖,比如常用的my-dir立莉、all-subdir-makefiles、all-subdir-java-files等等七问。這些編譯主要用于處理目錄相關的功能蜓耻,比如my-dir是獲取當前目錄路徑,all-subdir-makefiles調(diào)用所有子目錄的android.mk械巡。definitions.mk中有很多變量刹淌,列舉如下:
definitions.mk:

define print-vars
define true-or-empty
define gcno-touch-rule
define my-dir
define all-makefiles-under
define first-makefiles-under
define all-subdir-makefiles
define all-named-subdir-makefiles
define all-named-dirs-under
define all-subdir-named-dirs
define all-named-files-under
define all-subdir-named-files
define all-java-files-under
define all-subdir-java-files
define all-c-files-under
define all-subdir-c-files
define all-cpp-files-under
define all-subdir-cpp-files
define all-Iaidl-files-under
define all-subdir-Iaidl-files
define all-vts-files-under
define all-subdir-vts-files
define all-logtags-files-under
define all-proto-files-under
define all-renderscript-files-under
define all-S-files-under
define all-html-files-under
define all-subdir-html-files
define find-subdir-files
define find-subdir-subdir-files
define find-subdir-assets
define find-other-java-files
define find-other-html-files
define find-files-in-subdirs
define find-parent-file
define find-test-data-in-subdirs
define add-dependency
define reverse-list
define def-host-aux-target
define find-idf-prefix
define intermediates-dir-for
define local-intermediates-dir
define generated-sources-dir-for
define local-generated-sources-dir
define module-built-files
define module-installed-files
define module-stubs-files
define doc-timestamp-for
define java-lib-files
define java-lib-header-files
define java-lib-header-files
define java-lib-deps
define app-lib-files
define app-lib-header-files
define app-lib-header-files
define streq
define normalize-path-list
define normalize-comma-list
define word-colon
define collapse-pairs
define uniq-pairs-by-first-component
define modules-for-tag-list
define module-names-for-tag-list
define get-tagged-modules
define append-path
define echo-warning
define echo-error
define pretty-warning
define pretty-error
define _get-package-overrides
define get-package-overrides
define pretty
define pretty
define include-depfile
define include-depfiles-for-objs
define track-src-file-obj
define _track-src-file-obj
define track-src-file-gen
define _track-src-file-gen
define track-gen-file-obj
define transform-l-to-c-or-cpp
define transform-y-to-c-or-cpp
define _merge-renderscript-d
define transform-renderscripts-to-java-and-bc
define transform-bc-to-so
define transform-renderscripts-to-cpp-and-bc
define transform-aidl-to-java
define transform-aidl-to-cpp
define define-aidl-java-rule
define define-aidl-java-rule
define-aidl-java-rule-src
define define-aidl-cpp-rule
define define-aidl-cpp-rule
define-aidl-cpp-rule-src
define transform-vts-to-cpp
define define-vts-cpp-rule
define define-vts-cpp-rule
define-vts-cpp-rule-src
define transform-logtags-to-java
define transform-proto-to-java
define transform-proto-to-cc
define c-includes
define transform-cpp-to-o-compiler-args
define clang-tidy-cpp
define transform-cpp-to-o
define transform-cpp-to-o
define transform-c-or-s-to-o-compiler-args
define transform-c-to-o-compiler-args
define clang-tidy-c
define transform-c-to-o
define transform-c-to-o
define transform-s-to-o
define transform-asm-to-o
define transform-m-to-o
define transform-host-cpp-to-o-compiler-args
define clang-tidy-host-cpp
define transform-host-cpp-to-o
define transform-host-cpp-to-o
define transform-host-c-or-s-to-o-common-args
define transform-host-c-or-s-to-o
define transform-host-c-to-o-compiler-args
define clang-tidy-host-c
define transform-host-c-to-o
define transform-host-c-to-o
define transform-host-s-to-o
define transform-host-m-to-o
define transform-host-mm-to-o
define compile-dotdot-cpp-file
define compile-dotdot-c-file
define compile-dotdot-s-file
define compile-dotdot-s-file-no-deps
define _concat-if-arg2-not-empty
define split-long-arguments
define _extract-and-include-single-target-whole-static-lib
define extract-and-include-whole-static-libs-first
define extract-and-include-target-whole-static-libs
define transform-o-to-static-lib
define _extract-and-include-single-aux-whole-static-lib
define extract-and-include-aux-whole-static-libs
define transform-o-to-aux-static-lib
define transform-o-to-aux-executable-inner
define transform-o-to-aux-executable
define transform-o-to-aux-static-executable-inner
define transform-o-to-aux-static-executable
define _extract-and-include-single-host-whole-static-lib
define extract-and-include-host-whole-static-libs
define create-dummy.o-if-no-objs
define get-dummy.o-if-no-objs
define delete-dummy.o-if-no-objs
define transform-host-o-to-static-lib
define transform-host-o-to-shared-lib-inner
define transform-host-o-to-shared-lib
define transform-host-o-to-package
define transform-o-to-shared-lib-inner
define transform-o-to-shared-lib
define transform-to-stripped
define transform-to-stripped-keep-mini-debug-info
define transform-to-stripped-keep-symbols
define pack-elf-relocations
define transform-o-to-executable-inner
define transform-o-to-executable
define transform-o-to-static-executable-inner
define transform-o-to-static-executable
define transform-host-o-to-executable-inner
define transform-host-o-to-executable
define create-resource-java-files
define find-generated-R.java
define aapt2-compile-one-resource-file
define aapt2-compile-resource-dirs
define aapt2-compile-resource-zips
define aapt2-compile-one-resource-file-rule
define aapt2-compiled-resource-out-file
define aapt2-link
define emit-line
define dump-words-to-file
define unzip-jar-files
define jar-args-sorted-files-in-directory
define fetch-additional-java-source
define write-java-source-list
define compile-java
define transform-java-to-header.jar
define commit-change-for-toc
define _transform-dex-to-toc
define define-dex-to-toc-rule
define define-dex-to-toc-rule
define define-dex-to-toc-rule
define define-dex-to-toc-rule
define codename-or-sdk-to-sdk
define desugar-classes-jar
define transform-classes.jar-to-dex
define transform-classes-d8.jar-to-dex
define create-empty-package-at
define create-empty-package
define initialize-package-file
define add-assets-to-package
define _add-jni-shared-libs-to-package-per-abi
define add-jni-shared-libs-to-package
define add-dex-to-package
define add-dex-to-package-arg
define add-java-resources-to
define add-jar-resources-to-package
define sign-package
define sign-package-arg
define align-package
define compress-package
define remove-timestamps-from-package
define uncompress-dexs
define uncompress-shared-libs
define transform-host-java-to-package
define transform-host-java-to-dalvik-package
define copy-one-header
define copy-one-file
define copy-and-uncompress-dexs
define copy-many-files
define copy-xml-file-checked
define copy-file-to-target
define copy-file-to-target-with-cp
define copy-file-to-target-strip-comments
define copy-file-to-new-target
define copy-file-to-new-target-with-cp
define transform-prebuilt-to-target
define transform-prebuilt-to-target-strip-comments
define copy-files-with-structure
define symlink-file
define _symlink-file
define dexpreopt-copy-jar
define dexpreopt-remove-classes.dex
define hiddenapi-copy-dex-files
define hiddenapi-copy-soong-jar
define transform-jar-to-proguard
define transform-jar-to-proguard
define transform-jar-to-dex-r8
define transform-generated-source
define assert-max-image-size
define add-radio-file
define add-radio-file-internal
define add-radio-file-checked
define add-radio-file-checked-internal
define inherit-package
define inherit-package-internal
define set-inherited-package-variables
define keep-or-override
define set-inherited-package-variables-internal
define check-api
define if-build-from-source
define if-build-from-source
define include-if-build-from-source
define get-prebuilt-src-arch
define record-module-type
define compatibility_suite_dirs
define create-suite-dependencies
define _clean-path-strip-dotdot
define _clean-path-strip-root-dotdots
define _clean-path-expanded
define clean-path
define my_test
define try-validate-path-is-subdir
define validate-path-is-subdir
define try-validate-paths-are-subdirs
define validate-paths-are-subdirs
define test-validate-paths-are-subdirs
define jacoco-class-filter-to-file-args
define jacoco-validate-file-args
define append_enforce_rro_sources
define generate_all_enforce_rro_packages
define has-system-sdk-version
define get-numeric-sdk-version

main.mk中另一個重要的部分就是定義了一系列的規(guī)則,這些規(guī)則的目標就是編譯要生成的目標文件:

# This is the default target.  It must be the first declared target.
.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL): droid_targets

......

.PHONY: ramdisk
ramdisk: $(INSTALLED_RAMDISK_TARGET)

.PHONY: systemtarball
systemtarball: $(INSTALLED_SYSTEMTARBALL_TARGET)

.PHONY: boottarball
boottarball: $(INSTALLED_BOOTTARBALL_TARGET)

.PHONY: userdataimage
userdataimage: $(INSTALLED_USERDATAIMAGE_TARGET)

ifneq (,$(filter userdataimage, $(MAKECMDGOALS)))
$(call dist-for-goals, userdataimage, $(BUILT_USERDATAIMAGE_TARGET))
endif

.PHONY: userdatatarball
userdatatarball: $(INSTALLED_USERDATATARBALL_TARGET)

.PHONY: cacheimage
cacheimage: $(INSTALLED_CACHEIMAGE_TARGET)

.PHONY: bptimage
bptimage: $(INSTALLED_BPTIMAGE_TARGET)

.PHONY: vendorimage
vendorimage: $(INSTALLED_VENDORIMAGE_TARGET)

.PHONY: productimage
productimage: $(INSTALLED_PRODUCTIMAGE_TARGET)

.PHONY: systemotherimage
systemotherimage: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET)

.PHONY: bootimage
bootimage: $(MTK_BOOTIMAGE_TARGET)

而編譯的默認目標讥耗,也就是終極目標droid有勾,逐級依賴,依賴到各個image文件古程,也就是各個分區(qū)imge文件:

# Building a full system-- the default is to build droidcore
droid_targets: droidcore dist_files

......

# Build files and then package it into the rom formats
.PHONY: droidcore
droidcore: files \
    systemimage \
    $(INSTALLED_BOOTIMAGE_TARGET) \
    $(MTK_BOOTIMAGE_TARGET) \
    $(INSTALLED_RECOVERYIMAGE_TARGET) \
    $(INSTALLED_VBMETAIMAGE_TARGET) \
    $(INSTALLED_USERDATAIMAGE_TARGET) \
    $(INSTALLED_CACHEIMAGE_TARGET) \
    $(INSTALLED_BPTIMAGE_TARGET) \
    $(INSTALLED_VENDORIMAGE_TARGET) \
    $(INSTALLED_PRODUCTIMAGE_TARGET) \
    $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
    $(INSTALLED_FILES_FILE) \
    $(INSTALLED_FILES_FILE_VENDOR) \
    $(INSTALLED_FILES_FILE_PRODUCT) \
    $(INSTALLED_FILES_FILE_SYSTEMOTHER) \
    soong_docs

根據(jù)make的編譯原理蔼卡,編譯時,先編譯終極目標的各個依賴文件挣磨,如image文件雇逞、bin文件等等,而image文件又依賴許多的庫文件茁裙、APK文件塘砸、資源文件等等,也就會遞歸觸發(fā)庫文件呜达、APK文件谣蠢、資源文件等模塊的編譯。遞歸編譯完依賴文件查近,最后完成終極目標眉踱,這樣就完成了整個android源碼的構(gòu)建。當然霜威,main.mk中為了完成整個android的編譯谈喳,還導入了一系列的mk等等,這里就不一一介紹了戈泼,有興趣的可以自行查看源碼婿禽。

同樣,根據(jù)make的編譯原理大猛,我們也可以通過make指定的目標來單獨編譯某個模塊扭倾,這樣可以加快編譯速度。例如: make systemimage挽绩。

當然膛壹,為了進一步加快編譯速度,我們還可以利用envsetup.sh中的mm或者mmm函數(shù),在僅需要編譯模塊自身模聋,不需要編譯模塊的依賴的情況下肩民,用mm或者mmm編譯更快。

我們可以看到链方,實際上android.mk和Makefile沒有明顯差別持痰。android.mk實際上只是多了一些方便編譯android源碼的內(nèi)置變量和內(nèi)置函數(shù)。android.mk完全遵循Makefile的語法規(guī)則祟蚀,并且它的內(nèi)置變量和內(nèi)置函數(shù)也是按照Makefile語法進行導入的工窍。最關鍵的,構(gòu)建android系統(tǒng)時也是從一個Makefile開始的暂题。所以移剪,我們可以認為android.mk實際上是一種擴展的Makefile,就像GNU make擴展了原始make一樣薪者。

接下來我們介紹android.mk的使用實例纵苛。

3. android.mk的使用實例

3.1 編譯APK

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
# 源文件,可包含java言津、aidl文件
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SRC_FILES += src/com/sprd/gallery3d/aidl/IFloatWindowController.aidl
# resource資源文件
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
# AndroidManifest.xml文件
LOCAL_MANIFEST_FILE := $(LOCAL_PATH)/AndroidManifest.xml
# 是否啟用AAPT2
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
# 目標APK文件名稱
LOCAL_PACKAGE_NAME := DreamCamera2
# 需要override的名稱
LOCAL_OVERRIDES_PACKAGES := Camera2
# APK的簽名
LOCAL_CERTIFICATE := platform
# 是否啟用odex優(yōu)化
LOCAL_DEX_PREOPT := false
# SDK版本
LOCAL_SDK_VERSION := current
# 混淆配置文件
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
# 依賴的java共享庫
LOCAL_JAVA_LIBRARIES := android.test.runner
# 依賴的java靜態(tài)庫
LOCAL_STATIC_JAVA_LIBRARIES := zxing
# 依賴的共享庫
LOCAL_SHARED_LIBRARIES := libjpeg
# 依賴的靜態(tài)庫
LOCAL_STATIC_LIBRARIES := libjpeg_static_ndk
# 版本號
LOCAL_AAPT_FLAGS := \
        --auto-add-overlay \
        --version-name "$(version_name_package)" \
        --version-code $(version_code_package) \
# 構(gòu)建APK
include $(BUILD_PACKAGE)

3.2 編譯java靜態(tài)庫

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
# 源文件攻人,可包含java、aidl文件
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# 依賴的java靜態(tài)庫
LOCAL_STATIC_JAVA_LIBRARIES := zxing
# 依賴的java動態(tài)庫
LOCAL_JAVA_LIBRARIES := android.test.runner
# 目標java靜態(tài)庫的名稱
LOCAL_MODULE := scan
# 構(gòu)建java靜態(tài)庫
include $(BUILD_STATIC_JAVA_LIBRARY)

3.3 編譯java共享庫

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
# 源文件悬槽,可包含java怀吻、aidl文件
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# 依賴的java共享庫
LOCAL_JAVA_LIBRARIES := bouncycastle core-libart ext services.core
LOCAL_MODULE_TAGS := optional
LOCAL_JACK_ENABLED := disabled
# 目標java共享庫的名稱
LOCAL_MODULE:= security
# 構(gòu)建java共享庫
include $(BUILD_JAVA_LIBRARY)

3.4 編譯C/C++靜態(tài)庫

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

# 目標靜態(tài)庫的名稱
LOCAL_MODULE := libgif-ex

# C/C++源文件
LOCAL_SRC_FILES := \
    dgif_lib.c     \
    egif_lib.c     \
    gifalloc.c     \
    gif_err.c      \
    gif_hash.c     \
    openbsd-reallocarray.c    \
    quantize.c

LOCAL_CFLAGS += -Wno-format -Wno-sign-compare -Wno-unused-parameter -DHAVE_CONFIG_H
LOCAL_SDK_VERSION := 8
LOCAL_NDK_STL_VARIANT := c++_static
# 構(gòu)建C/C++靜態(tài)庫
include $(BUILD_STATIC_LIBRARY)

3.5 編譯C/C++共享庫

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
# C/C++頭文件
LOCAL_C_INCLUDES := \
        $(LOCAL_PATH)/include \
        $(TOPDIR)system/core/include
# C FLAG
LOCAL_CFLAGS := -O3 -DNDEBUG
# LDFLAG
LOCAL_LDFLAGS := -llog
# 依賴的共享庫
LOCAL_SHARED_LIBRARIES := \
                          libutils \
                          myutils 
# 依賴的靜態(tài)庫
LOCAL_STATIC_LIBRARIES := libjpeg_static_ndk
# C/C++源文件
LOCAL_SRC_FILES := \
                   main.cpp \
                   utils.cpp 
# 目標共享庫的名稱
LOCAL_MODULE    := mylib
LOCAL_MODULE_TAGS := optional
# 構(gòu)建共享庫
include $(BUILD_SHARED_LIBRARY)

4. 用于預置的android.mk

4.1 預置jar

方法一:
LOCAL_PATH:= $(call my-dir)

# 預置
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := zxing:libs/core.jar \
                                        gson:libs/gson-2.8.0.jar \
                                        android-support-v7:libs/android-support-v7-recyclerview.jar 
include $(BUILD_MULTI_PREBUILT)

# 引用
include $(CLEAR_VARS)
......
LOCAL_STATIC_JAVA_LIBRARIES += zxing
LOCAL_STATIC_JAVA_LIBRARIES += gson
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7
......
include $(BUILD_PACKAGE)
方法二:
LOCAL_PATH := $(call my-dir)

# 預置
include $(CLEAR_VARS)
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_MODULE := commons-io
LOCAL_SDK_VERSION := current
LOCAL_SRC_FILES := ../../../../../../../../prebuilts/tools/common/m2/repository/commons-io/commons-io/2.4/commons-io-2.4.jar
LOCAL_UNINSTALLABLE_MODULE := true
include $(BUILD_PREBUILT)

# 引用
include $(CLEAR_VARS)
......
LOCAL_STATIC_JAVA_LIBRARIES += commons-io
......
include $(BUILD_PACKAGE)

4.2 預置so

方法一:
LOCAL_PATH:= $(call my-dir)

# 預置
include $(CLEAR_VARS)
LOCAL_MODULE := mylib2
LOCAL_SRC_FILES_32 := lib/armeabi-v7a/mylib2.so
LOCAL_SRC_FILES_64 := lib/arm64-v8a/mylib2.so
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MULTILIB := both
include $(BUILD_PREBUILT)

......
# 引用
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES += mylib2
include $(BUILD_PACKAGE)
......
方法二:
LOCAL_PATH:= $(call my-dir)

# 預置
include $(CLEAR_VARS)
......
ifeq ($(strip $(TARGET_ARCH)), arm64)
    LOCAL_PREBUILT_JNI_LIBS := libs/arm64-v8a/mylib3.so
else ifeq ($(strip $(TARGET_ARCH)), x86_64)
    LOCAL_PREBUILT_JNI_LIBS := libs/x86_64/mylib3.so
else ifeq ($(strip $(TARGET_ARCH)),arm)
    LOCAL_PREBUILT_JNI_LIBS := libs/armeabi-v7a/mylib3.so
else
    LOCAL_PREBUILT_JNI_LIBS := libs/x86/mylib3.so
endif
......
include $(BUILD_PACKAGE)

4.3 預置APK

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# 模塊名稱
LOCAL_MODULE := NewGallery2
# 要覆蓋掉的模塊名稱
LOCAL_OVERRIDES_PACKAGES := Gallery Gallery3D GalleryNew3D Gallery2 DreamGallery2
# 模塊類型為APPS
LOCAL_MODULE_CLASS := APPS
# 允許使用系統(tǒng)隱藏接口
LOCAL_PRIVATE_PLATFORM_APIS := true
# 簽名,如無需重簽名初婆,則直接設置為PRESIGNED使用已有簽名蓬坡;需要重簽,則設置為對應簽名的值磅叛。
LOCAL_CERTIFICATE := platform
# 目標編譯后的輸出目錄
LOCAL_MODULE_PATH := $(TARGET_OUT)/priv-app
# APK文件
LOCAL_SRC_FILES := apk/NewGallery2.apk
# APK預置的so
ifeq ($(strip $(TARGET_ARCH)), arm64)
    LOCAL_PREBUILT_JNI_LIBS := libs/arm64-v8a/libjni_jpeg.so
else ifeq ($(strip $(TARGET_ARCH)), x86_64)
    LOCAL_PREBUILT_JNI_LIBS := libs/x86_64/libjni_jpeg.so
else ifeq ($(strip $(TARGET_ARCH)),arm)
    LOCAL_PREBUILT_JNI_LIBS := libs/armeabi-v7a/libjni_jpeg.so
else
    LOCAL_PREBUILT_JNI_LIBS := libs/x86/libjni_jpeg.so
endif
include $(BUILD_PREBUILT)

5. 結(jié)語

在掌握了Makefile基礎知識以及結(jié)合源碼理清楚了android.mk之后屑咳,就不會覺得.mk文件那么陌生了。尤其是在理解了android.mk的內(nèi)置變量和內(nèi)置函數(shù)之后弊琴,我們在編寫.mk文件就基本可以得心應手了兆龙。

由于make在編譯android系統(tǒng)源碼時表現(xiàn)出效率不夠高的問題,google后來在7.0及以上版本引進了速度更快的Soong敲董,Soong對應的配置文件是android.bp紫皇。但google即便引進了Soong,源碼中還是保留了部分android.mk腋寨。并且android.mk也可以通過kati工具轉(zhuǎn)換成ninja構(gòu)建清單文件聪铺,也就是說android.mk還可以繼續(xù)使用。所以萄窜,make仍然是android開發(fā)者的必備技能计寇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市脂倦,隨后出現(xiàn)的幾起案子番宁,更是在濱河造成了極大的恐慌,老刑警劉巖赖阻,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝶押,死亡現(xiàn)場離奇詭異,居然都是意外死亡火欧,警方通過查閱死者的電腦和手機棋电,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苇侵,“玉大人赶盔,你說我怎么就攤上這事∮芘ǎ” “怎么了于未?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長陡鹃。 經(jīng)常有香客問我烘浦,道長,這世上最難降的妖魔是什么萍鲸? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任闷叉,我火速辦了婚禮,結(jié)果婚禮上脊阴,老公的妹妹穿的比我還像新娘握侧。我一直安慰自己,他們只是感情好嘿期,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布品擎。 她就那樣靜靜地躺著,像睡著了一般秽五。 火紅的嫁衣襯著肌膚如雪孽查。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天坦喘,我揣著相機與錄音盲再,去河邊找鬼。 笑死瓣铣,一個胖子當著我的面吹牛答朋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播棠笑,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼梦碗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起洪规,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤印屁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后斩例,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雄人,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年念赶,在試婚紗的時候發(fā)現(xiàn)自己被綠了础钠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡叉谜,死狀恐怖旗吁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情停局,我是刑警寧澤很钓,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站翻具,受9級特大地震影響履怯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜裆泳,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一叹洲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧工禾,春花似錦运提、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至槽畔,卻和暖如春栈妆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背厢钧。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工鳞尔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人早直。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓寥假,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霞扬。 傳聞我的和親對象是個殘疾皇子糕韧,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345