xref: /aosp_15_r20/build/soong/cc/image.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2020 The Android Open Source Project
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.
14package cc
15
16// This file contains image variant related things, including image mutator functions, utility
17// functions to determine where a module is installed, etc.
18
19import (
20	"strings"
21
22	"android/soong/android"
23
24	"github.com/google/blueprint/proptools"
25)
26
27var _ android.ImageInterface = (*Module)(nil)
28
29type ImageVariantType string
30
31const (
32	coreImageVariant          ImageVariantType = "core"
33	vendorImageVariant        ImageVariantType = "vendor"
34	productImageVariant       ImageVariantType = "product"
35	ramdiskImageVariant       ImageVariantType = "ramdisk"
36	vendorRamdiskImageVariant ImageVariantType = "vendor_ramdisk"
37	recoveryImageVariant      ImageVariantType = "recovery"
38	hostImageVariant          ImageVariantType = "host"
39)
40
41const (
42	// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
43	// against the VNDK.
44	VendorVariationPrefix = "vendor."
45
46	// ProductVariationPrefix is the variant prefix used for /product code that compiles
47	// against the VNDK.
48	ProductVariationPrefix = "product."
49)
50
51func (ctx *moduleContextImpl) inProduct() bool {
52	return ctx.mod.InProduct()
53}
54
55func (ctx *moduleContextImpl) inVendor() bool {
56	return ctx.mod.InVendor()
57}
58
59func (ctx *moduleContextImpl) inRamdisk() bool {
60	return ctx.mod.InRamdisk()
61}
62
63func (ctx *moduleContextImpl) inVendorRamdisk() bool {
64	return ctx.mod.InVendorRamdisk()
65}
66
67func (ctx *moduleContextImpl) inRecovery() bool {
68	return ctx.mod.InRecovery()
69}
70
71func (c *Module) InstallInProduct() bool {
72	// Additionally check if this module is inProduct() that means it is a "product" variant of a
73	// module. As well as product specific modules, product variants must be installed to /product.
74	return c.InProduct()
75}
76
77func (c *Module) InstallInVendor() bool {
78	// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
79	// module. As well as SoC specific modules, vendor variants must be installed to /vendor
80	// unless they have "odm_available: true".
81	return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm()
82}
83
84func (c *Module) InstallInOdm() bool {
85	// Some vendor variants want to be installed to /odm by setting "odm_available: true".
86	return c.InVendor() && c.VendorVariantToOdm()
87}
88
89// Returns true when this module is configured to have core and vendor variants.
90func (c *Module) HasVendorVariant() bool {
91	return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available)
92}
93
94// Returns true when this module creates a vendor variant and wants to install the vendor variant
95// to the odm partition.
96func (c *Module) VendorVariantToOdm() bool {
97	return Bool(c.VendorProperties.Odm_available)
98}
99
100// Returns true when this module is configured to have core and product variants.
101func (c *Module) HasProductVariant() bool {
102	return Bool(c.VendorProperties.Product_available)
103}
104
105// Returns true when this module is configured to have core and either product or vendor variants.
106func (c *Module) HasNonSystemVariants() bool {
107	return c.HasVendorVariant() || c.HasProductVariant()
108}
109
110// Returns true if the module is "product" variant. Usually these modules are installed in /product
111func (c *Module) InProduct() bool {
112	return c.Properties.ImageVariation == android.ProductVariation
113}
114
115// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
116func (c *Module) InVendor() bool {
117	return c.Properties.ImageVariation == android.VendorVariation
118}
119
120// Returns true if the module is "vendor" or "product" variant. This replaces previous UseVndk usages
121// which were misused to check if the module variant is vendor or product.
122func (c *Module) InVendorOrProduct() bool {
123	return c.InVendor() || c.InProduct()
124}
125
126func (c *Module) InRamdisk() bool {
127	return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
128}
129
130func (c *Module) InVendorRamdisk() bool {
131	return c.ModuleBase.InVendorRamdisk() || c.ModuleBase.InstallInVendorRamdisk()
132}
133
134func (c *Module) InRecovery() bool {
135	return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
136}
137
138func (c *Module) OnlyInRamdisk() bool {
139	return c.ModuleBase.InstallInRamdisk()
140}
141
142func (c *Module) OnlyInVendorRamdisk() bool {
143	return c.ModuleBase.InstallInVendorRamdisk()
144}
145
146func (c *Module) OnlyInRecovery() bool {
147	return c.ModuleBase.InstallInRecovery()
148}
149
150// ImageMutatableModule provides a common image mutation interface for  LinkableInterface modules.
151type ImageMutatableModule interface {
152	android.Module
153	LinkableInterface
154
155	// AndroidModuleBase returns the android.ModuleBase for this module
156	AndroidModuleBase() *android.ModuleBase
157
158	// VendorAvailable returns true if this module is available on the vendor image.
159	VendorAvailable() bool
160
161	// OdmAvailable returns true if this module is available on the odm image.
162	OdmAvailable() bool
163
164	// ProductAvailable returns true if this module is available on the product image.
165	ProductAvailable() bool
166
167	// RamdiskAvailable returns true if this module is available on the ramdisk image.
168	RamdiskAvailable() bool
169
170	// RecoveryAvailable returns true if this module is available on the recovery image.
171	RecoveryAvailable() bool
172
173	// VendorRamdiskAvailable returns true if this module is available on the vendor ramdisk image.
174	VendorRamdiskAvailable() bool
175
176	// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
177	IsSnapshotPrebuilt() bool
178
179	// SnapshotVersion returns the snapshot version for this module.
180	SnapshotVersion(mctx android.ImageInterfaceContext) string
181
182	// ExtraVariants returns the list of extra variants this module requires.
183	ExtraVariants() []string
184
185	// AppendExtraVariant returns an extra variant to the list of extra variants this module requires.
186	AppendExtraVariant(extraVariant string)
187
188	// SetRamdiskVariantNeeded sets whether the Ramdisk Variant is needed.
189	SetRamdiskVariantNeeded(b bool)
190
191	// SetVendorRamdiskVariantNeeded sets whether the Vendor Ramdisk Variant is needed.
192	SetVendorRamdiskVariantNeeded(b bool)
193
194	// SetRecoveryVariantNeeded sets whether the Recovery Variant is needed.
195	SetRecoveryVariantNeeded(b bool)
196
197	// SetCoreVariantNeeded sets whether the Core Variant is needed.
198	SetCoreVariantNeeded(b bool)
199
200	// SetProductVariantNeeded sets whether the Product Variant is needed.
201	SetProductVariantNeeded(b bool)
202
203	// SetVendorVariantNeeded sets whether the Vendor Variant is needed.
204	SetVendorVariantNeeded(b bool)
205}
206
207var _ ImageMutatableModule = (*Module)(nil)
208
209func (m *Module) ImageMutatorBegin(mctx android.ImageInterfaceContext) {
210	MutateImage(mctx, m)
211}
212
213func (m *Module) VendorAvailable() bool {
214	return Bool(m.VendorProperties.Vendor_available)
215}
216
217func (m *Module) OdmAvailable() bool {
218	return Bool(m.VendorProperties.Odm_available)
219}
220
221func (m *Module) ProductAvailable() bool {
222	return Bool(m.VendorProperties.Product_available)
223}
224
225func (m *Module) RamdiskAvailable() bool {
226	return Bool(m.Properties.Ramdisk_available)
227}
228
229func (m *Module) VendorRamdiskAvailable() bool {
230	return Bool(m.Properties.Vendor_ramdisk_available)
231}
232
233func (m *Module) AndroidModuleBase() *android.ModuleBase {
234	return &m.ModuleBase
235}
236
237func (m *Module) RecoveryAvailable() bool {
238	return Bool(m.Properties.Recovery_available)
239}
240
241func (m *Module) ExtraVariants() []string {
242	return m.Properties.ExtraVersionedImageVariations
243}
244
245func (m *Module) AppendExtraVariant(extraVariant string) {
246	m.Properties.ExtraVersionedImageVariations = append(m.Properties.ExtraVersionedImageVariations, extraVariant)
247}
248
249func (m *Module) SetRamdiskVariantNeeded(b bool) {
250	m.Properties.RamdiskVariantNeeded = b
251}
252
253func (m *Module) SetVendorRamdiskVariantNeeded(b bool) {
254	m.Properties.VendorRamdiskVariantNeeded = b
255}
256
257func (m *Module) SetRecoveryVariantNeeded(b bool) {
258	m.Properties.RecoveryVariantNeeded = b
259}
260
261func (m *Module) SetCoreVariantNeeded(b bool) {
262	m.Properties.CoreVariantNeeded = b
263}
264
265func (m *Module) SetProductVariantNeeded(b bool) {
266	m.Properties.ProductVariantNeeded = b
267}
268
269func (m *Module) SetVendorVariantNeeded(b bool) {
270	m.Properties.VendorVariantNeeded = b
271}
272
273func (m *Module) SnapshotVersion(mctx android.ImageInterfaceContext) string {
274	if snapshot, ok := m.linker.(SnapshotInterface); ok {
275		return snapshot.Version()
276	} else {
277		mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
278		// Should we be panicking here instead?
279		return ""
280	}
281}
282
283func (m *Module) KernelHeadersDecorator() bool {
284	if _, ok := m.linker.(*kernelHeadersDecorator); ok {
285		return true
286	}
287	return false
288}
289
290// MutateImage handles common image mutations for ImageMutatableModule interfaces.
291func MutateImage(mctx android.ImageInterfaceContext, m ImageMutatableModule) {
292	// Validation check
293	vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
294	productSpecific := mctx.ProductSpecific()
295
296	if m.VendorAvailable() {
297		if vendorSpecific {
298			mctx.PropertyErrorf("vendor_available",
299				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
300		}
301		if m.OdmAvailable() {
302			mctx.PropertyErrorf("vendor_available",
303				"doesn't make sense at the same time as `odm_available: true`")
304		}
305	}
306
307	if m.OdmAvailable() {
308		if vendorSpecific {
309			mctx.PropertyErrorf("odm_available",
310				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
311		}
312	}
313
314	if m.ProductAvailable() {
315		if productSpecific {
316			mctx.PropertyErrorf("product_available",
317				"doesn't make sense at the same time as `product_specific: true`")
318		}
319		if vendorSpecific {
320			mctx.PropertyErrorf("product_available",
321				"cannot provide product variant from a vendor module. Please use `product_specific: true` with `vendor_available: true`")
322		}
323	}
324
325	var vendorVariantNeeded bool = false
326	var productVariantNeeded bool = false
327	var coreVariantNeeded bool = false
328	var ramdiskVariantNeeded bool = false
329	var vendorRamdiskVariantNeeded bool = false
330	var recoveryVariantNeeded bool = false
331
332	if m.NeedsLlndkVariants() {
333		// This is an LLNDK library.  The implementation of the library will be on /system,
334		// and vendor and product variants will be created with LLNDK stubs.
335		// The LLNDK libraries need vendor variants even if there is no VNDK.
336		coreVariantNeeded = true
337		vendorVariantNeeded = true
338		productVariantNeeded = true
339
340	} else if m.NeedsVendorPublicLibraryVariants() {
341		// A vendor public library has the implementation on /vendor, with stub variants
342		// for system and product.
343		coreVariantNeeded = true
344		vendorVariantNeeded = true
345		productVariantNeeded = true
346	} else if m.IsSnapshotPrebuilt() {
347		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
348		// PRODUCT_EXTRA_VNDK_VERSIONS.
349		if m.InstallInRecovery() {
350			recoveryVariantNeeded = true
351		} else {
352			m.AppendExtraVariant(VendorVariationPrefix + m.SnapshotVersion(mctx))
353		}
354	} else if m.HasNonSystemVariants() {
355		// This will be available to /system unless it is product_specific
356		// which will be handled later.
357		coreVariantNeeded = true
358
359		// We assume that modules under proprietary paths are compatible for
360		// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
361		// PLATFORM_VNDK_VERSION.
362		if m.HasVendorVariant() {
363			vendorVariantNeeded = true
364		}
365
366		// product_available modules are available to /product.
367		if m.HasProductVariant() {
368			productVariantNeeded = true
369		}
370	} else if vendorSpecific {
371		// This will be available in /vendor (or /odm) only
372		vendorVariantNeeded = true
373	} else {
374		// This is either in /system (or similar: /data), or is a
375		// module built with the NDK. Modules built with the NDK
376		// will be restricted using the existing link type checks.
377		coreVariantNeeded = true
378	}
379
380	if coreVariantNeeded && productSpecific {
381		// The module has "product_specific: true" that does not create core variant.
382		coreVariantNeeded = false
383		productVariantNeeded = true
384	}
385
386	if m.RamdiskAvailable() {
387		ramdiskVariantNeeded = true
388	}
389
390	if m.AndroidModuleBase().InstallInRamdisk() {
391		ramdiskVariantNeeded = true
392		coreVariantNeeded = false
393	}
394
395	if m.VendorRamdiskAvailable() {
396		vendorRamdiskVariantNeeded = true
397	}
398
399	if m.AndroidModuleBase().InstallInVendorRamdisk() {
400		vendorRamdiskVariantNeeded = true
401		coreVariantNeeded = false
402	}
403
404	if m.RecoveryAvailable() {
405		recoveryVariantNeeded = true
406	}
407
408	if m.AndroidModuleBase().InstallInRecovery() {
409		recoveryVariantNeeded = true
410		coreVariantNeeded = false
411	}
412
413	m.SetRamdiskVariantNeeded(ramdiskVariantNeeded)
414	m.SetVendorRamdiskVariantNeeded(vendorRamdiskVariantNeeded)
415	m.SetRecoveryVariantNeeded(recoveryVariantNeeded)
416	m.SetCoreVariantNeeded(coreVariantNeeded)
417	m.SetProductVariantNeeded(productVariantNeeded)
418	m.SetVendorVariantNeeded(vendorVariantNeeded)
419
420	// Disable the module if no variants are needed.
421	if !ramdiskVariantNeeded &&
422		!recoveryVariantNeeded &&
423		!coreVariantNeeded &&
424		!productVariantNeeded &&
425		!vendorVariantNeeded &&
426		len(m.ExtraVariants()) == 0 {
427		m.Disable()
428	}
429}
430
431func (c *Module) VendorVariantNeeded(ctx android.ImageInterfaceContext) bool {
432	return c.Properties.VendorVariantNeeded
433}
434
435func (c *Module) ProductVariantNeeded(ctx android.ImageInterfaceContext) bool {
436	return c.Properties.ProductVariantNeeded
437}
438
439func (c *Module) CoreVariantNeeded(ctx android.ImageInterfaceContext) bool {
440	return c.Properties.CoreVariantNeeded
441}
442
443func (c *Module) RamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
444	return c.Properties.RamdiskVariantNeeded
445}
446
447func (c *Module) VendorRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
448	return c.Properties.VendorRamdiskVariantNeeded
449}
450
451func (c *Module) DebugRamdiskVariantNeeded(ctx android.ImageInterfaceContext) bool {
452	return false
453}
454
455func (c *Module) RecoveryVariantNeeded(ctx android.ImageInterfaceContext) bool {
456	return c.Properties.RecoveryVariantNeeded
457}
458
459func (c *Module) ExtraImageVariations(ctx android.ImageInterfaceContext) []string {
460	return c.Properties.ExtraVersionedImageVariations
461}
462
463func squashVendorSrcs(m *Module) {
464	if lib, ok := m.compiler.(*libraryDecorator); ok {
465		lib.baseCompiler.Properties.Srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Vendor.Srcs)
466		lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs)
467
468		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
469			lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
470
471		if lib.Properties.Target.Vendor.No_stubs {
472			proptools.Clear(&lib.Properties.Stubs)
473		}
474	}
475}
476
477func squashProductSrcs(m *Module) {
478	if lib, ok := m.compiler.(*libraryDecorator); ok {
479		lib.baseCompiler.Properties.Srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Product.Srcs)
480		lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Product.Exclude_srcs)
481
482		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
483			lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...)
484
485		if lib.Properties.Target.Product.No_stubs {
486			proptools.Clear(&lib.Properties.Stubs)
487		}
488	}
489}
490
491func squashRecoverySrcs(m *Module) {
492	if lib, ok := m.compiler.(*libraryDecorator); ok {
493		lib.baseCompiler.Properties.Srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Recovery.Srcs)
494		lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs)
495
496		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
497			lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...)
498	}
499}
500
501func squashVendorRamdiskSrcs(m *Module) {
502	if lib, ok := m.compiler.(*libraryDecorator); ok {
503		lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs)
504	}
505}
506
507func squashRamdiskSrcs(m *Module) {
508	if lib, ok := m.compiler.(*libraryDecorator); ok {
509		lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Ramdisk.Exclude_srcs)
510	}
511}
512
513func (c *Module) SetImageVariation(ctx android.ImageInterfaceContext, variant string) {
514	if variant == android.RamdiskVariation {
515		c.MakeAsPlatform()
516		squashRamdiskSrcs(c)
517	} else if variant == android.VendorRamdiskVariation {
518		c.MakeAsPlatform()
519		squashVendorRamdiskSrcs(c)
520	} else if variant == android.RecoveryVariation {
521		c.MakeAsPlatform()
522		squashRecoverySrcs(c)
523	} else if strings.HasPrefix(variant, android.VendorVariation) {
524		c.Properties.ImageVariation = android.VendorVariation
525
526		if strings.HasPrefix(variant, VendorVariationPrefix) {
527			c.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
528		}
529		squashVendorSrcs(c)
530	} else if strings.HasPrefix(variant, android.ProductVariation) {
531		c.Properties.ImageVariation = android.ProductVariation
532		if strings.HasPrefix(variant, ProductVariationPrefix) {
533			c.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
534		}
535		squashProductSrcs(c)
536	}
537
538	if c.NeedsVendorPublicLibraryVariants() &&
539		(variant == android.CoreVariation || strings.HasPrefix(variant, ProductVariationPrefix)) {
540		c.VendorProperties.IsVendorPublicLibrary = true
541	}
542}
543