[ Android 编译 ] Android.bp 根据条件添加宏定义

本文介绍了如何在Android.bp中根据条件添加宏定义,由于Android.bp不支持流程控制,因此通过编写Go脚本文件实现。示例展示了如何在Go脚本中检查环境变量并添加宏,并在Android.bp中引入和应用该脚本。最终,代码中可以根据宏进行特定操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

尊重原创,转载请注明出处!
创作不易,如有帮助请点赞支持~

参考:
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 构建系统中,`Android.bp` 是一种基于 Blueprint 的构建描述文件,用于替代传统的 `Android.mk`。为了实现在 `Android.bp` 中通过宏进行条件编译或配置控制,通常需要结合 Go 脚本来动态生成所需的宏定义。 以下是具体方法: #### 使用 Go 脚本动态生成宏定义 由于 `Android.bp` 不支持直接编写复杂的逻辑来有条件添加宏定义,因此可以通过外部的 Go 脚本来完成这一功能。Go 脚本可以读取环境变量或其他输入参数,并将其转换为适合 `Android.bp` 的格式。 1. **创建 Go 脚本** 首先,在与 `Android.bp` 同级目录下创建一个 `.go` 文件(例如 `surface.go`),该脚本负责生成特定的宏定义[^3]。 下面是一个简单的 Go 脚本示例: ```go package surface import ( "android/soong/android" ) func init() { android.RegisterModuleType("macro_module", MacroFactory) } type Macro struct { android.ModuleBase } func MacroFactory() android.Module { module := &Macro{} module.AddProperties(&struct{}{}) android.InitDefaultModule(module) return module } func (m *Macro) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyBool("multimedia_support_enabled", true) if multimediaSupportEnabled, ok := ctx.Config().Getenv("MULTIMEDIA_XXX_SUPPORT"); ok && multimediaSupportEnabled == "true" { ctx.AppendCompileFlags("-DMULTIMEDIA_XXX_SUPPORT") } } ``` 2. **修改 Android.bp 文件** 接下来,在 `Android.bp` 文件中引入上述 Go 脚本并调用其功能。以下是一个典型的 `Android.bp` 示例: ```blueprint macro_module { name: "macro-support", srcs: ["surface.go"], properties: { multimedia_support_enabled: true, }, } cc_library { name: "my-library", srcs: [ "example.cpp", ], cflags: [ "-Wall", "$(inherited)", ], compile_flags: ":macro-support", } ``` 上述代码片段展示了如何通过 `compile_flags` 属性引用由 Go 脚本生成的宏定义[^4]。 3. **验证宏定义是否生效** 宏定义最终会传递给编译器作为命令行选项的一部分。如果一切设置正确,则可以在 C/C++ 源码中使用这些宏来进行条件编译。例如: ```cpp #ifdef MULTIMEDIA_XXX_SUPPORT void enableMultimediaFeature() { // 实现多媒体特性 } #else void disableMultimediaFeature() { // 默认行为 } #endif ``` #### 注意事项 - 如果项目中有多个模块共享相同的宏定义,建议将这些宏集中管理在一个单独的 Go 脚本中,以便于维护和扩展[^5]。 - 确保 Go 脚本中的逻辑能够适配不同的构建场景,尤其是当某些环境变量可能不存在时,应提供默认值以避免错误发生。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值