<think>这个错误表明在Soong插件的Go代码中,`android.AidlInterfaceFactory`未定义。这是因为在Soong构建系统中,`AidlInterfaceFactory`可能不是公开可用的函数,或者需要特定的导入路径。我们需要调整实现方式。
### 解决方案修正
我们将使用另一种方法:创建一个自定义模块类型,它包含一个`aidl_interface`模块,并根据Android版本动态设置其`enabled`属性。
### 修正后的实现
#### 1. 修改`custom_plugin.go`
```go:custom_plugin.go
package main
import (
"android/soong/android"
"android/soong/cc"
"strconv"
)
func init() {
android.RegisterModuleType("conditional_aidl_interface", conditionalAidlInterfaceFactory)
}
type conditionalAidlInterface struct {
android.ModuleBase
properties struct {
// 我们将在这里包含原始aidl_interface的所有属性
// 但实际上,我们不需要复制所有属性,而是通过一个隐藏的aidl_interface模块
Srcs []string
Versions []string
Stability string
// 其他属性...
}
// 我们将创建一个隐藏的aidl_interface模块
hiddenModule android.Module
}
func conditionalAidlInterfaceFactory() android.Module {
module := &conditionalAidlInterface{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
return module
}
func (m *conditionalAidlInterface) DepsMutator(ctx android.BottomUpMutatorContext) {
// 在Android 9上跳过创建模块
sdkVerStr := ctx.Config().Getenv("RELEASE_PLATFORM_SDK_VERSION")
if sdkVerStr == "" {
// 默认处理,如果无法获取版本,则跳过
return
}
sdkVer, err := strconv.Atoi(sdkVerStr)
if err != nil {
ctx.PropertyErrorf("sdk_version", "Invalid SDK version: %s", sdkVerStr)
return
}
// 如果SDK版本大于28(Android 9),则创建隐藏的aidl_interface模块
if sdkVer > 28 {
// 创建一个aidl_interface模块
props := struct {
Name string
Srcs []string
Versions []string
Stability string
}{
Name: m.Name() + "_hidden",
Srcs: m.properties.Srcs,
Versions: m.properties.Versions,
Stability: m.properties.Stability,
}
ctx.CreateModule(android.AidlInterfaceFactory(), &props)
}
}
```
#### 2. 修改`Android.bp`
```bp:Android.bp
bootstrap_go_package {
name: "soong-custom-plugin",
pkgPath: "android/soong/custom",
deps: [
"soong-android",
"soong-builtins",
],
srcs: ["custom_plugin.go"],
pluginFor: ["soong_build"],
}
conditional_aidl_interface {
name: "my_service",
srcs: ["IMyService.aidl"],
versions: ["1"],
stability: "vintf",
}
```
### 关键修正点说明
1. **避免直接使用未导出函数**:
- 不再尝试直接使用`android.AidlInterfaceFactory()`创建模块,而是使用`ctx.CreateModule`动态创建模块
- 通过`ctx.CreateModule`可以创建任何类型的模块
2. **条件化创建模块**:
- 在`DepsMutator`阶段(依赖关系处理阶段)检查Android版本
- 当版本>28(即Android 9以上)时,动态创建一个隐藏的`aidl_interface`模块
- 隐藏模块的名称加上`_hidden`后缀避免冲突
3. **属性传递**:
- 将`conditional_aidl_interface`中定义的属性传递给隐藏的`aidl_interface`模块
- 需要确保传递所有必要的属性(如srcs, versions, stability等)
### 处理Android 9及以下版本
- 当SDK版本<=28时,不创建任何模块,相当于跳过编译
- 这样在Android 9上构建时,`conditional_aidl_interface`不会产生任何输出文件
### 注意事项
1. **属性传递完整性**:
- 示例中只传递了部分属性,实际需要传递`aidl_interface`支持的所有属性
- 可以在`conditionalAidlInterface`结构体中添加更多属性字段
2. **模块可见性**:
- 隐藏模块的名称使用`_hidden`后缀,避免与其他模块冲突
- 其他模块依赖时,应依赖`conditional_aidl_interface`的名称(如`my_service`),而不是隐藏模块
3. **动态创建模块**:
- `ctx.CreateModule`的第一个参数是模块工厂函数,这里使用`android.AidlInterfaceFactory()`
- 第二个参数是模块属性,以结构体形式传递
### 完整属性传递示例
如果需要传递更多属性(如`backend`):
```go
// 在conditionalAidlInterface结构体中添加属性
type conditionalAidlInterface struct {
...
properties struct {
Srcs []string
Versions []string
Stability string
Backend struct {
Java struct {
Enabled bool
}
Cpp struct {
Enabled bool
}
}
}
...
}
// 在DepsMutator中传递属性
props := struct {
Name string
Srcs []string
Versions []string
Stability string
Backend struct {
Java struct {
Enabled bool
}
Cpp struct {
Enabled bool
}
}
}{
Name: m.Name() + "_hidden",
Srcs: m.properties.Srcs,
Versions: m.properties.Versions,
Stability: m.properties.Stability,
Backend: m.properties.Backend,
}
```
### 验证构建
```bash
# 在Android 12上构建隐藏模块
RELEASE_PLATFORM_SDK_VERSION=31 m my_service_hidden
# 在Android 9上应无输出
RELEASE_PLATFORM_SDK_VERSION=28 m my_service_hidden
# 输出: "nothing to build"
```
---
**§§相关问题§§**:
1. 如何在Soong插件中处理模块依赖关系?
2. Soong构建系统有哪些不同的阶段(phase)?
3. 如何为动态创建的模块设置可见性(visibility)?
4. 除了`DepsMutator`,还有哪些Mutator阶段可用?</think>您遇到了一个关键问题:`android.AidlInterfaceFactory` 在 Soong 插件中不可直接访问。这是因为 `aidl_interface` 模块类型是在 Soong 的 AIDL 包中定义的,需要特殊处理才能访问。下面是完整的修正方案:
### 解决方案修正:正确访问 AIDL 模块工厂
#### 1. 修改 `custom_plugin.go` 使用正确的导入路径
```go:custom_plugin.go
package main
import (
"android/soong/android"
"android/soong/aidl" // 添加 AIDL 包导入
"strconv"
)
func init() {
// 注册自定义模块类型
android.RegisterModuleType("conditional_aidl_interface", conditionalAidlInterfaceFactory)
}
func conditionalAidlInterfaceFactory() android.Module {
// 使用 aidl.AidlInterfaceFactory() 替代 android.AidlInterfaceFactory()
module := aidl.AidlInterfaceFactory()
// 添加加载钩子
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
sdkVerStr := ctx.Config().Getenv("RELEASE_PLATFORM_SDK_VERSION")
if sdkVerStr == "" {
// 处理未定义环境变量的情况
return
}
sdkVer, err := strconv.Atoi(sdkVerStr)
if err != nil {
// 处理转换错误
ctx.PropertyErrorf("sdk_version", "Invalid SDK version: %s", sdkVerStr)
return
}
// Android 9 (API 28)跳过编译
if sdkVer <= 28 {
type props struct {
Enabled *bool
}
p := &props{Enabled: boolPtr(false)}
ctx.AppendProperties(p)
}
})
return module
}
func boolPtr(b bool) *bool { return &b }
```
#### 2. 更新 `Android.bp` 添加必要的依赖
```bp:Android.bp
bootstrap_go_package {
name: "soong-custom-plugin",
pkgPath: "android/soong/custom",
deps: [
"soong-android",
"soong-builtins",
"soong-aidl", // 添加 AIDL 依赖
],
srcs: ["custom_plugin.go"],
pluginFor: ["soong_build"],
}
conditional_aidl_interface {
name: "my_service",
srcs: ["IMyService.aidl"],
versions: ["1", "2"],
stability: "vintf",
backend: {
java: {
enabled: true,
},
cpp: {
enabled: true,
},
},
// 添加其他原始属性...
}
```
### 关键修正说明
1. **添加 AIDL 包导入**:
```go
import "android/soong/aidl"
```
- 这是访问 `AidlInterfaceFactory` 的必要导入
- 该包定义了所有 AIDL 相关的构建逻辑
2. **使用正确的工厂函数**:
```go
module := aidl.AidlInterfaceFactory()
```
- `aidl.AidlInterfaceFactory()` 返回实际的 AIDL 模块工厂
- 替代了之前不存在的 `android.AidlInterfaceFactory()`
3. **添加 AIDL 依赖**:
```bp
deps: [..., "soong-aidl"]
```
- 在 `bootstrap_go_package` 中添加 `soong-aidl` 依赖
- 确保插件可以链接到 AIDL 包
4. **错误处理增强**:
```go
if sdkVerStr == "" { ... }
if err != nil { ... }
```
- 添加环境变量未定义的处理
- 添加版本转换错误的处理
### 完整项目结构验证
```
project/
├── aidl/
│ ├── Android.bp
│ ├── custom_plugin.go
│ └── IMyService.aidl
└── other_modules/
└── ...
```
### 构建流程验证
1. **首次构建插件**:
```bash
m soong_plugins
```
2. **检查插件加载**:
```bash
# 查看 soong.log 确认插件加载
tail -f out/soong/soong.log
```
期望输出:
```
[DEBUG] Registered module type: conditional_aidl_interface
```
3. **测试不同版本**:
```bash
# Android 9 (API 28)
export RELEASE_PLATFORM_SDK_VERSION=28
m my_service
# 应输出: "module my_service disabled - skipping"
# Android 12 (API 31)
export RELEASE_PLATFORM_SDK_VERSION=31
m my_service
# 应正常编译生成:
# out/soong/.intermediates/my_service
```
### 备选方案:使用 ModuleFactory 注册
如果上述方法仍不可用,可以使用更底层的注册方式:
```go:custom_plugin.go
package main
import (
"android/soong/android"
"android/soong/aidl"
"strconv"
)
func init() {
// 直接注册模块工厂
android.RegisterModuleType("conditional_aidl_interface",
func() android.Module {
module := aidl.AidlInterfaceFactory()
android.AddLoadHook(module, versionHook)
return module
})
}
func versionHook(ctx android.LoadHookContext) {
// 相同版本检查逻辑
sdkVer, _ := strconv.Atoi(ctx.Config().Getenv("RELEASE_PLATFORM_SDK_VERSION"))
if sdkVer <= 28 {
type props struct { Enabled *bool }
p := &props{Enabled: boolPtr(false)}
ctx.AppendProperties(p)
}
}
func boolPtr(b bool) *bool { return &b }
```
### 注意事项
1. **依赖顺序**:
- 确保在 `soong-aidl` 之后加载插件
- 在 `Android.bp` 中添加:
```bp
pluginFor: ["soong_build", "soong-aidl"]
```
2. **API 级别对照**:
| Android 版本 | API 级别 |
|--------------|----------|
| Android 9 | 28 |
| Android 10 | 29 |
| Android 11 | 30 |
| Android 12 | 31 |
| Android 13 | 33 |
| Android 14 | 34 |
| Android 15 | 35 |
3. **调试技巧**:
```go
// 添加调试输出
ctx.Module().(*aidl.AidlInterface).Name())
```
---
**