xref: /aosp_15_r20/build/soong/java/platform_compat_config.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2019 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18	"path/filepath"
19
20	"android/soong/android"
21
22	"github.com/google/blueprint"
23	"github.com/google/blueprint/proptools"
24)
25
26func init() {
27	registerPlatformCompatConfigBuildComponents(android.InitRegistrationContext)
28
29	android.RegisterSdkMemberType(CompatConfigSdkMemberType)
30}
31
32var CompatConfigSdkMemberType = &compatConfigMemberType{
33	SdkMemberTypeBase: android.SdkMemberTypeBase{
34		PropertyName: "compat_configs",
35		SupportsSdk:  true,
36	},
37}
38
39func registerPlatformCompatConfigBuildComponents(ctx android.RegistrationContext) {
40	ctx.RegisterParallelSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
41	ctx.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory)
42	ctx.RegisterModuleType("prebuilt_platform_compat_config", prebuiltCompatConfigFactory)
43	ctx.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
44}
45
46var PrepareForTestWithPlatformCompatConfig = android.FixtureRegisterWithContext(registerPlatformCompatConfigBuildComponents)
47
48func platformCompatConfigPath(ctx android.PathContext) android.OutputPath {
49	return android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml")
50}
51
52type platformCompatConfigProperties struct {
53	Src *string `android:"path"`
54}
55
56type platformCompatConfig struct {
57	android.ModuleBase
58
59	properties     platformCompatConfigProperties
60	installDirPath android.InstallPath
61	configFile     android.OutputPath
62	metadataFile   android.OutputPath
63
64	installConfigFile android.InstallPath
65}
66
67func (p *platformCompatConfig) compatConfigMetadata() android.Path {
68	return p.metadataFile
69}
70
71func (p *platformCompatConfig) CompatConfig() android.OutputPath {
72	return p.configFile
73}
74
75func (p *platformCompatConfig) SubDir() string {
76	return "compatconfig"
77}
78
79type platformCompatConfigMetadataProvider interface {
80	compatConfigMetadata() android.Path
81}
82
83type PlatformCompatConfigIntf interface {
84	android.Module
85
86	CompatConfig() android.OutputPath
87	// Sub dir under etc dir.
88	SubDir() string
89}
90
91var _ PlatformCompatConfigIntf = (*platformCompatConfig)(nil)
92var _ platformCompatConfigMetadataProvider = (*platformCompatConfig)(nil)
93
94func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
95	rule := android.NewRuleBuilder(pctx, ctx)
96
97	configFileName := p.Name() + ".xml"
98	metadataFileName := p.Name() + "_meta.xml"
99	p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath
100	p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath
101	path := android.PathForModuleSrc(ctx, String(p.properties.Src))
102
103	rule.Command().
104		BuiltTool("process-compat-config").
105		FlagWithInput("--jar ", path).
106		FlagWithOutput("--device-config ", p.configFile).
107		FlagWithOutput("--merged-config ", p.metadataFile)
108
109	p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig")
110	p.installConfigFile = android.PathForModuleInstall(ctx, "etc", "compatconfig", p.configFile.Base())
111	rule.Build(configFileName, "Extract compat/compat_config.xml and install it")
112	ctx.InstallFile(p.installDirPath, p.configFile.Base(), p.configFile)
113	ctx.SetOutputFiles(android.Paths{p.configFile}, "")
114}
115
116func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries {
117	return []android.AndroidMkEntries{android.AndroidMkEntries{
118		Class:      "ETC",
119		OutputFile: android.OptionalPathForPath(p.configFile),
120	}}
121}
122
123func PlatformCompatConfigFactory() android.Module {
124	module := &platformCompatConfig{}
125	module.AddProperties(&module.properties)
126	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
127	return module
128}
129
130type compatConfigMemberType struct {
131	android.SdkMemberTypeBase
132}
133
134func (b *compatConfigMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
135	ctx.AddVariationDependencies(nil, dependencyTag, names...)
136}
137
138func (b *compatConfigMemberType) IsInstance(module android.Module) bool {
139	_, ok := module.(*platformCompatConfig)
140	return ok
141}
142
143func (b *compatConfigMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
144	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_platform_compat_config")
145}
146
147func (b *compatConfigMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
148	return &compatConfigSdkMemberProperties{}
149}
150
151type compatConfigSdkMemberProperties struct {
152	android.SdkMemberPropertiesBase
153
154	Metadata android.Path
155}
156
157func (b *compatConfigSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
158	module := variant.(*platformCompatConfig)
159	b.Metadata = module.metadataFile
160}
161
162func (b *compatConfigSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
163	builder := ctx.SnapshotBuilder()
164	if b.Metadata != nil {
165		snapshotRelativePath := filepath.Join("compat_configs", ctx.Name(), b.Metadata.Base())
166		builder.CopyToSnapshot(b.Metadata, snapshotRelativePath)
167		propertySet.AddProperty("metadata", snapshotRelativePath)
168	}
169}
170
171var _ android.SdkMemberType = (*compatConfigMemberType)(nil)
172
173// A prebuilt version of the platform compat config module.
174type prebuiltCompatConfigModule struct {
175	android.ModuleBase
176	prebuilt android.Prebuilt
177
178	properties prebuiltCompatConfigProperties
179
180	metadataFile android.Path
181}
182
183type prebuiltCompatConfigProperties struct {
184	Metadata *string `android:"path"`
185
186	// Name of the source soong module that gets shadowed by this prebuilt
187	// If unspecified, follows the naming convention that the source module of
188	// the prebuilt is Name() without "prebuilt_" prefix
189	Source_module_name *string
190}
191
192func (module *prebuiltCompatConfigModule) Prebuilt() *android.Prebuilt {
193	return &module.prebuilt
194}
195
196func (module *prebuiltCompatConfigModule) Name() string {
197	return module.prebuilt.Name(module.ModuleBase.Name())
198}
199
200func (module *prebuiltCompatConfigModule) compatConfigMetadata() android.Path {
201	return module.metadataFile
202}
203
204func (module *prebuiltCompatConfigModule) BaseModuleName() string {
205	return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
206}
207
208var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil)
209
210func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
211	module.metadataFile = module.prebuilt.SingleSourcePath(ctx)
212}
213
214// A prebuilt version of platform_compat_config that provides the metadata.
215func prebuiltCompatConfigFactory() android.Module {
216	m := &prebuiltCompatConfigModule{}
217	m.AddProperties(&m.properties)
218	android.InitSingleSourcePrebuiltModule(m, &m.properties, "Metadata")
219	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
220	return m
221}
222
223// compat singleton rules
224type platformCompatConfigSingleton struct {
225	metadata android.Path
226}
227
228func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
229
230	var compatConfigMetadata android.Paths
231
232	ctx.VisitAllModules(func(module android.Module) {
233		if !module.Enabled(ctx) {
234			return
235		}
236		if c, ok := module.(platformCompatConfigMetadataProvider); ok {
237			if !android.IsModulePreferred(module) {
238				return
239			}
240			metadata := c.compatConfigMetadata()
241			compatConfigMetadata = append(compatConfigMetadata, metadata)
242		}
243	})
244
245	if compatConfigMetadata == nil {
246		// nothing to do.
247		return
248	}
249
250	rule := android.NewRuleBuilder(pctx, ctx)
251	outputPath := platformCompatConfigPath(ctx)
252
253	rule.Command().
254		BuiltTool("process-compat-config").
255		FlagForEachInput("--xml ", compatConfigMetadata).
256		FlagWithOutput("--merged-config ", outputPath)
257
258	rule.Build("merged-compat-config", "Merge compat config")
259
260	p.metadata = outputPath
261}
262
263func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
264	if p.metadata != nil {
265		ctx.DistForGoal("droidcore", p.metadata)
266	}
267}
268
269func platformCompatConfigSingletonFactory() android.Singleton {
270	return &platformCompatConfigSingleton{}
271}
272
273// ============== merged_compat_config =================
274type globalCompatConfigProperties struct {
275	// name of the file into which the metadata will be copied.
276	Filename *string
277}
278
279type globalCompatConfig struct {
280	android.ModuleBase
281
282	properties globalCompatConfigProperties
283}
284
285func (c *globalCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
286	filename := String(c.properties.Filename)
287
288	inputPath := platformCompatConfigPath(ctx)
289	outputFilePath := android.PathForModuleOut(ctx, filename).OutputPath
290
291	// This ensures that outputFilePath has the correct name for others to
292	// use, as the source file may have a different name.
293	ctx.Build(pctx, android.BuildParams{
294		Rule:   android.Cp,
295		Output: outputFilePath,
296		Input:  inputPath,
297	})
298
299	ctx.SetOutputFiles(android.Paths{outputFilePath}, "")
300}
301
302// global_compat_config provides access to the merged compat config xml file generated by the build.
303func globalCompatConfigFactory() android.Module {
304	module := &globalCompatConfig{}
305	module.AddProperties(&module.properties)
306	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
307	return module
308}
309