Generate classpaths.proto config for *CLASSPATH variables.

Instead of embedding "raw" values from PRODUCT_*_CLASSPATH variables
into /etc/classpath, encode them into classpaths.proto binary format.

Existing platform_bootclasspath{} module is used to generate the whole
monolithic config to begin with. Later, the config will be split
among individual bootclasspath_fragment and
systemserverclasspath_fragment modules.

Bug: 180105615
Test: m && launch_cvd
Change-Id: Ia66f521f8976ff78a62ecf91131d26db21064de7
This commit is contained in:
Artur Satayev
2021-04-07 15:17:14 +01:00
parent 21fb92d7f6
commit 97259dc625
4 changed files with 188 additions and 17 deletions

View File

@@ -17,6 +17,9 @@
package java
import (
"fmt"
"strings"
"android/soong/android"
)
@@ -47,21 +50,102 @@ type classpathFragmentProperties struct {
type classpathFragment interface {
android.Module
classpathFragmentBase() *classpathFragmentBase
classpathFragmentBase() *ClasspathFragmentBase
}
// classpathFragmentBase is meant to be embedded in any module types that implement classpathFragment;
// ClasspathFragmentBase is meant to be embedded in any module types that implement classpathFragment;
// such modules are expected to call initClasspathFragment().
type classpathFragmentBase struct {
type ClasspathFragmentBase struct {
properties classpathFragmentProperties
classpathType classpathType
outputFilepath android.OutputPath
installDirPath android.InstallPath
}
// Initializes classpathFragmentBase struct. Must be called by all modules that include classpathFragmentBase.
func (c *ClasspathFragmentBase) classpathFragmentBase() *ClasspathFragmentBase {
return c
}
// Initializes ClasspathFragmentBase struct. Must be called by all modules that include ClasspathFragmentBase.
func initClasspathFragment(c classpathFragment) {
base := c.classpathFragmentBase()
c.AddProperties(&base.properties)
}
// Matches definition of Jar in packages/modules/SdkExtensions/proto/classpaths.proto
type classpathJar struct {
path string
classpath classpathType
// TODO(satayev): propagate min/max sdk versions for the jars
minSdkVersion int32
maxSdkVersion int32
}
func (c *ClasspathFragmentBase) generateAndroidBuildActions(ctx android.ModuleContext) {
outputFilename := ctx.ModuleName() + ".pb"
c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
var jars []classpathJar
jars = appendClasspathJar(jars, BOOTCLASSPATH, defaultBootclasspath(ctx)...)
jars = appendClasspathJar(jars, DEX2OATBOOTCLASSPATH, defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps...)
jars = appendClasspathJar(jars, SYSTEMSERVERCLASSPATH, systemServerClasspath(ctx)...)
generatedJson := android.PathForModuleOut(ctx, outputFilename+".json")
writeClasspathsJson(ctx, generatedJson, jars)
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
BuiltTool("conv_classpaths_proto").
Flag("encode").
Flag("--format=json").
FlagWithInput("--input=", generatedJson).
FlagWithOutput("--output=", c.outputFilepath)
rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String())
}
func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
var content strings.Builder
fmt.Fprintf(&content, "{\n")
fmt.Fprintf(&content, "\"jars\": [\n")
for idx, jar := range jars {
fmt.Fprintf(&content, "{\n")
fmt.Fprintf(&content, "\"relativePath\": \"%s\",\n", jar.path)
fmt.Fprintf(&content, "\"classpath\": \"%s\"\n", jar.classpath)
if idx < len(jars)-1 {
fmt.Fprintf(&content, "},\n")
} else {
fmt.Fprintf(&content, "}\n")
}
}
fmt.Fprintf(&content, "]\n")
fmt.Fprintf(&content, "}\n")
android.WriteFileRule(ctx, output, content.String())
}
func appendClasspathJar(slice []classpathJar, classpathType classpathType, paths ...string) (result []classpathJar) {
result = append(result, slice...)
for _, path := range paths {
result = append(result, classpathJar{
path: path,
classpath: classpathType,
})
}
return
}
func (c *ClasspathFragmentBase) getAndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "ETC",
OutputFile: android.OptionalPathForPath(c.outputFilepath),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_PATH", c.installDirPath.ToMakePath().String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", c.outputFilepath.Base())
},
},
}}
}