android bp文件_Android.bp正确姿势添加宏控制编译指南
前言
随着Android版本的迭代,越来越多的移动终端都用上了香喷喷的Android 9和10系统。相对于原来的Android版本,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中添加宏控制有两种场景,分别是:
无条件控制的宏添加,形如:
#无条件控制宏编译
LOCAL_CFLAGS += -Wno-error=implicit-function-declaration -DPRINT
有条件控制的宏添加,即满足某个条件才添加对应的宏,这个场景比较,形如:
#有条件的添加宏控制
ifeq ($(ANDROIDBP_FUN), "YES")
LOCAL_CFLAGS += -DXXX
endif
下面的篇章我们将分别从上述两种场景出发,来说明在Android.bp中如何添加宏控制。
1.1 无条件控制的宏添加
这里我会以实际案例来说明,怎么一步步添加无条件控制的宏。
1.1.1 编写源文件main.c
#include
int main()
{
#ifdef PRINT//宏控制
printf("Hello world\n");
#endif
#ifdef XXX//宏控制
printf("XXX\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 += -DXXX
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] xxx@pd:~/ssd/xxx/ap/idh.code/xxxxroid/external/AndroidBp$ androidmk Android.mk > Android.bp
[SPRD] xxx@pd:~/ssd/xxx/ap/idh.code/xxxxroid/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: ["-DXXX"] + [ // 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: ["-DXXX"] + [ // 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 += -DXXX
endif
1.2.1 添加go脚本
我们在Android.bp同级目录添加go脚本文件xxxparser.go,其内容如下:
package xxxparser
import (
"android/soong/android"
"android/soong/cc"
)
func init() {
// resister a module "xxxparser_defaults"
android.RegisterModuleType("xxxparser_defaults", xxxdroidDefaultsFactory)
}
func xxxdroidDefaultsFactory() (android.Module) {
module := cc.DefaultsFactory()
android.AddLoadHook(module, xxxdroidDefaults)
return module
}
func xxxdroidDefaults(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,"-DXXX")
}
return cppflags
}
1.2.2 Android.bp使用go脚本
在Android.bp开头位置引入go脚本文件xxxparser.go,如下:
//引入go脚本
bootstrap_go_package {
name: "soong-xxxparser",
pkgPath: "android/soong/xxxparser",
deps: [
"blueprint",
"blueprint-pathtools",
"soong",
"soong-android",
"soong-cc",
"soong-genrule",
],
srcs: [
"xxxparser.go",
],
pluginFor: ["soong_build"],
}
xxxparser_defaults {
name: "xxxparser_defaults",
}
ANDROIDBP_FUN = ["YES"]
cc_binary {
defaults: ["xxxparser_defaults"],
name: "AndroidBp",
srcs: ["main.c"],
cflags: ["-Wno-error=implicit-function-declaration"],
shared_libs: [
"libcutils",
"liblog",
"libutils",
],
}
以上语句可以保证运行Android.bp时,先编译对应的xxxparser.go运行go脚本时,会首先运行init函数,将 xxxdroidDefaultsFactory函数注册到module中,之后调用xxxdroidDefaultsFactory函数时,会将回调函数 xxxdroidDefaults注册进去之后调用 privateParserDefaults 时,我们可以从 ctx.AConfig() 中获取好多属性
(参考 build/soong/android/config.go 中对 build/soong/android/module.go中的 androidBaseContext interface的各种函数实现),其中有一项是获取宏值的,之后回调xxxdroidDefaults添加宏信息。
1.2.3 演示运行
在正式进行编译之前,让我们对编译环境设置环境变量,我这里使用的是ubuntu编译,所以这个不用多说怎么配置环境变量了,如下:
[SPRD] xxx@pd:~/ssd/xxx/ap/idh.code$ export ANDROIDBP_FUN=YES
[SPRD] xxx@pd:~/ssd/xxx/ap/idh.code$ echo $ANDROIDBP_FUN
YES
[SPRD] xxx@pd:~/ssd/xxx/ap/idh.code$
执行可执行文件,查看输出结果,完美。
1|xxx:/system/bin # ./AndroidBp
XXX
This is AndroidBp Test
xxx:/system/bin #
二.浅析go脚本文件
由于对go语法不是非常了解,这里只对xxxparser.go中用到的语法进行简单的解析,以便大家了解,如果想深入的话得自行研究内功了。这里臣妾做不到。
2.1 解析 init 函数
我们知道bin文件执行先从main开始,而运行go语言时,先运行init函数,我们这里的此函数为:
func init() {
// resister a module "xxxparser_defaults"
// 注册xxxparser_defaults, 指定要调用的方法入口xxxdroidDefaultsFactory
android.RegisterModuleType("xxxparser_defaults", xxxdroidDefaultsFactory)
}
2.1.1 解析RegisterModuleType函数
脚本开头import了两个包 “android/soong/android” 和 “android/soong/cc”从 build/soong/ 目录下搜索 “func RegisterModuleType” 来获取RegisterModuleType函数的定义位置RegisterModuleType函数位于build/soong/android/register.go中,如下:
func RegisterModuleType(name string, factory ModuleFactory) {
moduleTypes = append(moduleTypes, moduleType{name, ModuleFactoryAdaptor(factory)})
}
可以看出将 name 和 ModuleFactoryAdaptor(factory) append到 var moduleTypes []moduleType 中
moduleType类型如下:
type moduleType struct {
name string
factory blueprint.ModuleFactory
}
2.1.2 查找ModuleFactory类型
xxxparser.go 开头 import “github.com/google/blueprint”我们从github上下载 github.com/google/blueprint/ 仓后,搜索 “type ModuleFactory” 来获取 ModuleFactory 定义位置,位于 github.com/buleprint/context.go中,如下:
// A ModuleFactory function creates a new Module object. See the
// Context.RegisterModuleType method for details about how a registered
// ModuleFactory is used by a Context.
type ModuleFactory func() (m Module, propertyStructs []interface{})
可以看出ModuleFactory为一函数指针,形参为null,返回类型为 Module, []interface{}。
注: 此处我们详细的讲解了如何搜索变量名和函数名的位置,即关键字 “type xxx"和"func xxx”,之后不再给出详细步骤。
2.1.3 解析ModuleFactoryAdaptor函数
通过搜索如下所示:
// ModuleFactoryAdapter Wraps a ModuleFactory into a blueprint.ModuleFactory by converting an Module
// into a blueprint.Module and a list of property structs
func ModuleFactoryAdaptor(factory ModuleFactory) blueprint.ModuleFactory {
return func() (blueprint.Module, []interface{}) {
module := factory()
return module, module.GetProperties()
}
}
此处将xxxparser.go中的 type ModuleFactory func() Module 函数指针,转换成 blueprint.ModuleFactory 类型的函数指针。
2.2 解析回调函数 xxxdroidDefaultsFactory
从上文可以得知,xxxdroidDefaultsFactory类型为 type ModuleFactory func() Module
我们实现了这个函数为:
func xxxdroidDefaultsFactory() (android.Module) {
module := cc.DefaultsFactory()
android.AddLoadHook(module, xxxdroidDefaults)
return module
}
2.2.1 解析 DefaultsFactory()函数
函数实现见 build/soong/cc/cc.go,如下:
func DefaultsFactory(props ...interface{}) android.Module {
module := &Defaults{}
module.AddProperties(props...)
module.AddProperties(
&BaseProperties{},
&VendorProperties{},
&BaseCompilerProperties{},
&BaseLinkerProperties{},
&LibraryProperties{},
&FlagExporterProperties{},
&BinaryLinkerProperties{},
&TestProperties{},
&TestBinaryProperties{},
&UnusedProperties{},
&StlProperties{},
&SanitizeProperties{},
&StripProperties{},
&InstallerProperties{},
&TidyProperties{},
&CoverageProperties{},
&SAbiProperties{},
&VndkProperties{},
<OProperties{},
&PgoProperties{},
&android.ProtoProperties{},
)
android.InitDefaultsModule(module)
return module
}
好了,就到这里了。不是本人赖,是因为这个我也是参考别人的。但是各位放心,后续我会继续将本章接力下去继续分析精进的。
写在最后
Android.bp正确姿势添加宏控制编译指南中介绍的两种添加宏的场景就到这里了,我想通过这个文档大伙一定能构建自己的Android.bp脚本了。好了最后如果文章对你有帮助麻烦点个赞,如果觉得很low也可以拍个砖一起探讨。
相关推荐
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是
douyin-favorite-MyLike-main.zip
douyin-favorite-MyLike-main.zip
风光储虚拟同步VSG并离网切换预同步控制仿真(Simulink仿真实现)
内容概要:本文针对风光储混合微电网系统,深入研究了虚拟同步发电机(VSG)技术在并网与离网两种运行模式间进行切换时的关键控制策略——预同步控制,并基于Simulink平台构建了完整的系统仿真模型以验证该策略的有效性。该模型集成了风力发电、光伏发电和储能系统,通过VSG控制算法赋予电力电子逆变器类似于传统同步发电机的惯性和阻尼特性,从而显著增强了微电网在模式切换过程中的动态稳定性与鲁棒性。其中,预同步控制环节是实现无缝切换的核心,它通过实时调节VSG输出电压的频率、相位和幅值,使其在并网开关动作前就与主电网的电压参数达到高度一致,有效消除了并网冲击电流,实现了平滑、无扰动的模式转换。通过仿真结果,可以系统地分析和优化控制器的各项参数,进而验证该整体控制方案的技术可行性与优越性能。; 适合人群:具备电力电子技术、自动控制理论和电力系统基础的专业知识,从事新能源发电、微电网运行与控制、电力系统自动化等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究风光储一体化混合微电网的能量管理策略与并离网无缝切换控制技术;②深入学习和掌握虚拟同步机(VSG)的工作原理、数学建模及其在逆变器控制中的具体实现方法;③利用Simulink进行复杂的电力系统动态仿真,以验证和评估新型控制算法的动态响应特性和有效性。; 阅读建议:此资源以Simulink仿真为核心实践工具,使用者应紧密结合电力系统的基础理论知识,深入理解VSG的数学模型和控制逻辑,尤其要重点关注预同步环节的控制策略设计,并通过反复调整仿真模型中的各项参数来观察系统的动态响应变化,从而深化对微电网稳定运行机制和高级控制技术的理解。
【顶级EI复现】新扩展移相角下的双有源桥DC-DC 变换器优化控制策略(Simulink仿真实现)
内容概要:本文聚焦于“新扩展移相角下的双有源桥DC-DC变换器优化控制策略”的研究与仿真实现,基于Simulink平台系统地构建了完整的仿真模型,深入探讨了软开关实现、最小电流应力优化及闭环控制策略的设计方法。文章提出一种改进型扩展移相(EPS)调制策略,通过引入扩展移相角有效拓宽软开关范围,提升变换效率并降低功率器件的电压与电流应力。结合KKT最优性条件与分段解析优化理论,实现了软开关与最小应力的协同控制目标,并设计双闭环控制系统以增强动态响应与鲁棒性。研究成果成功复现了高水平EI期刊论文的核心思想,具有较强的学术参考价值与工程应用意义。; 适合人群:电力电子、电气工程及其自动化等方向的研究生、科研人员,以及具备一定Simulink建模能力与电力电子拓扑控制基础的工程技术人员。; 使用场景及目标:①深入理解双有源桥(DAB)变换器的工作机理与先进控制策略;②掌握基于KKT条件的优化控制建模方法;③在Simulink中复现并验证EI级论文提出的控制算法,服务于科研论文撰写、课题研究或实际项目开发; 阅读建议:建议结合文中涉及的EPS调制、软开关条件推导、KKT优化数学建模等内容进行系统学习,重点关注仿真模块的参数设置、控制逻辑实现与波形分析,以全面掌握该优化策略的技术细节与工程实现路径。
AI大模型医学影像诊断智能识别应用方案.pptx
AI大模型医学影像诊断智能识别应用方案.pptx


Google技术社区
