Android.bp正确姿势添加宏控制编译指南

       Android.bp正确姿势添加宏控制编译指南



前言

  随着Android版本的迭代,越来越多的移动终端都用上了香喷喷的Android 9和10系统。相对于原来的Android版本,9和10越来越多的使用Android.bp替换以前的Android.mk编译脚本。我们知道 Android.mk采用Makefile的语言,所以为了控制条件编译和多版本适配,我们可以在不同产品直接在Android.mk中采用Makefile语言控制编译。虽然我们也可以通过Android的内置工具androidmk将Android.mk转换为Android.bp脚本,但是对于有宏控制的条件编译,androidmk是无能为力的。这是因为Android.bp是类似JSON的纯文本形式.对于Android.mk里面流控制部分,在Android.bp里要借助使用go语言文件去进行控制。好了说了这么多了,我想读者应该知道这个篇章要写什么了,那就是手把手带领大伙手撸Android.bp添加宏控制编译。



一.实战开始

我们知道在Android原来的编译脚本Android.mk中添加宏控制有两种场景,分别是:

  • 无条件控制的宏添加
  • 有条件控制的宏添加,即满足某个条件才添加对应的宏,这个场景比较多

下面我们分别从上述两种场景出发,来说明在Android.bp中如何添加。


1.1 无条件控制的宏添加

这里我会以实际案例来说明,怎么一步步添加无条件控制的宏。

1.1.1 编写源文件main.c

#include<stdio.h>
int main()
{
    #ifdef PRINT  //宏控制
    printf("Hello world\n");
    #endif

    #ifdef PAX //宏控制
    printf("PAX\n");
    #endif

    printf("This is AndroidBp Test\n");
    return 0;
}

代码非常简单,就是一个简单的打印。在我们正式在Android.bp中添加宏前,我们先看看Android.mk应该怎么编写。

1.1.2 编写Android.mk编译脚本

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

LOCAL_MODULE := AndroidBp
LOCAL_SRC_FILES := main.c
ANDROIDBP_FUN=YES
#有条件的添加宏控制
ifeq ($(ANDROIDBP_FUN), "YES") 
    LOCAL_CFLAGS += -DPAX
endif

#无条件宏控制
LOCAL_CFLAGS += -Wno-error=implicit-function-declaration  -DPRINT

LOCAL_SHARED_LIBRARIES :=  libcutils liblog     libutils 



include $(BUILD_EXECUTABLE)

这个也非常简单,就是编译一个可执行文件,并有条件和无条件的添加宏控制。

1.1.3 将Android.mk转换为Android.bp

在前面的博客中,我们知道Android内置的androidmk工具能将Android.mk转换为对应的Android.bp,但是当Android.mk中有宏条件控制时就无能为力了。下面让我们转换一下看看是否如此:


[SPRD] tangkw@pd:~/ssd/A50/ap/idh.code/paxdroid/external/AndroidBp$ androidmk  Android.mk  > Android.bp
[SPRD] tangkw@pd:~/ssd/A50/ap/idh.code/paxdroid/external/AndroidBp$ 

查看转换后生成的Android.bp文件如下,可以看到androidmk的转换失效了,

ANDROIDBP_FUN = ["YES"]
cc_binary {

    name: "AndroidBp",
    srcs: ["main.c"],

    // ANDROIDMK TRANSLATION ERROR: unsupported conditional
    // ifeq ($(ANDROIDBP_FUN), "YES")

    cflags: ["-DPAX"] + [ // ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional
    // endif
        "-Wno-error=implicit-function-declaration",
        "-DPRINT",
    ],  

    shared_libs: [
        "libcutils",
        "liblog",
        "libutils",
    ],  

}

1.1.4 Android.bp直接添加宏

通过前面的章节我们可以直接,Android.bp直接添加宏非常简单,只需要在cflags后面添加对应的宏就OK了。

    cflags: ["-DPAX"] + [ // ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional
    // endif
        "-Wno-error=implicit-function-declaration",
        "-DPRINT",
    ],  

1.2 有条件控制的宏添加

根据前面的章节我们知道,在Android.bp中需要有条件的添加宏是不能直接做到的,必须借助go脚本实现动态控制编译项,那么让我们看看怎么动态添加如下的宏:

#有条件的添加宏控制
ifeq ($(ANDROIDBP_FUN), "YES") 
    LOCAL_CFLAGS += -DPAX
endif

1.2.1 添加go脚本

我们在Android.bp同级目录添加go脚本文件paxparser.go,其内容如下:

package  paxparser

import (
        "android/soong/android"
        "android/soong/cc"
)

func init() {
    // resister a module "paxdroid_defaults"
    android.RegisterModuleType("paxparser_defaults", paxdroidDefaultsFactory)
}

func paxdroidDefaultsFactory() (android.Module) {
    module := cc.DefaultsFactory()
    android.AddLoadHook(module, paxdroidDefaults)
    return module
}

func paxdroidDefaults(ctx android.LoadHookContext) {
   type props struct {
        Cflags []string
    }   
    p := &props{}
    p.Cflags = globalDefaults(ctx)
    ctx.AppendProperties(p) 
}

func globalDefaults(ctx android.BaseContext) ([]string) {
    var cppflags []string
    if ctx.AConfig().Getenv("ANDROIDBP_FUN") == "YES" {
          cppflags = append(cppflags,"-DPAX")
    }   
    return cppflags
}

1.2.2 Android.bp使用go脚本

在Android.bp开头位置引入go脚本文件paxparser.go,如下:

//引入go脚本
bootstrap_go_package {
    name: "soong-paxparser",
    pkgPath: "android/soong/paxparser",
    deps: [
    "blueprint",
    "blueprint-pathtools",
    "soong",
    "soong-android",
    "soong-cc",
    "soong-genrule",
    ],  
    srcs: [
        "paxparser.go",
    ],  
    pluginFor: ["soong_build"],
}

paxparser_defaults {
    name: "paxparser_defaults",
}

ANDROIDBP_FUN = ["YES"]
cc_binary {
    defaults: ["paxparser_defaults"],
    name: "AndroidBp",
    srcs: ["main.c"],
    
   
    cflags: ["-Wno-error=implicit-function-declaration"],



    shared_libs: [
        "libcutils",
        "liblog",
        "libutils",
    ],

}

以上语句可以保证运行Android.bp时,先编译对应的paxparser.go运行go脚本时,会首先运行init函数,将 paxdroidDefaultsFactory函数注册到module中,之后调用paxdroidDefaultsFactory函数时,会将回调函数 paxdroidDefaults注册进去之后调用 privateParserDefaults 时,我们可以从 ctx.AConfig() 中获取好多属性
(参考 build/soong/android/config.go 中对 build/soong/android/module.go中的 androidBaseContext interface的各种函数实现),其中有一项是获取宏值的,之后回调paxdroidDefaults添加宏信息。

1.2.3 演示运行

在正式进行编译之前,让我们对编译环境设置环境变量,我这里使用的是ubuntu编译,所以这个不用多说怎么配置环境变量了,如下:


[SPRD] tangkw@pd:~/ssd/A50/ap/idh.code$ export  ANDROIDBP_FUN=YES
[SPRD] tangkw@pd:~/ssd/A50/ap/idh.code$ echo $ANDROIDBP_FUN
YES
[SPRD] tangkw@pd:~/ssd/A50/ap/idh.code$ 

执行可执行文件,查看输出结果,完美。

1|A77:/system/bin # ./AndroidBp
PAX
This is AndroidBp Test
A77:/system/bin #


写在最后

Android.bp正确姿势添加宏控制编译指南中介绍的两种添加宏的场景就到这里了,我想通过这个文档大伙一定能构建自己的Android.bp脚本了。好了最后如果文章对你有帮助麻烦点个赞,如果觉得很low也可以拍个砖一起探讨。

发布了113 篇原创文章 · 获赞 123 · 访问量 35万+

猜你喜欢

转载自blog.csdn.net/tkwxty/article/details/105111218