Android构建系统中的Android.mk与Android.bp文件

3,458 阅读4分钟

1、历史与发展

Android.mk文件是Android构建系统中一种脚本文件,用于构建C/C++代码库的一套规则,是NDK的一部分。使用的是GNU Make构建系统。

Android 7.0引入Android Soong构建系统,使用了Android.bp作为构建脚本文件,旨在代替Android.mk和Make机制。由于使用了Ninja构建工具,可以更高效的处理依赖关系和并行处理。

1.1 区别

  • Android.mk使用Makefile风格语法,Android.bp使用Blueprint语法json风格声明式语法。

  • Android.mk历史悠久,所以兼容老项目更好;对熟悉Makefile开发者来说,可读性更强;提供更灵活的编写方式用于配置构建需求。

    Android.bp采用Soong构建,具有更好的性能;声明式语法、JSON风格更加现代化和可维护;适合大型项目和模块化构建、跨平台支持。

  • 使用建议:新项目使用bp,老项目是用mk。

2、Android.mk文件说明

我们拿内置第三方应用为系统应用的mk文件来分析。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Sougou
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
#LOCAL_PRIVILEGED_MODULE :=true
LOCAL_DEX_PREOPT := false
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
include $(BUILD_PREBUILT)
  • LOCAL_PATH:=${call my-dir}

    Android.mk文件必须以LOCAL_PATH开头,用于在文件tree中查找源文件。my-dir返回当前所在的目录路径。

  • include $(CLEAR_VARS)

    CLEAR_VARS变量用于清理本地环境,如LOCAL_MODULE。用于清除之前定义的所有局部变量,并重新初始化一个新的局部变量集合,以便定义一个新的模块。避免不同模块之前变量相互影响。

  • LOCAL_MODULE

    用于定义模块的名称,指定了当前模块在构建过程中输出文件的名称,以及在系统中被引用的标识符。包括可执行文件、共享库、静态库等。像在内置应用情况下,我们一般取应用的名称,并且保持mk文件所在目录同名。例如这里的Sougo。

  • LOCAL_MODULE_CLASS

    标记当前模块所属的类型。例如APPSJAVA_LIBRARIESSHARED_LIBRARIESEXECUTABLESSTATIC_LIBRARIES

  • LOCAL_BUILT_MODULE_STEM

    通常情况下,不需要配置,会根据模块名称LOCAL_MODULE来生成,例如上面会生成Sougou.apk。我们也可以指定生成的名称,例如上面的package.apk。

  • LOCAL_MODULE_SUFFIX

    生成模块的后缀,例如应用程序生成.apk,动态库生成.so

  • LOCAL_SRC_FILES

    用来指定当前模块要编译的源文件列表。告诉构建系统,模块需要生成哪些源文件来生成最终的输出文件。

  • LOCAL_CERTIFICATE

    应用所使用的签名。

    • platform 使用系统平台进行签名,这样应用就可以操作系统,并声明为系统应用。
    • testkey 使用默认的测试密钥,通常用在开发和测试的过程。
    • PRESIGNED 使用应用自带的签名,也就是不在进行覆盖签名。
  • LOCAL_MODULE_TAGS

    用于定义Android模块标签,用来确定模块的用途、特性或约束。我们在lunch选择编译菜单时,后缀eng、user、debug会和模块的LOCAL_MODULE_TAGS值进行判断,匹配了才会参与编译。

    • optional: 表示模块是可选的,不是系统的基本组成部分。不会被强制包含在构建中,根据设备配置进行选择是否包含。
    • debug:表示模块用于调试目的,这些模块通常包含调试信息或者启用了调试功能。
    • eng: 表示模块为工程开发环境而设计的,包含额外的调试功能、开发工具或测试代码。
    • user:表示模块面试最终用户的,是系统的一部分。通常是用户界面、应用程序或核心功能。
    • tests: 表示模块包含测试代码或资源,通常用于单元测试、集成测试或系统测试。
    • testsuite:表示模块是一个套完整的测试套件,可以在设备上运行以验系统的功能和性能。
    • verity_signing_key:表示模块是用于签名校验,用于验证系统映像的完整性和真实性。
    • vendor_public_key:供应商公钥,用于验证供应商提供的组件或者程序。
    • ota_changelog:用于OTA更新的变更日志,记录系统更新的变化和修复。
  • LOCAL_C_INCLUDES

    告诉C编译系统需要在哪些目录搜索当前模块所需或依赖的头文件。

  • LOCAL_CFLAGS

    用于指定针对C代码的编译器标志。如:LOCAL_CFLAGS := -O2 -Wall -g。常见标志有:

    • -02,启用了优化级别2,进行一定程度代码优化以提高执行效率。
    • -Wall:启用了所有警告,即输出所有警告信息,用于排查潜在问题。
    • -g: 生成调试信息,生成的可执行文件具有和源代码关联的可调试信息。
    • -D:增加全局宏定义。
  • LOCAL_LDFLAGS

    用于指定链接器的特定标志或选项,在构建动态库或可执行文件时传递自定义的链接器选项。

  • LOCAL_CXX_STL

    用于指定C++编译器所使用的标准模板库(STL)的类型。默认是system,表示使用设备产商提供的标准实现。

  • include $(BUILD_SHARED_LIBRARY)

    用于告诉构建系统构建一个共享库,通常用来完成当前模块的构建。

    • BUILD_SHARED_LIBRARY:共享库,即动态库。
    • BUILD_SHARED_LIBRARY: 静态库
    • BUILD_EXECUTEABLE: Native C可执行库

3、Android.bp文件说明

将上面Android.mk转换成Android.bp文件,可见简单很多。Android.dp不需要设置环境信息,只需要设置关键信息,对新手更加友好。

android_app_import {
    name: "Sougou",
    apk: "Sougou.apk",
    certificate: "PRESIGNED",
    dex_preopt: false,
    privileged: false,
}

我们来看看开机启动动画的Android.bp文件,目录在frameworks/base/cmds/bootanimation/Android.bp

//用于配置pakcage,常用来配置默认许可西
package {
 		//包默认适用的许可证
    default_applicable_licenses: ["frameworks_base_license"],
}
//配置C/C++编译器和链接器一些参数
cc_defaults {
    name: "bootanimation_defaults",

    cflags: [
        "-DGL_GLEXT_PROTOTYPES",
        "-DEGL_EGLEXT_PROTOTYPES",

        "-Wall",//启用所有警告
        "-Werror",//所有警告都视为错误,发生错误编译将不通过
        "-Wunused",//警告未使用的变量
        "-Wunreachable-code", //警告不可到达代码
    ],

    shared_libs: [
        "libandroidfw",//Android框架库
        "libbase",// Android 基础库
        "libbinder", //Android Binder IPC库
        "libcutils", //Android C 工具库
        "liblog", //Android 日志库
        "libutils", //Android实用工具库
    ],
}

// bootanimation executable
// =========================================================

cc_binary {
    name: "bootanimation",//可执行程序的名称
    defaults: ["bootanimation_defaults"],//编译器和链接器默认参数

    header_libs: ["jni_headers"],//依赖的头文件库

    shared_libs: [//依赖的共享库
        "libOpenSLES",
        "libbootanimation",
    ],

    srcs: [//指定生成可执行文件需要的文件列表
        "BootAnimationUtil.cpp",
        "bootanimation_main.cpp",
        "audioplay.cpp",
    ],

    init_rc: ["bootanim.rc"],//初始化文件

    cflags: [
        "-Wno-deprecated-declarations",//不对过时的声明进行警告
    ],
}

// libbootanimation
// ===========================================================

cc_library_shared {
    name: "libbootanimation",
    defaults: ["bootanimation_defaults"],

    srcs: ["BootAnimation.cpp"],//源文件路径

    shared_libs: [//所依赖的共享库
        "libui",
        "libjnigraphics",
        "libEGL",
        "libGLESv2",
        "libgui",
        "libmedia",
    ],
}

开机动画Android.dp定义了四个模块:packagecc_defaultscc_binarycc_library_shared

  • package:主要用于集中管理许可证和可见性。

    • default_applicable_licenses:用于定义当前包内所有模块默认适用的许可证。如不同模块需要指定特殊的许可证,可以在模块增加licenses

      cc_library_shared {
          name: "libcamera",
          srcs: ["camera.cpp"],
          licenses: ["camera_license"],
          // 这个模块将使用 "camera_license" 而不是默认许可证
      }
      

      licenses基本放在AOSP根目录的licenses下,特殊子项目可能有自己的licenses目录。

    • name:用于指定包的名称,一般不设置。

    • visibility:控制包内模块的可见性。//visibility:public包内模块对所有模块可见;//visibility:private包内模块对包内模块可见;//visibility:inherit包内模块继承父包的可见性。

    package {
        name: "example_package",
        default_applicable_licenses: ["frameworks_base_license"],
        licenses: ["frameworks_base_license", "additional_license"],
        visibility: ["//visibility:public"],
    }
    
  • cc_defaults:用于设置C/C++编译器或接链器的一些参数,有利于保持环境统一,在不同平台版本进行编译。

    • name: 指定了该cc_defaults的名称。

    • cflags: 用于指定编译C文件的默认选项。

    • cppflags:指定了预处理器选项,包括定义 DEBUG 宏和添加本地头文件目录到搜索路径。

    • shared_libs:用于指定链接过程依赖的共享库。

    • static_libs:用于指定链接过程依赖的静态库。

    • include_dirs:指定头文件的搜索路径。

    • local_include_dirs:本地头文件的搜索路径。

      ……

  • **cc_binary **:用于构建可执行文件。例如这里构建生成开机动画的可执行文件bootanimation

    • name:指定了可执行文件的名称。
    • defaults:定义编译和链接过程使用的默认选项。
    • header_libs:链接时依赖的头文件库。
    • share_libs:链接时依赖的动态库。
    • srcs:生成可执行文件需要的源码文件列表。
    • init_rc:指定初始化RC文件。
  • cc_library_shared: 用于生成共享库。配置与cc_binary差不多。

Android.bp根据构建类型的不同,可以配置很多不同的模型,例如还可以构建静态库:cc_library_static,Android应用程序:android_app,Android库:android_library,Java程序:java_binary,Java库:java_library等等。

image.png

4、资源

本文大多数内容参考互联网知识和AI智能,可能存在个人理解错误和偏见,请注意甄别。