Merge "Implement rust_aconfig_library" into main

This commit is contained in:
Dennis Shen
2023-08-10 17:10:29 +00:00
committed by Gerrit Code Review
5 changed files with 163 additions and 1 deletions

View File

@@ -14,6 +14,7 @@ bootstrap_go_package {
"soong-bazel",
"soong-android",
"soong-java",
"soong-rust",
],
srcs: [
"aconfig_declarations.go",
@@ -24,6 +25,7 @@ bootstrap_go_package {
"init.go",
"java_aconfig_library.go",
"testing.go",
"rust_aconfig_library.go",
],
testSrcs: [
"aconfig_declarations_test.go",

View File

@@ -17,8 +17,9 @@ package aconfig
import (
"android/soong/android"
"fmt"
"github.com/google/blueprint"
"strings"
"github.com/google/blueprint"
)
type DeclarationsModule struct {

View File

@@ -16,6 +16,7 @@ package aconfig
import (
"android/soong/android"
"github.com/google/blueprint"
)
@@ -70,6 +71,20 @@ var (
},
}, "gendir")
rustRule = pctx.AndroidStaticRule("rust_aconfig_library",
blueprint.RuleParams{
Command: `rm -rf ${gendir}` +
` && mkdir -p ${gendir}` +
` && ${aconfig} create-rust-lib` +
` --mode ${mode}` +
` --cache ${in}` +
` --out ${gendir}`,
CommandDeps: []string{
"$aconfig",
"$soong_zip",
},
}, "gendir", "mode")
// For all_aconfig_declarations
allDeclarationsRule = pctx.AndroidStaticRule("all_aconfig_declarations_dump",
blueprint.RuleParams{
@@ -92,5 +107,6 @@ func registerBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory)
ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
ctx.RegisterModuleType("rust_aconfig_library", RustAconfigLibraryFactory)
ctx.RegisterParallelSingletonType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
}

View File

@@ -0,0 +1,83 @@
package aconfig
import (
"android/soong/android"
"android/soong/rust"
"fmt"
"github.com/google/blueprint"
)
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
}
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 := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
ctx.Build(pctx, android.BuildParams{
Rule: rustRule,
Input: declarations.IntermediatePath,
Outputs: []android.WritablePath{
generatedSource,
},
Description: "rust_aconfig_library",
Args: map[string]string{
"gendir": generatedDir.String(),
// TODO: Add test mode
"mode": "production",
},
})
a.BaseSourceProvider.OutputFiles = android.Paths{generatedSource}
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, "libflags_rust")
ctx.AddDependency(ctx.Module(), rustDeclarationsTag, a.Properties.Aconfig_declarations)
return deps
}

View File

@@ -0,0 +1,60 @@
package aconfig
import (
"android/soong/android"
"android/soong/rust"
"fmt"
"testing"
)
func TestRustAconfigLibrary(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithAconfigBuildComponents,
rust.PrepareForTestWithRustIncludeVndk,
android.PrepareForTestWithArchMutator,
android.PrepareForTestWithDefaults,
android.PrepareForTestWithPrebuilts,
).
ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
RunTestWithBp(t, fmt.Sprintf(`
rust_library {
name: "libflags_rust", // test mock
crate_name: "flags_rust",
srcs: ["lib.rs"],
}
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
srcs: ["foo.aconfig"],
}
rust_aconfig_library {
name: "libmy_rust_aconfig_library",
crate_name: "my_rust_aconfig_library",
aconfig_declarations: "my_aconfig_declarations",
}
`))
sourceVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
rule := sourceVariant.Rule("rust_aconfig_library")
android.AssertStringEquals(t, "rule must contain production mode", rule.Args["mode"], "production")
dylibVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_dylib")
rlibRlibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_rlib-std")
rlibDylibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_dylib-std")
variants := []android.TestingModule{
dylibVariant,
rlibDylibStdVariant,
rlibRlibStdVariant,
}
for _, variant := range variants {
android.AssertStringEquals(
t,
"dylib variant builds from generated rust code",
"out/soong/.intermediates/libmy_rust_aconfig_library/android_arm64_armv8-a_source/gen/src/lib.rs",
variant.Rule("rustc").Inputs[0].RelativeToTop().String(),
)
}
}