Merge "Integrate Rust-specific System Properties into rules generation." into main

This commit is contained in:
Andrew Walbran 2024-02-05 10:50:59 +00:00 committed by Gerrit Code Review
commit 4b8e361b4c
4 changed files with 151 additions and 12 deletions

View file

@ -75,6 +75,7 @@ func GatherRequiredDepsForTest() string {
apex_available: ["//apex_available:platform", "//apex_available:anyapex"], apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
min_sdk_version: "29", min_sdk_version: "29",
vendor_available: true, vendor_available: true,
host_supported: true,
recovery_available: true, recovery_available: true,
llndk: { llndk: {
symbol_file: "liblog.map.txt", symbol_file: "liblog.map.txt",

View file

@ -11,6 +11,7 @@ bootstrap_go_package {
"soong-android", "soong-android",
"soong-cc", "soong-cc",
"soong-java", "soong-java",
"soong-rust",
], ],
srcs: [ srcs: [
"sysprop_library.go", "sysprop_library.go",

View file

@ -21,6 +21,7 @@ import (
"io" "io"
"os" "os"
"path" "path"
"strings"
"sync" "sync"
"github.com/google/blueprint" "github.com/google/blueprint"
@ -29,6 +30,7 @@ import (
"android/soong/android" "android/soong/android"
"android/soong/cc" "android/soong/cc"
"android/soong/java" "android/soong/java"
"android/soong/rust"
) )
type dependencyTag struct { type dependencyTag struct {
@ -51,7 +53,16 @@ type syspropJavaGenRule struct {
genSrcjars android.Paths genSrcjars android.Paths
} }
type syspropRustGenRule struct {
android.ModuleBase
properties syspropGenProperties
genSrcs android.Paths
}
var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil) var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil)
var _ android.OutputFileProducer = (*syspropRustGenRule)(nil)
var ( var (
syspropJava = pctx.AndroidStaticRule("syspropJava", syspropJava = pctx.AndroidStaticRule("syspropJava",
@ -64,11 +75,20 @@ var (
"$soongZipCmd", "$soongZipCmd",
}, },
}, "scope") }, "scope")
syspropRust = pctx.AndroidStaticRule("syspropRust",
blueprint.RuleParams{
Command: `rm -rf $out_dir && mkdir -p $out_dir && ` +
`$syspropRustCmd --scope $scope --rust-output-dir $out_dir $in`,
CommandDeps: []string{
"$syspropRustCmd",
},
}, "scope", "out_dir")
) )
func init() { func init() {
pctx.HostBinToolVariable("soongZipCmd", "soong_zip") pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java") pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
pctx.HostBinToolVariable("syspropRustCmd", "sysprop_rust")
} }
// syspropJavaGenRule module generates srcjar containing generated java APIs. // syspropJavaGenRule module generates srcjar containing generated java APIs.
@ -122,6 +142,56 @@ func syspropJavaGenFactory() android.Module {
return g return g
} }
// syspropRustGenRule module generates rust source files containing generated rust APIs.
// It also depends on check api rule, so api check has to pass to use sysprop_library.
func (g *syspropRustGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var checkApiFileTimeStamp android.WritablePath
ctx.VisitDirectDeps(func(dep android.Module) {
if m, ok := dep.(*syspropLibrary); ok {
checkApiFileTimeStamp = m.checkApiFileTimeStamp
}
})
for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
syspropDir := strings.TrimSuffix(syspropFile.String(), syspropFile.Ext())
outputDir := android.PathForModuleGen(ctx, syspropDir, "src")
libPath := android.PathForModuleGen(ctx, syspropDir, "src", "lib.rs")
parsersPath := android.PathForModuleGen(ctx, syspropDir, "src", "gen_parsers_and_formatters.rs")
ctx.Build(pctx, android.BuildParams{
Rule: syspropRust,
Description: "sysprop_rust " + syspropFile.Rel(),
Outputs: android.WritablePaths{libPath, parsersPath},
Input: syspropFile,
Implicit: checkApiFileTimeStamp,
Args: map[string]string{
"scope": g.properties.Scope,
"out_dir": outputDir.String(),
},
})
g.genSrcs = append(g.genSrcs, libPath, parsersPath)
}
}
func (g *syspropRustGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add a dependency from the stubs to sysprop library so that the generator rule can depend on
// the check API rule of the sysprop library.
ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
}
func (g *syspropRustGenRule) OutputFiles(_ string) (android.Paths, error) {
return g.genSrcs, nil
}
func syspropRustGenFactory() android.Module {
g := &syspropRustGenRule{}
g.AddProperties(&g.properties)
android.InitAndroidModule(g)
return g
}
type syspropLibrary struct { type syspropLibrary struct {
android.ModuleBase android.ModuleBase
android.ApexModuleBase android.ApexModuleBase
@ -180,6 +250,12 @@ type syspropLibraryProperties struct {
// Forwarded to java_library.min_sdk_version // Forwarded to java_library.min_sdk_version
Min_sdk_version *string Min_sdk_version *string
} }
Rust struct {
// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
// Forwarded to rust_library.min_sdk_version
Min_sdk_version *string
}
} }
var ( var (
@ -233,6 +309,21 @@ func (m *syspropLibrary) javaGenPublicStubName() string {
return m.BaseModuleName() + "_java_gen_public" return m.BaseModuleName() + "_java_gen_public"
} }
func (m *syspropLibrary) rustGenModuleName() string {
return m.rustCrateName() + "_rust_gen"
}
func (m *syspropLibrary) rustGenStubName() string {
return "lib" + m.rustCrateName() + "_rust"
}
func (m *syspropLibrary) rustCrateName() string {
moduleName := strings.ToLower(m.BaseModuleName())
moduleName = strings.ReplaceAll(moduleName, "-", "_")
moduleName = strings.ReplaceAll(moduleName, ".", "_")
return moduleName
}
func (m *syspropLibrary) BaseModuleName() string { func (m *syspropLibrary) BaseModuleName() string {
return m.ModuleBase.Name() return m.ModuleBase.Name()
} }
@ -436,6 +527,18 @@ type javaLibraryProperties struct {
Min_sdk_version *string Min_sdk_version *string
} }
type rustLibraryProperties struct {
Name *string
Srcs []string
Installable *bool
Crate_name string
Rustlibs []string
Vendor_available *bool
Product_available *bool
Apex_available []string
Min_sdk_version *string
}
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) { func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
if len(m.properties.Srcs) == 0 { if len(m.properties.Srcs) == 0 {
ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs") ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
@ -564,6 +667,28 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
}) })
} }
// Generate a Rust implementation library.
ctx.CreateModule(syspropRustGenFactory, &syspropGenProperties{
Srcs: m.properties.Srcs,
Scope: scope,
Name: proptools.StringPtr(m.rustGenModuleName()),
Check_api: proptools.StringPtr(ctx.ModuleName()),
})
rustProps := rustLibraryProperties{
Name: proptools.StringPtr(m.rustGenStubName()),
Srcs: []string{":" + m.rustGenModuleName()},
Installable: proptools.BoolPtr(false),
Crate_name: m.rustCrateName(),
Rustlibs: []string{
"librustutils",
},
Vendor_available: m.properties.Vendor_available,
Product_available: m.properties.Product_available,
Apex_available: m.ApexProperties.Apex_available,
Min_sdk_version: proptools.StringPtr("29"),
}
ctx.CreateModule(rust.RustLibraryFactory, &rustProps)
// syspropLibraries will be used by property_contexts to check types. // syspropLibraries will be used by property_contexts to check types.
// Record absolute paths of sysprop_library to prevent soong_namespace problem. // Record absolute paths of sysprop_library to prevent soong_namespace problem.
if m.ExportedToMake() { if m.ExportedToMake() {

View file

@ -22,6 +22,7 @@ import (
"android/soong/android" "android/soong/android"
"android/soong/cc" "android/soong/cc"
"android/soong/java" "android/soong/java"
"android/soong/rust"
"github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools"
) )
@ -46,18 +47,6 @@ func test(t *testing.T, bp string) *android.TestResult {
recovery_available: true, recovery_available: true,
} }
cc_library {
name: "liblog",
no_libcrt: true,
nocrt: true,
system_shared_libs: [],
recovery_available: true,
host_supported: true,
llndk: {
symbol_file: "liblog.map.txt",
}
}
java_library { java_library {
name: "sysprop-library-stub-platform", name: "sysprop-library-stub-platform",
sdk_version: "core_current", sdk_version: "core_current",
@ -74,6 +63,15 @@ func test(t *testing.T, bp string) *android.TestResult {
product_specific: true, product_specific: true,
sdk_version: "core_current", sdk_version: "core_current",
} }
rust_library {
name: "librustutils",
crate_name: "rustutils",
srcs: ["librustutils/lib.rs"],
product_available: true,
vendor_available: true,
min_sdk_version: "29",
}
` `
mockFS := android.MockFS{ mockFS := android.MockFS{
@ -115,11 +113,14 @@ func test(t *testing.T, bp string) *android.TestResult {
"android/sysprop/PlatformProperties.sysprop": nil, "android/sysprop/PlatformProperties.sysprop": nil,
"com/android/VendorProperties.sysprop": nil, "com/android/VendorProperties.sysprop": nil,
"com/android2/OdmProperties.sysprop": nil, "com/android2/OdmProperties.sysprop": nil,
"librustutils/lib.rs": nil,
} }
result := android.GroupFixturePreparers( result := android.GroupFixturePreparers(
cc.PrepareForTestWithCcDefaultModules, cc.PrepareForTestWithCcDefaultModules,
java.PrepareForTestWithJavaDefaultModules, java.PrepareForTestWithJavaDefaultModules,
rust.PrepareForTestWithRustDefaultModules,
PrepareForTestWithSyspropBuildComponents, PrepareForTestWithSyspropBuildComponents,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceSystemSdkVersions = []string{"28"} variables.DeviceSystemSdkVersions = []string{"28"}
@ -356,6 +357,10 @@ func TestApexAvailabilityIsForwarded(t *testing.T) {
javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library) javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
propFromJava := javaModule.ApexProperties.Apex_available propFromJava := javaModule.ApexProperties.Apex_available
android.AssertDeepEquals(t, "apex_available forwarding to java module", expected, propFromJava) android.AssertDeepEquals(t, "apex_available forwarding to java module", expected, propFromJava)
rustModule := result.ModuleForTests("libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
propFromRust := rustModule.ApexProperties.Apex_available
android.AssertDeepEquals(t, "apex_available forwarding to rust module", expected, propFromRust)
} }
func TestMinSdkVersionIsForwarded(t *testing.T) { func TestMinSdkVersionIsForwarded(t *testing.T) {
@ -371,6 +376,9 @@ func TestMinSdkVersionIsForwarded(t *testing.T) {
java: { java: {
min_sdk_version: "30", min_sdk_version: "30",
}, },
rust: {
min_sdk_version: "29",
}
} }
`) `)
@ -381,4 +389,8 @@ func TestMinSdkVersionIsForwarded(t *testing.T) {
javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library) javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
propFromJava := javaModule.MinSdkVersionString() propFromJava := javaModule.MinSdkVersionString()
android.AssertStringEquals(t, "min_sdk_version forwarding to java module", "30", propFromJava) android.AssertStringEquals(t, "min_sdk_version forwarding to java module", "30", propFromJava)
rustModule := result.ModuleForTests("libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
propFromRust := proptools.String(rustModule.Properties.Min_sdk_version)
android.AssertStringEquals(t, "min_sdk_version forwarding to rust module", "29", propFromRust)
} }