• Android——编译(二):android.mk的相关知识


    上一篇学习了make的相关东西,这里结合android.mk这个makefile文件讲讲安卓是怎么通过android.mk编译的(不用多想,android.mk就是个makefile)。

    本文还是转载的前辈的文章,学习。

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

    来回顾一下常见的编译步骤:

    source build/envsetup.sh
    
    lunch xxx
    
    make -j8 2>&1 | tee build.log
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这三步究竟做了什么呢?我们来逐步分析一下。

    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.(切换到包含某个文件的目录下)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    除了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: 模拟按菜单键
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    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_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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    最后,envsetup.sh中还遍历并执行 vendordevice目录下的所有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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这些vendorsetup.sh中也定义了的一些product,执行这些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
    
    • 1
    • 2
    • 3

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

    1.2 lunch

    执行lunch函数时,如果用户指定了product,获取指定的product。

    如果用户未指定product,调用print_lunch_menu函数输出上一步生成的lunch menu choices让用户选择。

    如用户指定了product或者提示后选择了product,会获取用户指定的product,并提取 p r o d u c t 和 product和 productvariant。

    然后检查是否支持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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

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

    每个程序在运行后,都会至少打开三个文件描述符,分别是0:标准输入;1:标准输出;2:标准错误。
    
    1、程序运行后会打开三个文件描述符,分别是标准输入,标准输出和标准错误输出。
    
    2、在调用脚本时,可使用2>&1来将标准错误输出重定向。
    
    3、只需要查看脚本的错误时,可将标准输出重定向到文件,而标准错误会打印在控制台,便于查看。
    
    4、>>log.txt会将重定向内容追加到log.txt文件末尾。
    
    5、通过查看/proc/进程id/fd下的内容,可了解进程打开的文件描述符信息。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 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 ###
    
    • 1
    • 2
    • 3

    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
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    config.mk中定义了一系列编译需要用到的变量,比如常用的CLEAR_VARSBUILD_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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    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-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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267

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

    # 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    而编译的默认目标,也就是终极目标droid,逐级依赖,依赖到各个image文件,也就是各个分区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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    根据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
    # 是否启用AAPT2
    LOCAL_USE_AAPT2 := true
    LOCAL_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) \
    # 构建APK
    include $(BUILD_PACKAGE)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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
    # 构建java共享库
    include $(BUILD_JAVA_LIBRARY)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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.c
    
    LOCAL_CFLAGS += -Wno-format -Wno-sign-compare -Wno-unused-parameter -DHAVE_CONFIG_H
    LOCAL_SDK_VERSION := 8
    LOCAL_NDK_STL_VARIANT := c++_static
    # 构建C/C++静态库
    include $(BUILD_STATIC_LIBRARY)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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 
    # 依赖的静态库
    LOCAL_STATIC_LIBRARIES := libjpeg_static_ndk
    # C/C++源文件
    LOCAL_SRC_FILES := \
                       main.cpp \
                       utils.cpp 
    # 目标共享库的名称
    LOCAL_MODULE    := mylib
    LOCAL_MODULE_TAGS := optional
    # 构建共享库
    include $(BUILD_SHARED_LIBRARY)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    方法二:

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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)
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    方法二:

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    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
    # 允许使用系统隐藏接口
    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    5、结语

    在掌握了Makefile基础知识以及结合源码理清楚了android.mk之后,就不会觉得.mk文件那么陌生了。

    尤其是在理解了android.mk的内置变量和内置函数之后,我们在编写.mk文件就基本可以得心应手了。

    由于make在编译android系统源码时表现出效率不够高的问题,google后来在7.0及以上版本引进了速度更快的Soong,Soong对应的配置文件是android.bp。

    但google即便引进了Soong,源码中还是保留了部分android.mk

    并且android.mk也可以通过kati工具转换成ninja构建清单文件,也就是说android.mk还可以继续使用。

    所以,make仍然是android开发者的必备技能

  • 相关阅读:
    C# 给Word中的字符添加强调符号(着重号)
    UE5、CesiumForUnreal实现瓦片坐标信息图层效果
    USB PD v1.0快速充电通信原理
    Java 中的面向数据编程
    【Transformers】第 8 章 :使Transformers高效生产
    NLP(六十九)智能文档问答助手升级
    唐诗的四个阶段
    机器学习笔记 九:预测模型优化(防止欠拟合和过拟合问题发生)
    在Domino上部署运行在Web浏览器中的Notes客户机
    贤鱼的刷题日常(数据结构栈学习)--P1175 表达式的转换--题目详解
  • 原文地址:https://blog.csdn.net/weixin_45264425/article/details/127137844