Merge changes I8e8e8b01,Ifb1f54d5,I9986e64f

* changes:
  Add systemserverclasspath_fragments property to apex.
  Add "contents" property to systemserverclasspath_fragment.
  Move classpaths.proto related info into a separate provider.
This commit is contained in:
satayev
2021-05-17 22:40:08 +00:00
committed by Gerrit Code Review
7 changed files with 206 additions and 42 deletions

View File

@@ -32,6 +32,7 @@ bootstrap_go_package {
"apex_test.go", "apex_test.go",
"bootclasspath_fragment_test.go", "bootclasspath_fragment_test.go",
"platform_bootclasspath_test.go", "platform_bootclasspath_test.go",
"systemserver_classpath_fragment_test.go",
"vndk_test.go", "vndk_test.go",
], ],
pluginFor: ["soong_build"], pluginFor: ["soong_build"],

View File

@@ -102,6 +102,9 @@ type apexBundleProperties struct {
// List of bootclasspath fragments that are embedded inside this APEX bundle. // List of bootclasspath fragments that are embedded inside this APEX bundle.
Bootclasspath_fragments []string Bootclasspath_fragments []string
// List of systemserverclasspath fragments that are embedded inside this APEX bundle.
Systemserverclasspath_fragments []string
// List of java libraries that are embedded inside this APEX bundle. // List of java libraries that are embedded inside this APEX bundle.
Java_libs []string Java_libs []string
@@ -575,6 +578,7 @@ var (
executableTag = dependencyTag{name: "executable", payload: true} executableTag = dependencyTag{name: "executable", payload: true}
fsTag = dependencyTag{name: "filesystem", payload: true} fsTag = dependencyTag{name: "filesystem", payload: true}
bcpfTag = dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true} bcpfTag = dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true}
sscpfTag = dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true}
compatConfigTag = dependencyTag{name: "compatConfig", payload: true, sourceOnly: true} compatConfigTag = dependencyTag{name: "compatConfig", payload: true, sourceOnly: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true} javaLibTag = dependencyTag{name: "javaLib", payload: true}
jniLibTag = dependencyTag{name: "jniLib", payload: true} jniLibTag = dependencyTag{name: "jniLib", payload: true}
@@ -755,6 +759,7 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
// Common-arch dependencies come next // Common-arch dependencies come next
commonVariation := ctx.Config().AndroidCommonTarget.Variations() commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...) ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...)
ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments...)
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...) ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...) ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...) ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
@@ -1715,6 +1720,15 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
filesInfo = append(filesInfo, filesToAdd...) filesInfo = append(filesInfo, filesToAdd...)
return true return true
} }
case sscpfTag:
{
if _, ok := child.(*java.SystemServerClasspathModule); !ok {
ctx.PropertyErrorf("systemserverclasspath_fragments", "%q is not a systemserverclasspath_fragment module", depName)
return false
}
filesInfo = append(filesInfo, apexClasspathFragmentProtoFile(ctx, child))
return true
}
case javaLibTag: case javaLibTag:
switch child.(type) { switch child.(type) {
case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import: case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
@@ -1941,7 +1955,16 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
default: default:
ctx.PropertyErrorf("bootclasspath_fragments", "bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child)) ctx.PropertyErrorf("bootclasspath_fragments", "bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
} }
} else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) {
// Add the contents of the systemserverclasspath fragment to the apex.
switch child.(type) {
case *java.Library, *java.SdkLibrary:
af := apexFileForJavaModule(ctx, child.(javaModule))
filesInfo = append(filesInfo, af)
return true // track transitive dependencies
default:
ctx.PropertyErrorf("systemserverclasspath_fragments", "systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
} else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok { } else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
// nothing // nothing
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() { } else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
@@ -2106,13 +2129,19 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.
} }
// Add classpaths.proto config. // Add classpaths.proto config.
classpathProtoOutput := bootclasspathFragmentInfo.ClasspathFragmentProtoOutput filesToAdd = append(filesToAdd, apexClasspathFragmentProtoFile(ctx, module))
classpathProto := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), bootclasspathFragmentInfo.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
filesToAdd = append(filesToAdd, classpathProto)
return filesToAdd return filesToAdd
} }
// apexClasspathFragmentProtoFile returns apexFile structure defining the classpath.proto config that
// the module contributes to the apex.
func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) apexFile {
fragmentInfo := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
classpathProtoOutput := fragmentInfo.ClasspathFragmentProtoOutput
return newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), fragmentInfo.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
}
// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment // apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment
// content module, i.e. a library that is part of the bootclasspath. // content module, i.e. a library that is part of the bootclasspath.
func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile { func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile {

View File

@@ -0,0 +1,78 @@
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package apex
import (
"testing"
"android/soong/android"
"android/soong/java"
)
var prepareForTestWithSystemserverclasspathFragment = android.GroupFixturePreparers(
java.PrepareForTestWithDexpreopt,
PrepareForTestWithApexBuildComponents,
)
func TestSystemserverclasspathFragmentContents(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
).RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
systemserverclasspath_fragments: [
"mysystemserverclasspathfragment",
],
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
java_library {
name: "foo",
srcs: ["b.java"],
installable: true,
apex_available: [
"myapex",
],
}
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
contents: [
"foo",
],
apex_available: [
"myapex",
],
}
`)
ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
"etc/classpaths/mysystemserverclasspathfragment.pb",
"javalib/foo.jar",
})
java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
`myapex.key`,
`mysystemserverclasspathfragment`,
})
}

View File

@@ -268,22 +268,6 @@ var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(Bootcla
// BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the // BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the
// apex contents. // apex contents.
type BootclasspathFragmentApexContentInfo struct { type BootclasspathFragmentApexContentInfo struct {
// ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module.
//
// The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir
// for more details.
ClasspathFragmentProtoOutput android.OutputPath
// ClasspathFragmentProtoInstallDir contains information about on device location for the generated classpaths.proto file.
//
// The path encodes expected sub-location within partitions, i.e. etc/classpaths/<proto-file>,
// for ClasspathFragmentProtoOutput. To get sub-location, instead of the full output / make path
// use android.InstallPath#Rel().
//
// This is only relevant for APEX modules as they perform their own installation; while regular
// system files are installed via ClasspathFragmentBase#androidMkEntries().
ClasspathFragmentProtoInstallDir android.InstallPath
// The image config, internal to this module (and the dex_bootjars singleton). // The image config, internal to this module (and the dex_bootjars singleton).
// //
// Will be nil if the BootclasspathFragmentApexContentInfo has not been provided for a specific module. That can occur // Will be nil if the BootclasspathFragmentApexContentInfo has not been provided for a specific module. That can occur
@@ -396,25 +380,19 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
// Perform hidden API processing. // Perform hidden API processing.
b.generateHiddenAPIBuildActions(ctx, contents) b.generateHiddenAPIBuildActions(ctx, contents)
// Construct the boot image info from the config.
info := BootclasspathFragmentApexContentInfo{
ClasspathFragmentProtoInstallDir: b.classpathFragmentBase().installDirPath,
ClasspathFragmentProtoOutput: b.classpathFragmentBase().outputFilepath,
imageConfig: nil,
}
if !SkipDexpreoptBootJars(ctx) { if !SkipDexpreoptBootJars(ctx) {
// Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
// GenerateSingletonBuildActions method as it cannot create it for itself. // GenerateSingletonBuildActions method as it cannot create it for itself.
dexpreopt.GetGlobalSoongConfig(ctx) dexpreopt.GetGlobalSoongConfig(ctx)
info.imageConfig = b.getImageConfig(ctx)
// Only generate the boot image if the configuration does not skip it. // Only generate the boot image if the configuration does not skip it.
b.generateBootImageBuildActions(ctx, contents) b.generateBootImageBuildActions(ctx, contents)
}
// Make it available for other modules. // Make the boot image info available for other modules
ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info) ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, BootclasspathFragmentApexContentInfo{
imageConfig: b.getImageConfig(ctx),
})
}
} }
// generateClasspathProtoBuildActions generates all required build actions for classpath.proto config // generateClasspathProtoBuildActions generates all required build actions for classpath.proto config

View File

@@ -18,6 +18,7 @@ package java
import ( import (
"fmt" "fmt"
"github.com/google/blueprint"
"strings" "strings"
"android/soong/android" "android/soong/android"
@@ -120,6 +121,12 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M
FlagWithOutput("--output=", c.outputFilepath) FlagWithOutput("--output=", c.outputFilepath)
rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String()) rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String())
classpathProtoInfo := ClasspathFragmentProtoContentInfo{
ClasspathFragmentProtoInstallDir: c.installDirPath,
ClasspathFragmentProtoOutput: c.outputFilepath,
}
ctx.SetProvider(ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
} }
func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) { func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
@@ -157,3 +164,23 @@ func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries {
}, },
}} }}
} }
var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider(ClasspathFragmentProtoContentInfo{})
type ClasspathFragmentProtoContentInfo struct {
// ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module.
//
// The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir
// for more details.
ClasspathFragmentProtoOutput android.OutputPath
// ClasspathFragmentProtoInstallDir contains information about on device location for the generated classpaths.proto file.
//
// The path encodes expected sub-location within partitions, i.e. etc/classpaths/<proto-file>,
// for ClasspathFragmentProtoOutput. To get sub-location, instead of the full output / make path
// use android.InstallPath#Rel().
//
// This is only relevant for APEX modules as they perform their own installation; while regular
// system files are installed via ClasspathFragmentBase#androidMkEntries().
ClasspathFragmentProtoInstallDir android.InstallPath
}

View File

@@ -17,6 +17,7 @@ package java
import ( import (
"android/soong/android" "android/soong/android"
"android/soong/dexpreopt" "android/soong/dexpreopt"
"github.com/google/blueprint"
) )
func init() { func init() {
@@ -66,24 +67,63 @@ func (p *platformSystemServerClasspathModule) ClasspathFragmentToConfiguredJarLi
}).(android.ConfiguredJarList) }).(android.ConfiguredJarList)
} }
type systemServerClasspathModule struct { type SystemServerClasspathModule struct {
android.ModuleBase android.ModuleBase
android.ApexModuleBase
ClasspathFragmentBase ClasspathFragmentBase
properties systemServerClasspathFragmentProperties
}
func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
return nil
}
type systemServerClasspathFragmentProperties struct {
// The contents of this systemserverclasspath_fragment, could be either java_library, or java_sdk_library.
//
// The order of this list matters as it is the order that is used in the SYSTEMSERVERCLASSPATH.
Contents []string
} }
func systemServerClasspathFactory() android.Module { func systemServerClasspathFactory() android.Module {
m := &systemServerClasspathModule{} m := &SystemServerClasspathModule{}
m.AddProperties(&m.properties)
android.InitApexModule(m)
initClasspathFragment(m, SYSTEMSERVERCLASSPATH) initClasspathFragment(m, SYSTEMSERVERCLASSPATH)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m return m
} }
func (s *systemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(s.properties.Contents) == 0 {
ctx.PropertyErrorf("contents", "empty contents are not allowed")
}
s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJarListToClasspathJars(ctx, s.ClasspathFragmentToConfiguredJarList(ctx))) s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJarListToClasspathJars(ctx, s.ClasspathFragmentToConfiguredJarList(ctx)))
} }
func (s *systemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList { func (s *SystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList {
// TODO(satayev): populate with actual content // TODO(satayev): populate with actual content
return android.EmptyConfiguredJarList() return android.EmptyConfiguredJarList()
} }
type systemServerClasspathFragmentContentDependencyTag struct {
blueprint.BaseDependencyTag
}
// The tag used for the dependency between the systemserverclasspath_fragment module and its contents.
var systemServerClasspathFragmentContentDepTag = systemServerClasspathFragmentContentDependencyTag{}
func IsSystemServerClasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool {
return tag == systemServerClasspathFragmentContentDepTag
}
func (s *SystemServerClasspathModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
module := ctx.Module()
for _, name := range s.properties.Contents {
ctx.AddDependency(module, systemServerClasspathFragmentContentDepTag, name)
}
}

View File

@@ -20,13 +20,13 @@ import (
"android/soong/android" "android/soong/android"
) )
var prepareForTestWithSystemserverClasspath = android.GroupFixturePreparers( var prepareForTestWithSystemServerClasspath = android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules, PrepareForTestWithJavaDefaultModules,
) )
func TestSystemserverClasspathVariant(t *testing.T) { func TestPlatformSystemserverClasspathVariant(t *testing.T) {
result := android.GroupFixturePreparers( result := android.GroupFixturePreparers(
prepareForTestWithSystemserverClasspath, prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(` android.FixtureWithRootAndroidBp(`
platform_systemserverclasspath { platform_systemserverclasspath {
name: "platform-systemserverclasspath", name: "platform-systemserverclasspath",
@@ -38,9 +38,9 @@ func TestSystemserverClasspathVariant(t *testing.T) {
android.AssertIntEquals(t, "expect 1 variant", 1, len(variants)) android.AssertIntEquals(t, "expect 1 variant", 1, len(variants))
} }
func TestSystemserverClasspath_ClasspathFragmentPaths(t *testing.T) { func TestPlatformSystemserverClasspath_ClasspathFragmentPaths(t *testing.T) {
result := android.GroupFixturePreparers( result := android.GroupFixturePreparers(
prepareForTestWithSystemserverClasspath, prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(` android.FixtureWithRootAndroidBp(`
platform_systemserverclasspath { platform_systemserverclasspath {
name: "platform-systemserverclasspath", name: "platform-systemserverclasspath",
@@ -53,9 +53,9 @@ func TestSystemserverClasspath_ClasspathFragmentPaths(t *testing.T) {
android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath) android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath)
} }
func TestSystemserverClasspathModule_AndroidMkEntries(t *testing.T) { func TestPlatformSystemserverClasspathModule_AndroidMkEntries(t *testing.T) {
preparer := android.GroupFixturePreparers( preparer := android.GroupFixturePreparers(
prepareForTestWithSystemserverClasspath, prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(` android.FixtureWithRootAndroidBp(`
platform_systemserverclasspath { platform_systemserverclasspath {
name: "platform-systemserverclasspath", name: "platform-systemserverclasspath",
@@ -95,3 +95,14 @@ func TestSystemserverClasspathModule_AndroidMkEntries(t *testing.T) {
} }
}) })
} }
func TestSystemserverclasspathFragmentWithoutContents(t *testing.T) {
prepareForTestWithSystemServerClasspath.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
`\Qempty contents are not allowed\E`)).
RunTestWithBp(t, `
systemserverclasspath_fragment {
name: "systemserverclasspath-fragment",
}
`)
}