platform_build_soong/java/platform_compat_config.go
Paul Duffin fcf79850d8 Export any platform_compat_config used by apex to sdk snapshot
Previously, the platform_compat_config modules needed to be explicitly
listed in the sdk snapshot and the apex. This change will automatically
export them to the sdk snapshot when the apex is listed in its apexes
property.

Bug: 232401814
Test: m tethering-module-sdk
      # Before this change the generated snapshot did not contain the
      # platform_compat_config, after this change it did.
      m art-module-sdk
      # As that explicitly specifies the platform_compat_config in its
      # compat_configs property this change has no effect.
Change-Id: Ia854b9a52db2b1619fca41a387ce98d7f9f9efe9
2022-07-20 14:18:24 +00:00

327 lines
9.9 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(CompatConfigSdkMemberType)
}
var CompatConfigSdkMemberType = &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.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(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
ctx.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 android.IsModuleInVersionedSdk(module) {
return false
}
return android.IsModulePreferred(module)
}
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
}