1. android系统源码的编译流程

来回顾一下常见的编译步骤:
source build/envsetup.sh
lunch xxx
make -j8 2>&1 | tee build.log
这三步究竟做了什么呢?我们来逐步分析一下。

1.1 source build/envsetup.sh

build/envsetup.sh这个文件中定义了一些变量和函数,执行source build/envsetup.sh之后,envsetup.sh中的变量成了全局变量,而其中的函数也可以直接在当前终端命令行中使用了。这些函数可以帮助我们切换目录,查找文件,可以使我们在编译源码时更方便。这些函数可通过hmm函数来查看,下面列出了一些常用的函数:

  • lunch: lunch - (选择要编译的目标产品和版本)
  • tapas: tapas [ ...] [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整个系统)
  • mm: Builds all of the modules in the current directory, but not their dependencies.(构建当前目录下所有的模块,但不包括它们的依赖)
  • mmm: Builds all of the modules in the supplied directories, but not their dependencies.(构建指定目录下所有的模块,但不包括它们的依赖)
  • mma: Builds all of the modules in the current directory, and their dependencies.(构建当前目录下所有的模块以及它们所依赖的模块)
  • mmma: Builds all of the modules in the supplied directories, and their dependencies.(构建指定目录下所有的模块以及它们所依赖的模块)
  • provision: Flash device with all required partitions. Options will be passed on to fastboot.(将设备所有需要的分区刷入,选项将传递给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 查看某个可执行程序对应的进程id
  • key_back: 模拟按返回键
  • key_home: 模拟按Home键
  • key_menu: 模拟按菜单键

envsetup.sh中还定义了add_lunch_combo函数,并且多次执行了add_lunch_combo函数,将自身定义的所有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_CHOICESfunction 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 hereadd_lunch_combo aosp_arm-engadd_lunch_combo aosp_arm64-engadd_lunch_combo aosp_mips-engadd_lunch_combo aosp_mips64-engadd_lunch_combo aosp_x86-engadd_lunch_combo aosp_x86_64-eng

最后,envsetup.sh中还遍历并执行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"    . $fdoneunset f

这些vendorsetup.sh中也定义了的一些product,执行这些vendorsetup.sh后,也会将它们当中定义的product添加到LUNCH_MENU_CHOICES中:

 

add_lunch_combo full_k63v2_64_bsp-engadd_lunch_combo full_k63v2_64_bsp-useradd_lunch_combo full_k63v2_64_bsp-userdebug

在此之后,我们就可以在命令行用lunch函数从LUNCH_MENU_CHOICES中选择需要编译的product。

1.2 lunch

执行lunch函数时,如果用户指定了product,获取指定的product。如果用户未指定product,调用print_lunch_menu函数输出上一步生成的lunch menu choices让用户选择。如用户指定了product或者提示后选择了product,会获取用户指定的product,并提取$product和$variant。然后检查是否支持product,如不支持,提示不支持并退出。如支持,接着会调用set_stuff_for_environment函数设置一系列环境变量,还会调用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则是执行make命令,寻找源码根目录下的Makefile,解析Makefile并开始整个源码的编译。

接下来我们就从源码根目录下的Makefile开始逐步解析。

2. android的Makefile和android.mk

执行make之后,从源码根目录下的Makefile开始逐步解析。该Makefile的内容很少,只是导入了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 placeinclude $(BUILD_SYSTEM)/pathmap.mk# Allow projects to define their own globally-available variablesinclude $(BUILD_SYSTEM)/project_definitions.mk# ################################################################ Build system internal files# ###############################################################BUILD_COMBOS:= $(BUILD_SYSTEM)/comboCLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mkBUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mkBUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mkBUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mkBUILD_HEADER_LIBRARY:= $(BUILD_SYSTEM)/header_library.mkBUILD_AUX_STATIC_LIBRARY:= $(BUILD_SYSTEM)/aux_static_library.mkBUILD_AUX_EXECUTABLE:= $(BUILD_SYSTEM)/aux_executable.mkBUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mkBUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mkBUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mkBUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mkBUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mkBUILD_RRO_PACKAGE:= $(BUILD_SYSTEM)/build_rro_package.mkBUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mkBUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mkBUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mkBUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mkBUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mkBUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mkBUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mkBUILD_APIDIFF:= $(BUILD_SYSTEM)/apidiff.mkBUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mkBUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mkBUILD_NATIVE_BENCHMARK := $(BUILD_SYSTEM)/native_benchmark.mkBUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mkBUILD_FUZZ_TEST := $(BUILD_SYSTEM)/fuzz_test.mkBUILD_HOST_FUZZ_TEST := $(BUILD_SYSTEM)/host_fuzz_test.mkBUILD_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/shared_test_lib.mkBUILD_HOST_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/host_shared_test_lib.mkBUILD_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/static_test_lib.mkBUILD_HOST_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/host_static_test_lib.mkBUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mkBUILD_HOST_DALVIK_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_java_library.mkBUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_static_java_library.mkBUILD_HOST_TEST_CONFIG := $(BUILD_SYSTEM)/host_test_config.mkBUILD_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调用所有子目录的android.mk。definitions.mk中有很多变量,列举如下:
definitions.mk:

 

define print-varsdefine true-or-emptydefine gcno-touch-ruledefine my-dirdefine all-makefiles-underdefine first-makefiles-underdefine all-subdir-makefilesdefine all-named-subdir-makefilesdefine all-named-dirs-underdefine all-subdir-named-dirsdefine all-named-files-underdefine all-subdir-named-filesdefine all-java-files-underdefine all-subdir-java-filesdefine all-c-files-underdefine all-subdir-c-filesdefine all-cpp-files-underdefine all-subdir-cpp-filesdefine all-Iaidl-files-underdefine all-subdir-Iaidl-filesdefine all-vts-files-underdefine all-subdir-vts-filesdefine all-logtags-files-underdefine all-proto-files-underdefine all-renderscript-files-underdefine all-S-files-underdefine all-html-files-underdefine all-subdir-html-filesdefine find-subdir-filesdefine find-subdir-subdir-filesdefine find-subdir-assetsdefine find-other-java-filesdefine find-other-html-filesdefine find-files-in-subdirsdefine find-parent-filedefine find-test-data-in-subdirsdefine add-dependencydefine reverse-listdefine def-host-aux-targetdefine find-idf-prefixdefine intermediates-dir-fordefine local-intermediates-dirdefine generated-sources-dir-fordefine local-generated-sources-dirdefine module-built-filesdefine module-installed-filesdefine module-stubs-filesdefine doc-timestamp-fordefine java-lib-filesdefine java-lib-header-filesdefine java-lib-header-filesdefine java-lib-depsdefine app-lib-filesdefine app-lib-header-filesdefine app-lib-header-filesdefine streqdefine normalize-path-listdefine normalize-comma-listdefine word-colondefine collapse-pairsdefine uniq-pairs-by-first-componentdefine modules-for-tag-listdefine module-names-for-tag-listdefine get-tagged-modulesdefine append-pathdefine echo-warningdefine echo-errordefine pretty-warningdefine pretty-errordefine _get-package-overridesdefine get-package-overridesdefine prettydefine prettydefine include-depfiledefine include-depfiles-for-objsdefine track-src-file-objdefine _track-src-file-objdefine track-src-file-gendefine _track-src-file-gendefine track-gen-file-objdefine transform-l-to-c-or-cppdefine transform-y-to-c-or-cppdefine _merge-renderscript-ddefine transform-renderscripts-to-java-and-bcdefine transform-bc-to-sodefine transform-renderscripts-to-cpp-and-bcdefine transform-aidl-to-javadefine transform-aidl-to-cppdefine define-aidl-java-ruledefine define-aidl-java-ruledefine-aidl-java-rule-srcdefine define-aidl-cpp-ruledefine define-aidl-cpp-ruledefine-aidl-cpp-rule-srcdefine transform-vts-to-cppdefine define-vts-cpp-ruledefine define-vts-cpp-ruledefine-vts-cpp-rule-srcdefine transform-logtags-to-javadefine transform-proto-to-javadefine transform-proto-to-ccdefine c-includesdefine transform-cpp-to-o-compiler-argsdefine clang-tidy-cppdefine transform-cpp-to-odefine transform-cpp-to-odefine transform-c-or-s-to-o-compiler-argsdefine transform-c-to-o-compiler-argsdefine clang-tidy-cdefine transform-c-to-odefine transform-c-to-odefine transform-s-to-odefine transform-asm-to-odefine transform-m-to-odefine transform-host-cpp-to-o-compiler-argsdefine clang-tidy-host-cppdefine transform-host-cpp-to-odefine transform-host-cpp-to-odefine transform-host-c-or-s-to-o-common-argsdefine transform-host-c-or-s-to-odefine transform-host-c-to-o-compiler-argsdefine clang-tidy-host-cdefine transform-host-c-to-odefine transform-host-c-to-odefine transform-host-s-to-odefine transform-host-m-to-odefine transform-host-mm-to-odefine compile-dotdot-cpp-filedefine compile-dotdot-c-filedefine compile-dotdot-s-filedefine compile-dotdot-s-file-no-depsdefine _concat-if-arg2-not-emptydefine split-long-argumentsdefine _extract-and-include-single-target-whole-static-libdefine extract-and-include-whole-static-libs-firstdefine extract-and-include-target-whole-static-libsdefine transform-o-to-static-libdefine _extract-and-include-single-aux-whole-static-libdefine extract-and-include-aux-whole-static-libsdefine transform-o-to-aux-static-libdefine transform-o-to-aux-executable-innerdefine transform-o-to-aux-executabledefine transform-o-to-aux-static-executable-innerdefine transform-o-to-aux-static-executabledefine _extract-and-include-single-host-whole-static-libdefine extract-and-include-host-whole-static-libsdefine create-dummy.o-if-no-objsdefine get-dummy.o-if-no-objsdefine delete-dummy.o-if-no-objsdefine transform-host-o-to-static-libdefine transform-host-o-to-shared-lib-innerdefine transform-host-o-to-shared-libdefine transform-host-o-to-packagedefine transform-o-to-shared-lib-innerdefine transform-o-to-shared-libdefine transform-to-strippeddefine transform-to-stripped-keep-mini-debug-infodefine transform-to-stripped-keep-symbolsdefine pack-elf-relocationsdefine transform-o-to-executable-innerdefine transform-o-to-executabledefine transform-o-to-static-executable-innerdefine transform-o-to-static-executabledefine transform-host-o-to-executable-innerdefine transform-host-o-to-executabledefine create-resource-java-filesdefine find-generated-R.javadefine aapt2-compile-one-resource-filedefine aapt2-compile-resource-dirsdefine aapt2-compile-resource-zipsdefine aapt2-compile-one-resource-file-ruledefine aapt2-compiled-resource-out-filedefine aapt2-linkdefine emit-linedefine dump-words-to-filedefine unzip-jar-filesdefine jar-args-sorted-files-in-directorydefine fetch-additional-java-sourcedefine write-java-source-listdefine compile-javadefine transform-java-to-header.jardefine commit-change-for-tocdefine _transform-dex-to-tocdefine define-dex-to-toc-ruledefine define-dex-to-toc-ruledefine define-dex-to-toc-ruledefine define-dex-to-toc-ruledefine codename-or-sdk-to-sdkdefine desugar-classes-jardefine transform-classes.jar-to-dexdefine transform-classes-d8.jar-to-dexdefine create-empty-package-atdefine create-empty-packagedefine initialize-package-filedefine add-assets-to-packagedefine _add-jni-shared-libs-to-package-per-abidefine add-jni-shared-libs-to-packagedefine add-dex-to-packagedefine add-dex-to-package-argdefine add-java-resources-todefine add-jar-resources-to-packagedefine sign-packagedefine sign-package-argdefine align-packagedefine compress-packagedefine remove-timestamps-from-packagedefine uncompress-dexsdefine uncompress-shared-libsdefine transform-host-java-to-packagedefine transform-host-java-to-dalvik-packagedefine copy-one-headerdefine copy-one-filedefine copy-and-uncompress-dexsdefine copy-many-filesdefine copy-xml-file-checkeddefine copy-file-to-targetdefine copy-file-to-target-with-cpdefine copy-file-to-target-strip-commentsdefine copy-file-to-new-targetdefine copy-file-to-new-target-with-cpdefine transform-prebuilt-to-targetdefine transform-prebuilt-to-target-strip-commentsdefine copy-files-with-structuredefine symlink-filedefine _symlink-filedefine dexpreopt-copy-jardefine dexpreopt-remove-classes.dexdefine hiddenapi-copy-dex-filesdefine hiddenapi-copy-soong-jardefine transform-jar-to-proguarddefine transform-jar-to-proguarddefine transform-jar-to-dex-r8define transform-generated-sourcedefine assert-max-image-sizedefine add-radio-filedefine add-radio-file-internaldefine add-radio-file-checkeddefine add-radio-file-checked-internaldefine inherit-packagedefine inherit-package-internaldefine set-inherited-package-variablesdefine keep-or-overridedefine set-inherited-package-variables-internaldefine check-apidefine if-build-from-sourcedefine if-build-from-sourcedefine include-if-build-from-sourcedefine get-prebuilt-src-archdefine record-module-typedefine compatibility_suite_dirsdefine create-suite-dependenciesdefine _clean-path-strip-dotdotdefine _clean-path-strip-root-dotdotsdefine _clean-path-expandeddefine clean-pathdefine my_testdefine try-validate-path-is-subdirdefine validate-path-is-subdirdefine try-validate-paths-are-subdirsdefine validate-paths-are-subdirsdefine test-validate-paths-are-subdirsdefine jacoco-class-filter-to-file-argsdefine jacoco-validate-file-argsdefine append_enforce_rro_sourcesdefine generate_all_enforce_rro_packagesdefine has-system-sdk-versiondefine get-numeric-sdk-version

main.mk中另一个重要的部分就是定义了一系列的规则,这些规则的目标就是编译要生成的目标文件:

 

# This is the default target.  It must be the first declared target..PHONY: droidDEFAULT_GOAL := droid$(DEFAULT_GOAL): droid_targets.......PHONY: ramdiskramdisk: $(INSTALLED_RAMDISK_TARGET).PHONY: systemtarballsystemtarball: $(INSTALLED_SYSTEMTARBALL_TARGET).PHONY: boottarballboottarball: $(INSTALLED_BOOTTARBALL_TARGET).PHONY: userdataimageuserdataimage: $(INSTALLED_USERDATAIMAGE_TARGET)ifneq (,$(filter userdataimage, $(MAKECMDGOALS)))$(call dist-for-goals, userdataimage, $(BUILT_USERDATAIMAGE_TARGET))endif.PHONY: userdatatarballuserdatatarball: $(INSTALLED_USERDATATARBALL_TARGET).PHONY: cacheimagecacheimage: $(INSTALLED_CACHEIMAGE_TARGET).PHONY: bptimagebptimage: $(INSTALLED_BPTIMAGE_TARGET).PHONY: vendorimagevendorimage: $(INSTALLED_VENDORIMAGE_TARGET).PHONY: productimageproductimage: $(INSTALLED_PRODUCTIMAGE_TARGET).PHONY: systemotherimagesystemotherimage: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET).PHONY: bootimagebootimage: $(MTK_BOOTIMAGE_TARGET)

而编译的默认目标,也就是终极目标droid,逐级依赖,依赖到各个image文件,也就是各个分区imge文件:

 

# Building a full system-- the default is to build droidcoredroid_targets: droidcore dist_files......# Build files and then package it into the rom formats.PHONY: droidcoredroidcore: 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

根据make的编译原理,编译时,先编译终极目标的各个依赖文件,如image文件、bin文件等等,而image文件又依赖许多的库文件、APK文件、资源文件等等,也就会递归触发库文件、APK文件、资源文件等模块的编译。递归编译完依赖文件,最后完成终极目标,这样就完成了整个android源码的构建。当然,main.mk中为了完成整个android的编译,还导入了一系列的mk等等,这里就不一一介绍了,有兴趣的可以自行查看源码。

同样,根据make的编译原理,我们也可以通过make指定的目标来单独编译某个模块,这样可以加快编译速度。例如: make systemimage。

当然,为了进一步加快编译速度,我们还可以利用envsetup.sh中的mm或者mmm函数,在仅需要编译模块自身,不需要编译模块的依赖的情况下,用mm或者mmm编译更快。

我们可以看到,实际上android.mk和Makefile没有明显差别。android.mk实际上只是多了一些方便编译android源码的内置变量和内置函数。android.mk完全遵循Makefile的语法规则,并且它的内置变量和内置函数也是按照Makefile语法进行导入的。最关键的,构建android系统时也是从一个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# 是否启用AAPT2LOCAL_USE_AAPT2 := trueLOCAL_MODULE_TAGS := optional# 目标APK文件名称LOCAL_PACKAGE_NAME := DreamCamera2# 需要override的名称LOCAL_OVERRIDES_PACKAGES := Camera2# APK的签名LOCAL_CERTIFICATE := platform# 是否启用odex优化LOCAL_DEX_PREOPT := false# SDK版本LOCAL_SDK_VERSION := current# 混淆配置文件LOCAL_PROGUARD_FLAG_FILES := proguard.flags# 依赖的java共享库LOCAL_JAVA_LIBRARIES := android.test.runner# 依赖的java静态库LOCAL_STATIC_JAVA_LIBRARIES := zxing# 依赖的共享库LOCAL_SHARED_LIBRARIES := libjpeg# 依赖的静态库LOCAL_STATIC_LIBRARIES := libjpeg_static_ndk# 版本号LOCAL_AAPT_FLAGS := \        --auto-add-overlay \        --version-name "$(version_name_package)" \        --version-code $(version_code_package) \# 构建APKinclude $(BUILD_PACKAGE)

3.2 编译java静态库

 

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)# 源文件,可包含java、aidl文件LOCAL_SRC_FILES := $(call all-subdir-java-files)# 依赖的java静态库LOCAL_STATIC_JAVA_LIBRARIES := zxing# 依赖的java动态库LOCAL_JAVA_LIBRARIES := android.test.runner# 目标java静态库的名称LOCAL_MODULE := scan# 构建java静态库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.coreLOCAL_MODULE_TAGS := optionalLOCAL_JACK_ENABLED := disabled# 目标java共享库的名称LOCAL_MODULE:= security# 构建java共享库include $(BUILD_JAVA_LIBRARY)

3.4 编译C/C++静态库

 

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)# 目标静态库的名称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.cLOCAL_CFLAGS += -Wno-format -Wno-sign-compare -Wno-unused-parameter -DHAVE_CONFIG_HLOCAL_SDK_VERSION := 8LOCAL_NDK_STL_VARIANT := c++_static# 构建C/C++静态库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 FLAGLOCAL_CFLAGS := -O3 -DNDEBUG# LDFLAGLOCAL_LDFLAGS := -llog# 依赖的共享库LOCAL_SHARED_LIBRARIES := \                          libutils \                          myutils # 依赖的静态库LOCAL_STATIC_LIBRARIES := libjpeg_static_ndk# C/C++源文件LOCAL_SRC_FILES := \                   main.cpp \                   utils.cpp # 目标共享库的名称LOCAL_MODULE    := mylibLOCAL_MODULE_TAGS := optional# 构建共享库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 += zxingLOCAL_STATIC_JAVA_LIBRARIES += gsonLOCAL_STATIC_JAVA_LIBRARIES += android-support-v7......include $(BUILD_PACKAGE)

方法二:

 

LOCAL_PATH := $(call my-dir)# 预置include $(CLEAR_VARS)LOCAL_MODULE_CLASS := JAVA_LIBRARIESLOCAL_MODULE := commons-ioLOCAL_SDK_VERSION := currentLOCAL_SRC_FILES := ../../../../../../../../prebuilts/tools/common/m2/repository/commons-io/commons-io/2.4/commons-io-2.4.jarLOCAL_UNINSTALLABLE_MODULE := trueinclude $(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 := mylib2LOCAL_SRC_FILES_32 := lib/armeabi-v7a/mylib2.soLOCAL_SRC_FILES_64 := lib/arm64-v8a/mylib2.soLOCAL_MODULE_TAGS := optionalLOCAL_MODULE_CLASS := SHARED_LIBRARIESLOCAL_MODULE_SUFFIX := .soLOCAL_PROPRIETARY_MODULE := trueLOCAL_MULTILIB := bothinclude $(BUILD_PREBUILT)......# 引用include $(CLEAR_VARS)LOCAL_SHARED_LIBRARIES += mylib2include $(BUILD_PACKAGE)......

方法二:

 

LOCAL_PATH:= $(call my-dir)# 预置include $(CLEAR_VARS)......ifeq ($(strip $(TARGET_ARCH)), arm64)    LOCAL_PREBUILT_JNI_LIBS := libs/arm64-v8a/mylib3.soelse ifeq ($(strip $(TARGET_ARCH)), x86_64)    LOCAL_PREBUILT_JNI_LIBS := libs/x86_64/mylib3.soelse ifeq ($(strip $(TARGET_ARCH)),arm)    LOCAL_PREBUILT_JNI_LIBS := libs/armeabi-v7a/mylib3.soelse    LOCAL_PREBUILT_JNI_LIBS := libs/x86/mylib3.soendif......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# 模块类型为APPSLOCAL_MODULE_CLASS := APPS# 允许使用系统隐藏接口LOCAL_PRIVATE_PLATFORM_APIS := true# 签名,如无需重签名,则直接设置为PRESIGNED使用已有签名;需要重签,则设置为对应签名的值。LOCAL_CERTIFICATE := platform# 目标编译后的输出目录LOCAL_MODULE_PATH := $(TARGET_OUT)/priv-app# APK文件LOCAL_SRC_FILES := apk/NewGallery2.apk# APK预置的soifeq ($(strip $(TARGET_ARCH)), arm64)    LOCAL_PREBUILT_JNI_LIBS := libs/arm64-v8a/libjni_jpeg.soelse ifeq ($(strip $(TARGET_ARCH)), x86_64)    LOCAL_PREBUILT_JNI_LIBS := libs/x86_64/libjni_jpeg.soelse ifeq ($(strip $(TARGET_ARCH)),arm)    LOCAL_PREBUILT_JNI_LIBS := libs/armeabi-v7a/libjni_jpeg.soelse    LOCAL_PREBUILT_JNI_LIBS := libs/x86/libjni_jpeg.soendifinclude $(BUILD_PREBUILT)

5. 结语

在掌握了Makefile基础知识以及结合源码理清楚了android.mk之后,就不会觉得.mk文件那么陌生了。尤其是在理解了android.mk的内置变量和内置函数之后,我们在编写.mk文件就基本可以得心应手了。

由于make在编译android系统源码时表现出效率不够高的问题,google后来在7.0及以上版本引进了速度更快的ninja,中文意思是忍者,ninja对应的配置文件是android.bp。但google即便引进了ninja,源码中还是保留了部分android.mk。并且android.mk也可以通过kati工具转换成ninja,也就是说android.mk还可以继续使用。所以,make仍然是android开发者的必备技能。

更多相关文章

  1. Android(安卓)Studio(十二):打包多个发布渠道的apk文件
  2. android -> 修改自动转为大写 的textAllCaps 属性
  3. android XML文件序列化
  4. Android(安卓)jni调用,实现自己的JNI_OnLoad函数
  5. Android(安卓)Studio导入Android平台源码
  6. android 编译模块
  7. android 扫描SD卡与系统文件
  8. Android(安卓)LCD和键盘 背光亮度设置
  9. NPM 和webpack 的基础使用

随机推荐

  1. Android Context 使用时注意内存泄漏问题
  2. android的帮助、about、关于作者、HELP等
  3. Android(安卓)程序完全退出的几种方法(参
  4. Android 知识汇总
  5. Android增加键值(二)
  6. Android入门(4) 开发第一个Android程序
  7. 给android添加系统属性:Settings.system和
  8. Android获取mac地址方法,6.0以上也可用
  9. Looper类浅析
  10. android上拔出sd卡导致flash上媒体也消失