package codegen import ( "fmt" "strconv" "android/soong/android" "android/soong/rust" "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) type rustDeclarationsTagType struct { blueprint.BaseDependencyTag } var rustDeclarationsTag = rustDeclarationsTagType{} type RustAconfigLibraryProperties struct { // name of the aconfig_declarations module to generate a library for Aconfig_declarations string // default mode is "production", the other accepted modes are: // "test": to generate test mode version of the library // "exported": to generate exported mode version of the library // "force-read-only": to generate force-read-only mode version of the library // an error will be thrown if the mode is not supported Mode *string } type aconfigDecorator struct { *rust.BaseSourceProvider Properties RustAconfigLibraryProperties } func NewRustAconfigLibrary(hod android.HostOrDeviceSupported) (*rust.Module, *aconfigDecorator) { aconfig := &aconfigDecorator{ BaseSourceProvider: rust.NewSourceProvider(), Properties: RustAconfigLibraryProperties{}, } module := rust.NewSourceProviderModule(android.HostAndDeviceSupported, aconfig, false, false) return module, aconfig } // rust_aconfig_library generates aconfig rust code from the provided aconfig declaration. This module type will // create library variants that can be used as a crate dependency by adding it to the rlibs, dylibs, and rustlibs // properties of other modules. func RustAconfigLibraryFactory() android.Module { module, _ := NewRustAconfigLibrary(android.HostAndDeviceSupported) return module.Init() } func (a *aconfigDecorator) SourceProviderProps() []interface{} { return append(a.BaseSourceProvider.SourceProviderProps(), &a.Properties) } func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path { generatedDir := android.PathForModuleGen(ctx) generatedSource := android.PathForModuleGen(ctx, "src", "lib.rs") declarationsModules := ctx.GetDirectDepsWithTag(rustDeclarationsTag) if len(declarationsModules) != 1 { panic(fmt.Errorf("Exactly one aconfig_declarations property required")) } declarations, _ := android.OtherModuleProvider(ctx, declarationsModules[0], android.AconfigDeclarationsProviderKey) mode := proptools.StringDefault(a.Properties.Mode, "production") if !isModeSupported(mode) { ctx.PropertyErrorf("mode", "%q is not a supported mode", mode) } ctx.Build(pctx, android.BuildParams{ Rule: rustRule, Input: declarations.IntermediateCacheOutputPath, Outputs: []android.WritablePath{ generatedSource, }, Description: "rust_aconfig_library", Args: map[string]string{ "gendir": generatedDir.String(), "mode": mode, "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()), }, }) a.BaseSourceProvider.OutputFiles = android.Paths{generatedSource} android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{ ModeInfos: map[string]android.ModeInfo{ ctx.ModuleName(): { Container: declarations.Container, Mode: mode, }}, }) return generatedSource } func (a *aconfigDecorator) SourceProviderDeps(ctx rust.DepsContext, deps rust.Deps) rust.Deps { deps = a.BaseSourceProvider.SourceProviderDeps(ctx, deps) deps.Rustlibs = append(deps.Rustlibs, "libaconfig_storage_read_api") deps.Rustlibs = append(deps.Rustlibs, "libflags_rust") deps.Rustlibs = append(deps.Rustlibs, "liblazy_static") deps.Rustlibs = append(deps.Rustlibs, "liblogger") deps.Rustlibs = append(deps.Rustlibs, "liblog_rust") ctx.AddDependency(ctx.Module(), rustDeclarationsTag, a.Properties.Aconfig_declarations) return deps }