Android编译之bp文件编写

编写bp文件用于Android编译模块的一些笔记。
Views: 58
2 0
Read Time:2 Minute, 13 Second

随着Android系统的演进,整个系统已经变得越来越复杂,越来越多的功能与代码加入其中,随之而来的是越来越长的编译时长。

从Android7.0之前,Android系统使用GNU Make来进行版本构建。在这之后,Android逐渐使用Soong系统来进行版本构建。前者需要编写.mk文件来指定我们每个编译模块的规则,而后者则需要编写.bp文件来对我们模块的编译行为进行指定。

关于Android系统中makefile的编写,可以参见我之前的博客。今天这篇博客,主要讲讲我们Android系统中blueprint(.bp)文件的编写。

概述

Android.bp编写时以模块进行划分,模块类型可以参考官方指导:https://ci.android.com/builds/submitted/8947179/linux/latest/view/soong_build.html。在编写时,我们以模块类型字段作为开头,以{}囊括具体的配置内容,每一个配置内容都支持Key:Value的形式。那么每个模块内可以配置的内容具体有哪些呢,同样地你可以在上面的链接中找到相关的材料。

以下将从几个比较常见的使用场景入手,看看如何去编写一个.bp文件

编译C/C++二进制

编译二进制.bin文件是比较常见的,我们所有的进程都是由二进制文件执行的实体,以下为一段编译二进制所对应的bp配置:

cc_binay{

name:”gzip”,

srcs:[“src/test/minigzip.c”],

shared_libs:[“libz”],

stl:“none”,

}

如上所示,如我们需要编译C/C++的二进制文件(.bin)文件,我们应使用cc_binary关键字作为模块名,其中各配置字段含义如下:

name :字符串,定义编译产物的名称。如示例所示,最终编译产物名为gzip.bin

srcs:字符串数组,定义编译此模块所对应的源文件。如示例所示,对应的源码文件应为 src/test/minigzip.c文件。

shared_libs:字符串数组,定义此模块所依赖的动态库。如示例所示,本模块依赖于libz.so。

stl :字符串,定义此模块所选择的STL库,一般可选项包括“libc++”,“libc++_static”,”libstdc++”与“none”。

除此之外还有一些常用的配置选项,这里一并列出:

init_rc:字符串,定义进程的rc启动文件。

cflag:字符串数组,用于定义编译此模块编译时适用于编译器的编译选项,一般我们可以在这里面传递一些宏参数。

cppflags:字符串数组,定义编译此模块时适用于C++编译器的编译选项。

static_libs :字符串数组,定义编译此模块时需要被静态链接到该模块的库。

visibility :定义此模块的可见性。

proprietary :布尔值,用于决定此模块是否属于Vendor,并且是否应当安装到vendor内。

如果你需要的是预编译的二进制库,则可以使用cc_prebuilt_binay关键字作为模块名,其余配置项则比较类似。

编译C/C++共享库

有时候我们需要编译一些库,以提供给其他模块使用,这时候如何编写bp文件呢,这里给出一个例子:

cc_library {
    name: "PixelVibratorCommonSunfish",
    srcs: [
        "HardwareBase.cpp",
    ],
    shared_libs: [
        "libbase",
        "libcutils",
        "liblog",
        "libutils",
    ],
    cflags: [
        "-DATRACE_TAG=(ATRACE_TAG_VIBRATOR | ATRACE_TAG_HAL)",
        "-DLOG_TAG=\"[email protected]\"",
    ],
    export_include_dirs: ["."],
    vendor_available: true,
}

其中各个配置项含义如下:

name :字符串,定义此库文件的名称。

srcs :字符串数组,定义此库文件所对应的源码文件。

shared_libs :字符串数组,用于定义此库文件所依赖的其他库文件。

cflags :字符串数组,用于定义编译此库文件所需要配置的编译选项。

export_include_dirs :字符串数组,用于定义编译此库所需要包含的头文件。

vendor_available :布尔值,用于定义此模块是否能够被其他Vendor内的模块所访问。

更多其他配置项,可以参考官方指导文档。

编译Java APK

作为Android开发人员,是需要经常去编译APK的。虽然我们一般会使用Android Studio事先编译好APK,作为预编译的一部分打包镜像,但有些时候还是需要进行通过源码,在编译时生成APK,这里给出一个编译APK文件的bp示例:

android_app {
    name: "VehicleSetting",
    platform_apis: true,
    certificate: "platform",
    srcs: ["java/**/*.java"],                                                                                                                                                                                                            
    resource_dirs: [
        "res",
    ],  
    manifest: "AndroidManifest.xml",
    optimize: {
        enabled: false,
    },  
    libs: [
   
    ],  
    static_libs: [
        "com.google.android.material_material",
        "androidx.appcompat_appcompat",
        "androidx-constraintlayout_constraintlayout",
    ],  
    
}

各个配置项的含义如下:

name :字符串,用于定义此APK的名称,在此示例中生成的APK名为 VehicleSetting .apk

platform_apis :布尔值,用于判定是否使用平台限定的API等级还是可以设置SDK的API的等级,如果设置为true,则sdk_version必须为空。

certificate :字符串,用于定义此APK所使用的签名证书。

srcs :字符串数组,用于定义此APK的源码文件。

resource_dirs :字符串数组,用于定义此APK所依赖的资源文件。

manifest :字符串,用于定义此APK的Manifest.xml文件。

optimize :可再行扩展的配置,此处enabled设为true则开启优化,设为false则不需要进行优化。

static_libs :字符串,用于定义此APK所依赖的静态库。

除此之外还有一些常用的配置选项:

max_sdk_version :字符串,定义此APK所支持的最大SDK版本。

min_sdk_version :字符串,用于定义此APK所支持的最小的SDK版本。

jni_libs :字符串数组,用于定义此APK所依赖的JNI调用库。

package_name :字符串,用于定义此apk的包名。

编译Java Jar包

如果我们需要编译Jar包,以便其他APP使用,如何通过bp文件来进行编译呢,这里给出一个示例:

android_library {
    name: "launcher-aosp-tapl",
    static_libs: [
        "androidx.annotation_annotation",
        "androidx.test.runner",
        "androidx.test.rules",
        "androidx.test.uiautomator_uiautomator",
        "androidx.preference_preference",
        "SystemUISharedLib",
    ],  
    srcs: [
        "tests/tapl/**/*.java",                                                                                                                                                                                                          
        "src/com/android/launcher3/ResourceUtils.java",
        "src/com/android/launcher3/testing/TestProtocol.java",
    ],  
    resource_dirs: [ ],
    manifest: "tests/tapl/AndroidManifest.xml",
    platform_apis: true,
}

从该示例可以看出,其实编译APK与编译Jar包是很相似的写法,这里不再赘述。

总结

无论是编写makefile还是编写bp文件,其实都没什么技巧可言,重要的是根据AOSP的示例与Soong官方的指导文件来进行编写。但两者之间还是有一些可以类比的地方的,这里给出编写Makefile与编写bp文件的一些类比:

含义Android.bpAndroid.mk
模块名定义name:” ModuleName”LOCAL_MODULE := ModuleName
编译产物定义cc_library_shared cc_library_static cc_binary cc_prebuilt_binaryinclude (BUILDSHAREDLIBRARY)include(BUILD_STATIC_LIBRARY) include (BUILDEXECUTABLE)include(PREBUILT_SHARED_LIBRARY)
源代码引用srcsLOCAL_SRC_FILES:=
头文件引用include_dirsLOCAL_C_INCLUDES:=
共享库依赖shared_libsLOCAL_SHARED_LIBRARIES :=
静态库依赖static_libsLOCAL_STATIC_LIBRARIES :=
编译器选项cflagsLOCAL_CFLAGS +=

以上就是本篇博客的全部内容了,希望能对您有所帮助~

Happy
Happy
100 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
默认图片
FranzKafka95
极客,文学爱好者。如果你也喜欢我,那你大可不必害羞。
文章: 45

留下评论

zh_CNCN