动态编译android.bp

我想在android.bp中,采用go语言添加条件变量进行动态添加。例如:

art_module_java_defaults {
    name: "art_module_source_build_java_defaults",
    defaults_visibility: [
        "//art:__subpackages__",
        "//libcore:__subpackages__",
        "//libnativehelper:__subpackages__",
    ],
    enabled: false,
    soong_config_variables: {
        source_build: {
            bar{
                  
            }
        },
    },
    target: {
        windows: {
            enabled: false,
        },
    },
}

我想要在bar里面,添加cflags,该如何实现.go语言例子

func init() {
    android.RegisterModuleType("llvm_defaults", llvmDefaultsFactory)
}
func llvmDefaultsFactory() android.Module {
    module := cc.DefaultsFactory()
    android.AddLoadHook(module, llvmDefaults)
    return module
}

func llvmDefaults(ctx android.LoadHookContext) {
    type props struct {
        Target struct {
            Android struct {
                Cflags  []string
                Enabled *bool
            }
            Host struct {
                Enabled *bool
            }
            Not_windows struct {
                Cflags []string
            }
        }
        Cflags []string
    }
    p := &props{}
    p.Cflags = globalFlags(ctx)
    p.Target.Android.Cflags = deviceFlags(ctx)
    // Mingw fails to link binaries with lots of debug information
    p.Target.Not_windows.Cflags = hostFlags(ctx)
    if ctx.Config().IsEnvTrue("DISABLE_LLVM_DEVICE_BUILDS") {
        p.Target.Android.Enabled = proptools.BoolPtr(false)
    }
    ctx.AppendProperties(p)
}

但是这个例子没有bp的,我不知道多级空间里面,是通过什么方法去获取

要在Android.bp中动态添加条件变量,并在bar模块中使用该条件变量添加cflags,可以按照以下步骤进行:
1、在Android.bp中定义条件变量。例如,可以使用以下代码定义名为my_cflags的条件变量:

my_cflags {
    bazel_module: {
        name: "my_cflags",
        visibility: ["//visibility:public"],
    },
    default: "",
}

在需要使用该条件变量的模块(例如bar)中,将该条件变量添加到cflags中。例如,可以使用以下代码将my_cflags添加到bar的cflags中:

cc_binary {
    name: "bar",
    srcs: ["bar.c"],
    cflags: ["$(my_cflags)"],
}

3、在需要动态设置该条件变量的地方,例如在Android.bp的某个函数中,使用ctx.VariableFunc来设置该条件变量的值。例如,可以使用以下代码设置my_cflags的值:

my_cflags_value = func() (string, error) {
    if some_condition {
        return "-DENABLE_FEATURE", nil
    } else {
        return "", nil
    }
}

my_cflags = ctx.VariableFunc("my_cflags", my_cflags_value)

在这个例子中,如果some_condition为true,则设置my_cflags为"-DENABLE_FEATURE",否则设置为""。

注意,为了使用ctx.VariableFunc,需要在Android.bp的顶部添加如下的import:

go_import("android/soong/android")

这些步骤可以在Android.bp的任何位置执行,但最好将它们放在函数中,并在module部分中使用这个函数。这样可以更好地组织代码并使它更易于维护。

用config模块,就是添加一个名为foo的条件变量,在Android.bp文件中定义:


config_defaults {
    name: "my_config_defaults",
    vars: {
        foo: false,
    },
}

art_module_java_defaults {
    name: "art_module_source_build_java_defaults",
    defaults_visibility: [
        "//art:__subpackages__",
        "//libcore:__subpackages__",
        "//libnativehelper:__subpackages__",
    ],
    enabled: false,
    target: {
        windows: {
            enabled: false,
        },
    },
}

if (config.my_config_defaults.vars.foo) {
    art_module_java_defaults.enabled = true
}

该回答引用ChatGPT
你可以通过在 bar 中添加 cflags 属性来设置编译标志。具体的实现方法如下所示:


art_module_java_defaults {
    name: "art_module_source_build_java_defaults",
    defaults_visibility: [
        "//art:__subpackages__",
        "//libcore:__subpackages__",
        "//libnativehelper:__subpackages__",
    ],
    enabled: false,
    soong_config_variables: {
        source_build: {
            bar{
                cflags: [
                    "-Ipath/to/include/dir",
                    "-DDEFINE_NAME=value",
                    // ...
                ],
            }
        },
    },
    target: {
        windows: {
            enabled: false,
        },
    },
}

在 cflags 属性中,你可以添加任意数量的编译标志,例如头文件包含路径 (-I)、宏定义 (-D)、链接库路径 (-L)、链接库名 (-l)、编译器优化选项 (-O2) 等等。

注意,cflags 属性应该是一个列表,其中每个元素都是一个字符串类型的编译标志。在这个例子中,我添加了两个编译标志:-Ipath/to/include/dir 和 -DDEFINE_NAME=value,你可以根据自己的需求进行修改。

我想要通过go语言去实现的话,目前我找到一个三个{}的例子,但是我编译并不过。例子参考如下

func init() {
    artModuleTypes := []string{
        "art_global_defaults",
        "art_debug_defaults",
        "art_apex_test_host",
    }
    android.AddNeverAllowRules(
        android.NeverAllow().
            NotIn("art", "external/vixl").
            ModuleType(artModuleTypes...))
    android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory)
    android.RegisterModuleType("art_debug_defaults", artDebugDefaultsFactory)
    // TODO: This makes the module disable itself for host if HOST_PREFER_32_BIT is
    // set. We need this because the multilib types of binaries listed in the apex
    // rule must match the declared type. This is normally not difficult but HOST_PREFER_32_BIT
    // changes this to 'prefer32' on all host binaries. Since HOST_PREFER_32_BIT is
    // only used for testing we can just disable the module.
    // See b/120617876 for more information.
    android.RegisterModuleType("art_apex_test_host", artHostTestApexBundleFactory)
}

func artGlobalDefaultsFactory() android.Module {
    module := artDefaultsFactory()
    android.AddLoadHook(module, addImplicitFlags)
    android.AddLoadHook(module, globalDefaults)
    return module
}

func artDefaultsFactory() android.Module {
    c := &codegenProperties{}
    module := cc.DefaultsFactory(c)
    android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, staticAndSharedLibrary) })
    return module
}

// Hook that adds flags that are implicit for all cc_art_* modules.
func addImplicitFlags(ctx android.LoadHookContext) {
    type props struct {
        Target struct {
            Android struct {
                Cflags []string
            }
        }
    }
    p := &props{}
    if ctx.Config().IsEnvTrue("ART_TARGET_LINUX") {
        p.Target.Android.Cflags = []string{"-DART_TARGET", "-DART_TARGET_LINUX"}
    } else {
        p.Target.Android.Cflags = []string{"-DART_TARGET", "-DART_TARGET_ANDROID"}
    }
    ctx.AppendProperties(p)
}

func globalDefaults(ctx android.LoadHookContext) {
    type props struct {
        Target struct {
            Android struct {
                Cflags []string
            }
            Host struct {
                Cflags []string
            }
        }
        Cflags   []string
        Asflags  []string
        Sanitize struct {
            Recover []string
        }
    }
    p := &props{}
    p.Cflags, p.Asflags = globalFlags(ctx)
    p.Target.Android.Cflags = deviceFlags(ctx)
    p.Target.Host.Cflags = hostFlags(ctx)
    if ctx.Config().IsEnvTrue("ART_DEX_FILE_ACCESS_TRACKING") {
        p.Cflags = append(p.Cflags, "-DART_DEX_FILE_ACCESS_TRACKING")
        p.Sanitize.Recover = []string{
            "address",
        }
    }
    ctx.AppendProperties(p)
}

参考GPT和自己的思路,在 Android.bp 中使用 Go 语言添加条件变量进行动态添加,需要使用 Soong 构建系统提供的相关 API。在 art_module_java_defaults 中添加一个名为 source_build 的 Soong 配置变量,然后在其中定义一个名为 bar 的变量,然后可以在 bar 变量中设置需要的 CFLAGS。示例代码如下:

package default

import (
    "android/soong/android"
    "android/soong/cc"
)

func artModuleDefaults(ctx android.LoadHookContext) {
    type props struct {
        SourceBuild struct {
            Bar struct {
                Cflags []string
            }
        }
    }

    p := &props{}
    p.SourceBuild.Bar.Cflags = []string{"-DFOO"}

    if ctx.Config().SourceBuild() {
        p.Enabled = true
    }

    ctx.AppendProperties(p)
}

func init() {
    android.RegisterModuleType("art_module_java_defaults", artModuleDefaults)
}

上面的示例代码定义了一个名为 art_module_java_defaults 的模块类型,并注册到 Soong 中。然后在 artModuleDefaults 中定义了一个 props 结构体,其中添加了一个 SourceBuild 变量,并在其中定义了一个名为 bar 的变量,可以设置需要的 CFLAGS。最后,如果 SourceBuild 变量为 true,则将 Enabled 属性设置为 true,并将 props 变量追加到 LoadHookContext 上下文中。这样就可以在 Android.bp 中使用 art_module_java_defaults 模块类型,并根据 SourceBuild 变量的值设置相应的 CFLAGS。

该回答引用GPTᴼᴾᴱᴺᴬᴵ
在 Android.bp 文件中,可以使用 android.ModuleBaseMixin 来添加属性和方法到模块定义中。以下是一个使用条件变量添加 cflags 属性的示例:

package mymodule

import (
    "android/soong/android"
    "github.com/google/blueprint/proptools"
)

func init() {
    android.RegisterModuleType("mymodule_defaults", defaultsFactory)
}

func defaultsFactory() android.Module {
    module := android.DefaultsFactory()
    android.AddLoadHook(module, defaults)
    return module
}

func defaults(ctx android.LoadHookContext) {
    type props struct {
        MyFlag []string
        Cflags []string
    }

    p := &props{}

    if ctx.Config().IsEnvTrue("MY_FLAG_ENABLED") {
        p.MyFlag = []string{"-DENABLE_MY_FLAG"}
        p.Cflags = append(p.Cflags, "-DMY_FLAG_ENABLED")
    }

    ctx.AppendProperties(p)
}


在上面的示例中,我们注册了一个名为 mymodule_defaults 的模块类型,使用 android.AddLoadHook 函数向 defaults 函数中添加一个条件变量来添加 MyFlag 和 Cflags 属性。在 defaults 函数中,我们检查了一个名为 MY_FLAG_ENABLED 的环境变量,如果其值为 true,则向 MyFlag 添加 -DENABLE_MY_FLAG,向 Cflags 添加 -DMY_FLAG_ENABLED。在此示例中,我们将条件变量的值直接硬编码在函数中,您可以根据需要更改此行为。

这里https://www.baidu.com/link?url=Vk4-_Toqja24Mjx-__mfk8ltomZlyG3pAAFVG0ynt_8rc1zLx7nSst2uF4gLowbcmMZpUPJUB4iThh0mLVItQK&wd=&eqid=db425c08001dcc0a00000002640036a4

在android.bp文件中,可以通过 ctx.ModuleName() 获取当前模块的名称,然后再通过 ctx.ModuleType() 获取当前模块的类型。这样就可以动态的添加属性了。

go_module {
    name: "example",
}

go_module_defaults {
    name: "example_defaults",
    baz: {
        name: "default_baz",
    },
}

go_library {
    name: "example_lib",
    defaults: ["example_defaults"],
    bar: {
        name: "bar1",
    },
}

go_library {
    name: "example_lib2",
    defaults: ["example_defaults"],
}

func exampleDefaultsFactory() android.Module {
    module := d.DefaultsFactory()
    android.AddLoadHook(module, exampleDefaults)
    return module
}

type bazProperties struct {
    Name string
}

type barProperties struct {
    Name string
}

type exampleLibraryProperties struct {
    Baz bazProperties
    Bar []barProperties
}

func exampleDefaults(ctx android.LoadHookContext) {
    if m, ok := ctx.Module().(*go_library); ok {
        if m.Name() != "example_lib" {
            return
        }

        props := m.baseCompiler.Properties
        exampleProps := props.(*exampleLibraryProperties)

        // Add a new bar.
        exampleProps.Bar = append(exampleProps.Bar, barProperties{
            Name: "bar2",
        })

        // Override baz.
        exampleProps.Baz = bazProperties{
            Name: "new_baz",
        }
    }
}

func init() {
    android.RegisterModuleType("example", exampleModuleFactory)
    android.RegisterModuleType("example_defaults", exampleDefaultsFactory)
}


在上面的例子中,我们首先定义了一个 go_module 模块,然后定义了一个 go_module_defaults 模块,其中包含一个 baz 属性,一个 go_library 模块,它默认包含了 example_defaults。在 exampleDefaults 函数中,我们通过 ctx.Module().(*go_library) 获取当前模块的类型,然后判断模块名称是否为 "example_lib",如果不是则直接返回,如果是则动态的添加属性。

在Android.bp文件中,可以使用Go语言编写函数来添加条件变量和cflags,示例代码如下:

go
Copy code
package android
func foo(ctx android.LoadHookContext) {
    // 添加条件变量
    ctx.AddVariationDependencies([]blueprint.Variation{
        {Mutator: "arch", Variation: "arm"},
    }, "my_module_arm")
}
func bar(ctx android.ModuleContext) {
    // 获取条件变量
    if ctx.Config().HasVariation("my_module_arm") {
        // 添加cflags
        ctx.StrictRawCflags("-DUSE_ARM")
    }
}
func RegisterModuleTypes(ctx android.RegistrationContext) {
    ctx.RegisterModuleType("my_module", func() android.Module {
        module := new(android.ModuleBase)
        module.AddProperties(&myModuleProperties{})
        return module.Init()
    })
}
type myModuleProperties struct {
    Srcs []string
}
func (p *myModuleProperties) GenerateAndroidBuildActions(ctx android.ModuleContext) {
    // 调用foo函数
    foo(ctx)
    // 调用bar函数
    bar(ctx)
}


在上述代码中,我们定义了一个名为foo的函数,用于添加条件变量my_module_arm。然后,在bar函数中,我们检查是否存在条件变量my_module_arm,如果存在,则添加-DUSE_ARM cflags。最后,在myModuleProperties中的GenerateAndroidBuildActions函数中,我们调用了foo和bar函数,来实现动态添加cflags的目的。
需要注意的是,如果要在Android.bp文件中使用Go语言编写函数,需要在文件开头添加package android语句,并且需要在Android.bp文件中通过调用RegisterModuleTypes函数来注册Go语言编写的模块类型。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
要在Android.bp中添加条件变量并设置属性,可以使用android.ModuleBaseAddProperties方法。在定义模块类型的init函数中,可以使用该方法来添加属性到属性集合中。

以下是一个例子,使用go语言动态添加cflags到art_module_java_defaults中

package art

import (
   "android/soong/android"
   "android/soong/cc"
)

func artDefaultsFactory() (android.Module) {
   module := cc.DefaultsFactory()
   android.AddLoadHook(module.(cc.ModuleBase), artDefaults)
   return module
}

func artDefaults(ctx android.LoadHookContext) {
   type props struct {
      Target struct {
         Android struct {
            Cflags []string
         }
         Host struct {
            Enabled *bool
         }
      }
   }
   p := &props{}
   p.Target.Android.Cflags = []string{"-Dmy_flag"}

   if ctx.Config().IsEnvTrue("DISABLE_ART_DEVICE_BUILDS") {
      p.Target.Host.Enabled = proptools.BoolPtr(false)
   }

   ctx.AppendProperties(p)
}

func init() {
   android.RegisterModuleType("art_defaults", artDefaultsFactory)
}

在这个例子中,我们定义了一个art_defaults模块类型,使用AddLoadHook方法将一个Hook函数artDefaults注册到模块的加载钩子中。加载钩子用于在模块属性加载之前对模块进行自定义操作。AddLoadHook方法需要传入一个实现了ModuleBase接口的模块,因此我们需要将默认的cc模块类型转换成cc.ModuleBase类型。 Hook函数中,我们创建了一个props结构体,它包含一个子属性集合Target,该属性集合包含了AndroidHost两个属性。我们将-Dmy_flag添加到Android.Cflags中,并且使用环境变量DISABLE_ART_DEVICE_BUILDS来禁用Host属性。最后我们调用了ctx.AppendProperties方法将props属性集合附加到模块中,这个方法会将属性添加或者覆盖到原有的属性中。

然后你可以在art_module_java_defaults中加入对art_defaults模块类型的依赖,如下:

art_defaults {
   name: "my_art_defaults",
}

art_module_java_defaults {
   name: "art_module_source_build_java_defaults",
   defaults_visibility: [
        "//art:__subpackages__",
        "//libcore:__subpackages__",
        "//libnativehelper:__subpackages__",
    ],
   enabled: false,
   cflags: [
       "-Dmy_flag2",
   ],
   srcs: [
       "my_source_code.cpp",
   ],
   required: ["my_art_defaults"],
}

art_module_java_defaults的属性中,我们添加了required属性来声明它需要哪些模块来进行构建。在这个例子中,我们需要art_defaults模块来添加Android.Cflags属性。同时我们还开启了默认的-Dmy_flag2选项和添加了一个源文件my_source_code.cpp
如果我的回答解决了您的问题,请采纳!