336 lines
10 KiB
Go
336 lines
10 KiB
Go
// Copyright 2019 Google Inc. All rights reserved.
|
|
//
|
|
// 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 (
|
|
"path/filepath"
|
|
|
|
"android/soong/android"
|
|
"github.com/google/blueprint"
|
|
|
|
"fmt"
|
|
)
|
|
|
|
func init() {
|
|
registerPlatformCompatConfigBuildComponents(android.InitRegistrationContext)
|
|
|
|
android.RegisterSdkMemberType(&compatConfigMemberType{
|
|
SdkMemberTypeBase: android.SdkMemberTypeBase{
|
|
PropertyName: "compat_configs",
|
|
SupportsSdk: true,
|
|
},
|
|
})
|
|
}
|
|
|
|
func registerPlatformCompatConfigBuildComponents(ctx android.RegistrationContext) {
|
|
ctx.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
|
|
ctx.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory)
|
|
ctx.RegisterModuleType("prebuilt_platform_compat_config", prebuiltCompatConfigFactory)
|
|
ctx.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
|
|
}
|
|
|
|
var PrepareForTestWithPlatformCompatConfig = android.FixtureRegisterWithContext(registerPlatformCompatConfigBuildComponents)
|
|
|
|
func platformCompatConfigPath(ctx android.PathContext) android.OutputPath {
|
|
return android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml")
|
|
}
|
|
|
|
type platformCompatConfigProperties struct {
|
|
Src *string `android:"path"`
|
|
}
|
|
|
|
type platformCompatConfig struct {
|
|
android.ModuleBase
|
|
android.SdkBase
|
|
|
|
properties platformCompatConfigProperties
|
|
installDirPath android.InstallPath
|
|
configFile android.OutputPath
|
|
metadataFile android.OutputPath
|
|
}
|
|
|
|
func (p *platformCompatConfig) compatConfigMetadata() android.Path {
|
|
return p.metadataFile
|
|
}
|
|
|
|
func (p *platformCompatConfig) CompatConfig() android.OutputPath {
|
|
return p.configFile
|
|
}
|
|
|
|
func (p *platformCompatConfig) SubDir() string {
|
|
return "compatconfig"
|
|
}
|
|
|
|
type platformCompatConfigMetadataProvider interface {
|
|
compatConfigMetadata() android.Path
|
|
}
|
|
|
|
type PlatformCompatConfigIntf interface {
|
|
android.Module
|
|
|
|
CompatConfig() android.OutputPath
|
|
// Sub dir under etc dir.
|
|
SubDir() string
|
|
}
|
|
|
|
var _ PlatformCompatConfigIntf = (*platformCompatConfig)(nil)
|
|
var _ platformCompatConfigMetadataProvider = (*platformCompatConfig)(nil)
|
|
|
|
func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
rule := android.NewRuleBuilder(pctx, ctx)
|
|
|
|
configFileName := p.Name() + ".xml"
|
|
metadataFileName := p.Name() + "_meta.xml"
|
|
p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath
|
|
p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath
|
|
path := android.PathForModuleSrc(ctx, String(p.properties.Src))
|
|
|
|
rule.Command().
|
|
BuiltTool("process-compat-config").
|
|
FlagWithInput("--jar ", path).
|
|
FlagWithOutput("--device-config ", p.configFile).
|
|
FlagWithOutput("--merged-config ", p.metadataFile)
|
|
|
|
p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig")
|
|
rule.Build(configFileName, "Extract compat/compat_config.xml and install it")
|
|
|
|
}
|
|
|
|
func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries {
|
|
return []android.AndroidMkEntries{android.AndroidMkEntries{
|
|
Class: "ETC",
|
|
OutputFile: android.OptionalPathForPath(p.configFile),
|
|
Include: "$(BUILD_PREBUILT)",
|
|
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
|
|
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
|
|
entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.ToMakePath().String())
|
|
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.configFile.Base())
|
|
},
|
|
},
|
|
}}
|
|
}
|
|
|
|
func PlatformCompatConfigFactory() android.Module {
|
|
module := &platformCompatConfig{}
|
|
module.AddProperties(&module.properties)
|
|
android.InitSdkAwareModule(module)
|
|
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
|
return module
|
|
}
|
|
|
|
type compatConfigMemberType struct {
|
|
android.SdkMemberTypeBase
|
|
}
|
|
|
|
func (b *compatConfigMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
|
|
mctx.AddVariationDependencies(nil, dependencyTag, names...)
|
|
}
|
|
|
|
func (b *compatConfigMemberType) IsInstance(module android.Module) bool {
|
|
_, ok := module.(*platformCompatConfig)
|
|
return ok
|
|
}
|
|
|
|
func (b *compatConfigMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
|
|
return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_platform_compat_config")
|
|
}
|
|
|
|
func (b *compatConfigMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
|
|
return &compatConfigSdkMemberProperties{}
|
|
}
|
|
|
|
type compatConfigSdkMemberProperties struct {
|
|
android.SdkMemberPropertiesBase
|
|
|
|
Metadata android.Path
|
|
}
|
|
|
|
func (b *compatConfigSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
|
|
module := variant.(*platformCompatConfig)
|
|
b.Metadata = module.metadataFile
|
|
}
|
|
|
|
func (b *compatConfigSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
|
|
builder := ctx.SnapshotBuilder()
|
|
if b.Metadata != nil {
|
|
snapshotRelativePath := filepath.Join("compat_configs", ctx.Name(), b.Metadata.Base())
|
|
builder.CopyToSnapshot(b.Metadata, snapshotRelativePath)
|
|
propertySet.AddProperty("metadata", snapshotRelativePath)
|
|
}
|
|
}
|
|
|
|
var _ android.SdkMemberType = (*compatConfigMemberType)(nil)
|
|
|
|
// A prebuilt version of the platform compat config module.
|
|
type prebuiltCompatConfigModule struct {
|
|
android.ModuleBase
|
|
android.SdkBase
|
|
prebuilt android.Prebuilt
|
|
|
|
properties prebuiltCompatConfigProperties
|
|
|
|
metadataFile android.Path
|
|
}
|
|
|
|
type prebuiltCompatConfigProperties struct {
|
|
Metadata *string `android:"path"`
|
|
}
|
|
|
|
func (module *prebuiltCompatConfigModule) Prebuilt() *android.Prebuilt {
|
|
return &module.prebuilt
|
|
}
|
|
|
|
func (module *prebuiltCompatConfigModule) Name() string {
|
|
return module.prebuilt.Name(module.ModuleBase.Name())
|
|
}
|
|
|
|
func (module *prebuiltCompatConfigModule) compatConfigMetadata() android.Path {
|
|
return module.metadataFile
|
|
}
|
|
|
|
var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil)
|
|
|
|
func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
module.metadataFile = module.prebuilt.SingleSourcePath(ctx)
|
|
}
|
|
|
|
// A prebuilt version of platform_compat_config that provides the metadata.
|
|
func prebuiltCompatConfigFactory() android.Module {
|
|
m := &prebuiltCompatConfigModule{}
|
|
m.AddProperties(&m.properties)
|
|
android.InitSingleSourcePrebuiltModule(m, &m.properties, "Metadata")
|
|
android.InitSdkAwareModule(m)
|
|
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
|
|
return m
|
|
}
|
|
|
|
// compat singleton rules
|
|
type platformCompatConfigSingleton struct {
|
|
metadata android.Path
|
|
}
|
|
|
|
// isModulePreferredByCompatConfig checks to see whether the module is preferred for use by
|
|
// platform compat config.
|
|
func isModulePreferredByCompatConfig(module android.Module) bool {
|
|
// A versioned prebuilt_platform_compat_config, i.e. foo-platform-compat-config@current should be
|
|
// ignored.
|
|
if s, ok := module.(android.SdkAware); ok {
|
|
if !s.ContainingSdk().Unversioned() {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// A prebuilt module should only be used when it is preferred.
|
|
if pi, ok := module.(android.PrebuiltInterface); ok {
|
|
if p := pi.Prebuilt(); p != nil {
|
|
return p.UsePrebuilt()
|
|
}
|
|
}
|
|
|
|
// Otherwise, a module should only be used if it has not been replaced by a prebuilt.
|
|
return !module.IsReplacedByPrebuilt()
|
|
}
|
|
|
|
func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|
|
|
var compatConfigMetadata android.Paths
|
|
|
|
ctx.VisitAllModules(func(module android.Module) {
|
|
if !module.Enabled() {
|
|
return
|
|
}
|
|
if c, ok := module.(platformCompatConfigMetadataProvider); ok {
|
|
if !isModulePreferredByCompatConfig(module) {
|
|
return
|
|
}
|
|
metadata := c.compatConfigMetadata()
|
|
compatConfigMetadata = append(compatConfigMetadata, metadata)
|
|
}
|
|
})
|
|
|
|
if compatConfigMetadata == nil {
|
|
// nothing to do.
|
|
return
|
|
}
|
|
|
|
rule := android.NewRuleBuilder(pctx, ctx)
|
|
outputPath := platformCompatConfigPath(ctx)
|
|
|
|
rule.Command().
|
|
BuiltTool("process-compat-config").
|
|
FlagForEachInput("--xml ", compatConfigMetadata).
|
|
FlagWithOutput("--merged-config ", outputPath)
|
|
|
|
rule.Build("merged-compat-config", "Merge compat config")
|
|
|
|
p.metadata = outputPath
|
|
}
|
|
|
|
func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
|
|
if p.metadata != nil {
|
|
ctx.Strict("INTERNAL_PLATFORM_MERGED_COMPAT_CONFIG", p.metadata.String())
|
|
}
|
|
}
|
|
|
|
func platformCompatConfigSingletonFactory() android.Singleton {
|
|
return &platformCompatConfigSingleton{}
|
|
}
|
|
|
|
//============== merged_compat_config =================
|
|
type globalCompatConfigProperties struct {
|
|
// name of the file into which the metadata will be copied.
|
|
Filename *string
|
|
}
|
|
|
|
type globalCompatConfig struct {
|
|
android.ModuleBase
|
|
|
|
properties globalCompatConfigProperties
|
|
|
|
outputFilePath android.OutputPath
|
|
}
|
|
|
|
func (c *globalCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
filename := String(c.properties.Filename)
|
|
|
|
inputPath := platformCompatConfigPath(ctx)
|
|
c.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
|
|
|
|
// This ensures that outputFilePath has the correct name for others to
|
|
// use, as the source file may have a different name.
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: android.Cp,
|
|
Output: c.outputFilePath,
|
|
Input: inputPath,
|
|
})
|
|
}
|
|
|
|
func (h *globalCompatConfig) OutputFiles(tag string) (android.Paths, error) {
|
|
switch tag {
|
|
case "":
|
|
return android.Paths{h.outputFilePath}, nil
|
|
default:
|
|
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
|
}
|
|
}
|
|
|
|
// global_compat_config provides access to the merged compat config xml file generated by the build.
|
|
func globalCompatConfigFactory() android.Module {
|
|
module := &globalCompatConfig{}
|
|
module.AddProperties(&module.properties)
|
|
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
|
|
return module
|
|
}
|