props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react

没有检索到摘要

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

错误信息:

props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information

意思是 dangerouslySetInnerHTML的格式写错了

正确格式:

dangerouslySetInnerHTML = {{_html:"<div>这里放的是html字符串</div>"}}

<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()) ``` --- **
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值