2021-04-07 16:45:02 +02:00
|
|
|
/*
|
|
|
|
* 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 java
|
|
|
|
|
|
|
|
import (
|
2021-04-07 16:17:14 +02:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
2021-04-07 16:45:02 +02:00
|
|
|
"android/soong/android"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Build rules and utilities to generate individual packages/modules/SdkExtensions/proto/classpaths.proto
|
|
|
|
// config files based on build configuration to embed into /system and /apex on a device.
|
|
|
|
//
|
|
|
|
// See `derive_classpath` service that reads the configs at runtime and defines *CLASSPATH variables
|
|
|
|
// on the device.
|
|
|
|
|
|
|
|
type classpathType int
|
|
|
|
|
|
|
|
const (
|
|
|
|
// Matches definition in packages/modules/SdkExtensions/proto/classpaths.proto
|
|
|
|
BOOTCLASSPATH classpathType = iota
|
|
|
|
DEX2OATBOOTCLASSPATH
|
|
|
|
SYSTEMSERVERCLASSPATH
|
|
|
|
)
|
|
|
|
|
|
|
|
func (c classpathType) String() string {
|
|
|
|
return [...]string{"BOOTCLASSPATH", "DEX2OATBOOTCLASSPATH", "SYSTEMSERVERCLASSPATH"}[c]
|
|
|
|
}
|
|
|
|
|
|
|
|
type classpathFragmentProperties struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
// classpathFragment interface is implemented by a module that contributes jars to a *CLASSPATH
|
|
|
|
// variables at runtime.
|
|
|
|
type classpathFragment interface {
|
|
|
|
android.Module
|
|
|
|
|
2021-04-07 16:17:14 +02:00
|
|
|
classpathFragmentBase() *ClasspathFragmentBase
|
2021-04-07 16:45:02 +02:00
|
|
|
}
|
|
|
|
|
2021-04-07 16:17:14 +02:00
|
|
|
// ClasspathFragmentBase is meant to be embedded in any module types that implement classpathFragment;
|
2021-04-07 16:45:02 +02:00
|
|
|
// such modules are expected to call initClasspathFragment().
|
2021-04-07 16:17:14 +02:00
|
|
|
type ClasspathFragmentBase struct {
|
2021-04-07 16:45:02 +02:00
|
|
|
properties classpathFragmentProperties
|
|
|
|
|
|
|
|
outputFilepath android.OutputPath
|
2021-04-07 16:17:14 +02:00
|
|
|
installDirPath android.InstallPath
|
2021-04-07 16:45:02 +02:00
|
|
|
}
|
|
|
|
|
2021-04-07 16:17:14 +02:00
|
|
|
func (c *ClasspathFragmentBase) classpathFragmentBase() *ClasspathFragmentBase {
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initializes ClasspathFragmentBase struct. Must be called by all modules that include ClasspathFragmentBase.
|
2021-04-07 16:45:02 +02:00
|
|
|
func initClasspathFragment(c classpathFragment) {
|
|
|
|
base := c.classpathFragmentBase()
|
|
|
|
c.AddProperties(&base.properties)
|
|
|
|
}
|
2021-04-07 16:17:14 +02:00
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2021-05-06 14:21:15 +02:00
|
|
|
func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext) {
|
2021-04-07 16:17:14 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-05-06 14:21:15 +02:00
|
|
|
func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries {
|
2021-04-07 16:17:14 +02:00
|
|
|
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())
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
}
|