[ Android 编译 ] Android.bp 根据条件添加宏定义
Posted 那个写代码的
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ Android 编译 ] Android.bp 根据条件添加宏定义相关的知识,希望对你有一定的参考价值。
[ android 编译 ] Android.bp 根据条件添加宏定义
尊重原创,转载请注明出处!
创作不易,如有帮助请点赞支持~
参考:
Android.bp文件详解
Android.bp入门指南之浅析Android.bp语法
Android.bp正确姿势添加宏控制编译指南
Android.bp 添加宏开关
之前对 Android.bp 一直了解不多,也就是停留在大概能看懂,可以简单改改的阶段。最近遇到了一个问题,需要根据编译参数去添加宏定义,一下子就傻眼了。
如果不需要添加控制逻辑,只是单纯地添加宏定义,直接在 Android.bp 对应模块的 cflags / cppflags
中添加 "-DXXX"
即可。
但是如果需要添加控制逻辑,由于 bp 文件跟 mk 文件不同,它是纯粹的配置,没有分支等流程控制,所以只能通过编写 Go 语言实现。
之前没接触过 go 语言,但是编程语言都是相通的,百度一下相关的文章,根据自己的实际情况进行修改,磕磕绊绊地也算是完成了这个需求,这里记录一下实现的整个流程。
编写 go 脚本文件
首先添加 bionic/linker/linker_controller.go
文件,编写控制逻辑:
package linker_controller
import (
"android/soong/android"
"android/soong/cc"
// 如果需要打印调试日志,这个需要导包。如果不需要打印则无需导包,否则编译会报错导入未使用的包
"fmt"
)
func init()
// 在 go 的入口函数中,将linkerDefaultsFactory注册到"linker_controller"的moduleType中
android.RegisterModuleType("linker_controller", linkerDefaultsFactory)
func linkerDefaultsFactory() (android.Module)
module := cc.DefaultsFactory()
// 添加装载时的hook函数
android.AddLoadHook(module, linkerDefaultsDefaults)
return module
func linkerDefaultsDefaults(ctx android.LoadHookContext)
type props struct
Cflags []string
p := &props
// 获取需要定义的宏,添加到cflags中
p.Cflags = cflagsDefaults(ctx)
ctx.AppendProperties(p)
// 这里加入控制逻辑,当符合条件时添加相应的-DXXX参数
func cflagsDefaults(ctx android.BaseContext) ([]string)
var cppflags []string
// 打印调试日志
fmt.Println("DEBUG === BUILD_TYPE:", ctx.AConfig().Getenv("BUILD_TYPE"))
// 当环境变量BUILD_TYPE为custom时,添加CUSTOM_LINKER的宏定义
if ctx.AConfig().Getenv("BUILD_TYPE") == "custom"
cppflags = append(cppflags, "-DCUSTOM_LINKER")
return cppflags
Android.bp 引入 go 脚本文件
添加了 go 脚本文件后,还需要把它配置到 Android.bp 中,才能生效,需要对 bionic/linker/Android.bp
做一点改动:
// 引入go脚本,添加编译go脚本所需的依赖
bootstrap_go_package
// 模块名为soong-[go文件名]
name: "soong-linker_controller",
// go文件包名路径
pkgPath: "android/soong/linker_controller",
deps: [
"blueprint",
"blueprint-pathtools",
"soong",
"soong-android",
"soong-cc",
"soong-genrule",
],
// go脚本文件
srcs: [
"linker_controller.go",
],
pluginFor: ["soong_build"],
// 自定义模块类型,即在go脚本中注册的moduleType
linker_controller
// 模块名称
name: "linker_controller_defaults",
cc_binary
// 在defaults中添加引用上面添加的module
defaults: ["linux_bionic_supported", "linker_defaults", "linker_controller_defaults"],
srcs: [ ":linker_sources" ],
...
在代码中添加对宏的判断
#ifdef CUSTOM_LINKER
// do something
DL_WARN("DEBUG === CUSTOM_LINKER has defined!");
#endif
结尾
本篇博客只是简单地添加了通过环境变量来控制宏的逻辑。显然,可以通过 go 脚本控制 Android.bp 的逻辑还有很多,想要掌握并不是一时半会儿的事,以后有机会使用到更多的控制逻辑的时候,再做进一步的学习和记录吧。
Android.bp学习
一. Android.bp概念
Android.bp 文件首先是 Android 系统的一种编译配置文件,是用来代替原来的 Android.mk文件的。在Android7.0 以前,Android 都是使用 make 来组织各模块的编译,对应的编译配置文件就是 Android.mk。
在 Android7.0 开始,Google 引入了 ninja 和 kati 来编译,为啥引入 ninja?因为随着 Android 越来越庞大,module 越来越多,编译时间也越来越久,而使用 ninja 在编译的并发处理上较 make 有很大的提升。Ninja 的配置文件就是Android.bp,Android 系统使用 Blueprint 和 Soong 工具来解析 Android.bp 转换生成 ninja文件。为了兼容老的 mk 配置文件,Android 当初也开发了 Kati 工具来转换 mk 文件生成ninja,目前 Android Q 里边,还是支持 Android.mk 方式的。相信在将来的版本中,会彻底让 mk 文件废弃,同时 Kati 也就淘汰了,只保留 bp 配置方式,所以我们要提前学习bp。
这里涉及到Ninja, kati, Soong, bp概念,接下来分别简单介绍一下。
Ninja
ninja是一个编译框架,会根据相应的ninja格式的配置文件进行编译,但是ninja文件一般不会手动修改,而是通过将Android.bp文件转换成ninja格文件来编译。
Android.bp
Android.bp的出现就是为了替换Android.mk文件。bp跟mk文件不同,它是纯粹的配置,没有分支、循环等流程控制,不能做算数逻辑运算。如果需要控制逻辑,那么只能通过Go语言编写。
Soong
Soong类似于之前的Makefile编译系统的核心,负责提供Android.bp语义解析,并将之转换成Ninja文件。Soong还会编译生成一个androidmk命令,用于将Android.mk文件转换为Android.bp文件,不过这个转换功能仅限于没有分支、循环等流程控制的Android.mk才有效。
Blueprint
Blueprint是生成、解析Android.bp的工具,是Soong的一部分。Soong负责Android编译而设计的工具,而Blueprint只是解析文件格式,Soong解析内容的具体含义。Blueprint和Soong都是由Golang写的项目,从Android 7.0,prebuilts/go/目录下新增Golang所需的运行环境,在编译时使用。
Kati
kati是专为Android开发的一个基于Golang和C++的工具,主要功能是把Android中的Android.mk文件转换成Ninja文件。代码路径是build/kati/,编译后的产物是ckati。
重要的事情说三篇,Android.mk可以引用Android.bp中的模块,反之Android.bp不能引用Android.mk中的模块。
重要的事情说三篇,Android.mk可以引用Android.bp中的模块,反之Android.bp不能引用Android.mk中的模块。
重要的事情说三篇,Android.mk可以引用Android.bp中的模块,反之Android.bp不能引用Android.mk中的模块。
二. Android mk转换成Android bp
1.安装androidmk 工具
我们以rk3399来举例说明
source build/envsetup.sh
lunch rk3399_roc_pc_plus-userdebug
make androidmk
生成androidmk转换工具,路径为:/out/soong/host/linux-x86/bin/androidmk
2.转换
androidmk Android.mk > Android.bp
三.Android bp语法
1.编译静态库
首先我们把vendor下创建一个Study的目录,然后再Study创建一个test1的目录,tree如下:
我们的目标是把test.c编译成一个静态库
test.c代码如下:
#include <stdio.h>
int test(void)
printf("hello Androoid.mk\\r\\n");
return 0;
Android.bp代码如下:
cc_library_static
name: "test3",
srcs: ["test.c"],
编译方法:
方法1:在android 跟目录下敲指令:make test3
方法2:在vendor/Study/test3目录下敲指令mm
注意:两个方法都需要先source build/envsetup.sh -> lunch选择41
test.a生成在out/target/product/rk3399_roc_pc_plus/obj_arm/STATIC_LIBRARIES/test3_intermediates/test3.a
NOTED:我们发现生成的并不是libtest3.a,而是test3.a,这个要注意下
其中cc_library_static就是编译成c/c++ 静态库,可以有以下类型
name就是模组的名称
srcs就是源文件
2.编译动态库
首先我们把vendor下创建一个Study的目录,然后再Study创建一个test2的目录,tree如下:
我们的目标是把test.c编译成一个静态库
test.c代码如下:
#include <stdio.h>
int test(void)
printf("hello Androoid.mk\\r\\n");
return 0;
Android.bp代码如下:
cc_library_shared
name: "test4",
srcs: ["test.c"],
编译方法:
方法1:在android 跟目录下敲指令:make test4
方法2:在vendor/Study/test4目录下敲指令mm
注意:两个方法都需要先source build/envsetup.sh -> lunch选择41
test.so生成在out/target/product/rk3399_roc_pc_plus/obj_arm/SHARED_LIBRARIES/test4_intermediates/test4.so
NOTED:我们发现生成的并不是libtest4.so,而是test4.so,这个要注意下
以上是关于[ Android 编译 ] Android.bp 根据条件添加宏定义的主要内容,如果未能解决你的问题,请参考以下文章