xref: /aosp_15_r20/build/soong/android/androidmk.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2015 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
15// This file offers AndroidMkEntriesProvider, which individual modules implement to output
16// Android.mk entries that contain information about the modules built through Soong. Kati reads
17// and combines them with the legacy Make-based module definitions to produce the complete view of
18// the source tree, which makes this a critical point of Make-Soong interoperability.
19//
20// Naturally, Soong-only builds do not rely on this mechanism.
21
22package android
23
24import (
25	"bytes"
26	"fmt"
27	"io"
28	"os"
29	"path/filepath"
30	"reflect"
31	"runtime"
32	"sort"
33	"strconv"
34	"strings"
35
36	"github.com/google/blueprint"
37	"github.com/google/blueprint/pathtools"
38	"github.com/google/blueprint/proptools"
39)
40
41func init() {
42	RegisterAndroidMkBuildComponents(InitRegistrationContext)
43}
44
45func RegisterAndroidMkBuildComponents(ctx RegistrationContext) {
46	ctx.RegisterParallelSingletonType("androidmk", AndroidMkSingleton)
47}
48
49// Enable androidmk support.
50// * Register the singleton
51// * Configure that we are inside make
52var PrepareForTestWithAndroidMk = GroupFixturePreparers(
53	FixtureRegisterWithContext(RegisterAndroidMkBuildComponents),
54	FixtureModifyConfig(SetKatiEnabledForTests),
55)
56
57// Deprecated: Use AndroidMkEntriesProvider instead, especially if you're not going to use the
58// Custom function. It's easier to use and test.
59type AndroidMkDataProvider interface {
60	AndroidMk() AndroidMkData
61	BaseModuleName() string
62}
63
64type AndroidMkData struct {
65	Class           string
66	SubName         string
67	DistFiles       TaggedDistFiles
68	OutputFile      OptionalPath
69	Disabled        bool
70	Include         string
71	Required        []string
72	Host_required   []string
73	Target_required []string
74
75	Custom func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData)
76
77	Extra []AndroidMkExtraFunc
78
79	Entries AndroidMkEntries
80}
81
82type AndroidMkExtraFunc func(w io.Writer, outputFile Path)
83
84// Interface for modules to declare their Android.mk outputs. Note that every module needs to
85// implement this in order to be included in the final Android-<product_name>.mk output, even if
86// they only need to output the common set of entries without any customizations.
87type AndroidMkEntriesProvider interface {
88	// Returns AndroidMkEntries objects that contain all basic info plus extra customization data
89	// if needed. This is the core func to implement.
90	// Note that one can return multiple objects. For example, java_library may return an additional
91	// AndroidMkEntries object for its hostdex sub-module.
92	AndroidMkEntries() []AndroidMkEntries
93	// Modules don't need to implement this as it's already implemented by ModuleBase.
94	// AndroidMkEntries uses BaseModuleName() instead of ModuleName() because certain modules
95	// e.g. Prebuilts, override the Name() func and return modified names.
96	// If a different name is preferred, use SubName or OverrideName in AndroidMkEntries.
97	BaseModuleName() string
98}
99
100// The core data struct that modules use to provide their Android.mk data.
101type AndroidMkEntries struct {
102	// Android.mk class string, e.g EXECUTABLES, JAVA_LIBRARIES, ETC
103	Class string
104	// Optional suffix to append to the module name. Useful when a module wants to return multiple
105	// AndroidMkEntries objects. For example, when a java_library returns an additional entry for
106	// its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a
107	// different name than the parent's.
108	SubName string
109	// If set, this value overrides the base module name. SubName is still appended.
110	OverrideName string
111	// Dist files to output
112	DistFiles TaggedDistFiles
113	// The output file for Kati to process and/or install. If absent, the module is skipped.
114	OutputFile OptionalPath
115	// If true, the module is skipped and does not appear on the final Android-<product name>.mk
116	// file. Useful when a module needs to be skipped conditionally.
117	Disabled bool
118	// The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk
119	// If not set, $(BUILD_SYSTEM)/prebuilt.mk is used.
120	Include string
121	// Required modules that need to be built and included in the final build output when building
122	// this module.
123	Required []string
124	// Required host modules that need to be built and included in the final build output when
125	// building this module.
126	Host_required []string
127	// Required device modules that need to be built and included in the final build output when
128	// building this module.
129	Target_required []string
130
131	header bytes.Buffer
132	footer bytes.Buffer
133
134	// Funcs to append additional Android.mk entries or modify the common ones. Multiple funcs are
135	// accepted so that common logic can be factored out as a shared func.
136	ExtraEntries []AndroidMkExtraEntriesFunc
137	// Funcs to add extra lines to the module's Android.mk output. Unlike AndroidMkExtraEntriesFunc,
138	// which simply sets Make variable values, this can be used for anything since it can write any
139	// Make statements directly to the final Android-*.mk file.
140	// Primarily used to call macros or declare/update Make targets.
141	ExtraFooters []AndroidMkExtraFootersFunc
142
143	// A map that holds the up-to-date Make variable values. Can be accessed from tests.
144	EntryMap map[string][]string
145	// A list of EntryMap keys in insertion order. This serves a few purposes:
146	// 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this,
147	// the outputted Android-*.mk file may change even though there have been no content changes.
148	// 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR),
149	// without worrying about the variables being mixed up in the actual mk file.
150	// 3. Makes troubleshooting and spotting errors easier.
151	entryOrder []string
152
153	// Provides data typically stored by Context objects that are commonly needed by
154	//AndroidMkEntries objects.
155	entryContext AndroidMkEntriesContext
156}
157
158type AndroidMkEntriesContext interface {
159	OtherModuleProviderContext
160	Config() Config
161}
162
163type AndroidMkExtraEntriesContext interface {
164	Provider(provider blueprint.AnyProviderKey) (any, bool)
165}
166
167type androidMkExtraEntriesContext struct {
168	ctx fillInEntriesContext
169	mod blueprint.Module
170}
171
172func (a *androidMkExtraEntriesContext) Provider(provider blueprint.AnyProviderKey) (any, bool) {
173	return a.ctx.otherModuleProvider(a.mod, provider)
174}
175
176type AndroidMkExtraEntriesFunc func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries)
177type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string)
178
179// Utility funcs to manipulate Android.mk variable entries.
180
181// SetString sets a Make variable with the given name to the given value.
182func (a *AndroidMkEntries) SetString(name, value string) {
183	if _, ok := a.EntryMap[name]; !ok {
184		a.entryOrder = append(a.entryOrder, name)
185	}
186	a.EntryMap[name] = []string{value}
187}
188
189// SetPath sets a Make variable with the given name to the given path string.
190func (a *AndroidMkEntries) SetPath(name string, path Path) {
191	if _, ok := a.EntryMap[name]; !ok {
192		a.entryOrder = append(a.entryOrder, name)
193	}
194	a.EntryMap[name] = []string{path.String()}
195}
196
197// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid.
198// It is a no-op if the given path is invalid.
199func (a *AndroidMkEntries) SetOptionalPath(name string, path OptionalPath) {
200	if path.Valid() {
201		a.SetPath(name, path.Path())
202	}
203}
204
205// AddPath appends the given path string to a Make variable with the given name.
206func (a *AndroidMkEntries) AddPath(name string, path Path) {
207	if _, ok := a.EntryMap[name]; !ok {
208		a.entryOrder = append(a.entryOrder, name)
209	}
210	a.EntryMap[name] = append(a.EntryMap[name], path.String())
211}
212
213// AddOptionalPath appends the given path string to a Make variable with the given name if it is
214// valid. It is a no-op if the given path is invalid.
215func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) {
216	if path.Valid() {
217		a.AddPath(name, path.Path())
218	}
219}
220
221// SetPaths sets a Make variable with the given name to a slice of the given path strings.
222func (a *AndroidMkEntries) SetPaths(name string, paths Paths) {
223	if _, ok := a.EntryMap[name]; !ok {
224		a.entryOrder = append(a.entryOrder, name)
225	}
226	a.EntryMap[name] = paths.Strings()
227}
228
229// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings
230// only if there are a non-zero amount of paths.
231func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) {
232	if len(paths) > 0 {
233		a.SetPaths(name, paths)
234	}
235}
236
237// AddPaths appends the given path strings to a Make variable with the given name.
238func (a *AndroidMkEntries) AddPaths(name string, paths Paths) {
239	if _, ok := a.EntryMap[name]; !ok {
240		a.entryOrder = append(a.entryOrder, name)
241	}
242	a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...)
243}
244
245// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true.
246// It is a no-op if the given flag is false.
247func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
248	if flag {
249		if _, ok := a.EntryMap[name]; !ok {
250			a.entryOrder = append(a.entryOrder, name)
251		}
252		a.EntryMap[name] = []string{"true"}
253	}
254}
255
256// SetBool sets a Make variable with the given name to if the given bool flag value.
257func (a *AndroidMkEntries) SetBool(name string, flag bool) {
258	if _, ok := a.EntryMap[name]; !ok {
259		a.entryOrder = append(a.entryOrder, name)
260	}
261	if flag {
262		a.EntryMap[name] = []string{"true"}
263	} else {
264		a.EntryMap[name] = []string{"false"}
265	}
266}
267
268// AddStrings appends the given strings to a Make variable with the given name.
269func (a *AndroidMkEntries) AddStrings(name string, value ...string) {
270	if len(value) == 0 {
271		return
272	}
273	if _, ok := a.EntryMap[name]; !ok {
274		a.entryOrder = append(a.entryOrder, name)
275	}
276	a.EntryMap[name] = append(a.EntryMap[name], value...)
277}
278
279// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling
280// for partial MTS and MCTS test suites.
281func (a *AndroidMkEntries) AddCompatibilityTestSuites(suites ...string) {
282	// M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}.
283	// To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite,
284	// we add the full test suite to our list.
285	if PrefixInList(suites, "mts-") && !InList("mts", suites) {
286		suites = append(suites, "mts")
287	}
288	if PrefixInList(suites, "mcts-") && !InList("mcts", suites) {
289		suites = append(suites, "mcts")
290	}
291	a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...)
292}
293
294// The contributions to the dist.
295type distContributions struct {
296	// Path to license metadata file.
297	licenseMetadataFile Path
298	// List of goals and the dist copy instructions.
299	copiesForGoals []*copiesForGoals
300}
301
302// getCopiesForGoals returns a copiesForGoals into which copy instructions that
303// must be processed when building one or more of those goals can be added.
304func (d *distContributions) getCopiesForGoals(goals string) *copiesForGoals {
305	copiesForGoals := &copiesForGoals{goals: goals}
306	d.copiesForGoals = append(d.copiesForGoals, copiesForGoals)
307	return copiesForGoals
308}
309
310// Associates a list of dist copy instructions with a set of goals for which they
311// should be run.
312type copiesForGoals struct {
313	// goals are a space separated list of build targets that will trigger the
314	// copy instructions.
315	goals string
316
317	// A list of instructions to copy a module's output files to somewhere in the
318	// dist directory.
319	copies []distCopy
320}
321
322// Adds a copy instruction.
323func (d *copiesForGoals) addCopyInstruction(from Path, dest string) {
324	d.copies = append(d.copies, distCopy{from, dest})
325}
326
327// Instruction on a path that must be copied into the dist.
328type distCopy struct {
329	// The path to copy from.
330	from Path
331
332	// The destination within the dist directory to copy to.
333	dest string
334}
335
336// Compute the contributions that the module makes to the dist.
337func (a *AndroidMkEntries) getDistContributions(mod blueprint.Module) *distContributions {
338	amod := mod.(Module).base()
339	name := amod.BaseModuleName()
340
341	// Collate the set of associated tag/paths available for copying to the dist.
342	// Start with an empty (nil) set.
343	var availableTaggedDists TaggedDistFiles
344
345	// Then merge in any that are provided explicitly by the module.
346	if a.DistFiles != nil {
347		// Merge the DistFiles into the set.
348		availableTaggedDists = availableTaggedDists.merge(a.DistFiles)
349	}
350
351	// If no paths have been provided for the DefaultDistTag and the output file is
352	// valid then add that as the default dist path.
353	if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() {
354		availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path())
355	}
356
357	info := OtherModuleProviderOrDefault(a.entryContext, mod, InstallFilesProvider)
358	// If the distFiles created by GenerateTaggedDistFiles contains paths for the
359	// DefaultDistTag then that takes priority so delete any existing paths.
360	if _, ok := info.DistFiles[DefaultDistTag]; ok {
361		delete(availableTaggedDists, DefaultDistTag)
362	}
363
364	// Finally, merge the distFiles created by GenerateTaggedDistFiles.
365	availableTaggedDists = availableTaggedDists.merge(info.DistFiles)
366
367	if len(availableTaggedDists) == 0 {
368		// Nothing dist-able for this module.
369		return nil
370	}
371
372	// Collate the contributions this module makes to the dist.
373	distContributions := &distContributions{}
374
375	if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) {
376		distContributions.licenseMetadataFile = info.LicenseMetadataFile
377	}
378
379	// Iterate over this module's dist structs, merged from the dist and dists properties.
380	for _, dist := range amod.Dists() {
381		// Get the list of goals this dist should be enabled for. e.g. sdk, droidcore
382		goals := strings.Join(dist.Targets, " ")
383
384		// Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map"
385		var tag string
386		if dist.Tag == nil {
387			// If the dist struct does not specify a tag, use the default output files tag.
388			tag = DefaultDistTag
389		} else {
390			tag = *dist.Tag
391		}
392
393		// Get the paths of the output files to be dist'd, represented by the tag.
394		// Can be an empty list.
395		tagPaths := availableTaggedDists[tag]
396		if len(tagPaths) == 0 {
397			// Nothing to dist for this tag, continue to the next dist.
398			continue
399		}
400
401		if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) {
402			errorMessage := "%s: Cannot apply dest/suffix for more than one dist " +
403				"file for %q goals tag %q in module %s. The list of dist files, " +
404				"which should have a single element, is:\n%s"
405			panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths))
406		}
407
408		copiesForGoals := distContributions.getCopiesForGoals(goals)
409
410		// Iterate over each path adding a copy instruction to copiesForGoals
411		for _, path := range tagPaths {
412			// It's possible that the Path is nil from errant modules. Be defensive here.
413			if path == nil {
414				tagName := "default" // for error message readability
415				if dist.Tag != nil {
416					tagName = *dist.Tag
417				}
418				panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name))
419			}
420
421			dest := filepath.Base(path.String())
422
423			if dist.Dest != nil {
424				var err error
425				if dest, err = validateSafePath(*dist.Dest); err != nil {
426					// This was checked in ModuleBase.GenerateBuildActions
427					panic(err)
428				}
429			}
430
431			ext := filepath.Ext(dest)
432			suffix := ""
433			if dist.Suffix != nil {
434				suffix = *dist.Suffix
435			}
436
437			productString := ""
438			if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product {
439				productString = fmt.Sprintf("_%s", a.entryContext.Config().DeviceProduct())
440			}
441
442			if suffix != "" || productString != "" {
443				dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext
444			}
445
446			if dist.Dir != nil {
447				var err error
448				if dest, err = validateSafePath(*dist.Dir, dest); err != nil {
449					// This was checked in ModuleBase.GenerateBuildActions
450					panic(err)
451				}
452			}
453
454			copiesForGoals.addCopyInstruction(path, dest)
455		}
456	}
457
458	return distContributions
459}
460
461// generateDistContributionsForMake generates make rules that will generate the
462// dist according to the instructions in the supplied distContribution.
463func generateDistContributionsForMake(distContributions *distContributions) []string {
464	var ret []string
465	for _, d := range distContributions.copiesForGoals {
466		ret = append(ret, fmt.Sprintf(".PHONY: %s", d.goals))
467		// Create dist-for-goals calls for each of the copy instructions.
468		for _, c := range d.copies {
469			if distContributions.licenseMetadataFile != nil {
470				ret = append(
471					ret,
472					fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))",
473						c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String()))
474			}
475			ret = append(
476				ret,
477				fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)", d.goals, c.from.String(), c.dest))
478		}
479	}
480
481	return ret
482}
483
484// Compute the list of Make strings to declare phony goals and dist-for-goals
485// calls from the module's dist and dists properties.
486func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
487	distContributions := a.getDistContributions(mod)
488	if distContributions == nil {
489		return nil
490	}
491
492	return generateDistContributionsForMake(distContributions)
493}
494
495// fillInEntries goes through the common variable processing and calls the extra data funcs to
496// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
497type fillInEntriesContext interface {
498	ModuleDir(module blueprint.Module) string
499	ModuleSubDir(module blueprint.Module) string
500	Config() Config
501	otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
502	ModuleType(module blueprint.Module) string
503	OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
504	HasMutatorFinished(mutatorName string) bool
505}
506
507func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
508	a.entryContext = ctx
509	a.EntryMap = make(map[string][]string)
510	amod := mod.(Module)
511	base := amod.base()
512	name := base.BaseModuleName()
513	if a.OverrideName != "" {
514		name = a.OverrideName
515	}
516
517	if a.Include == "" {
518		a.Include = "$(BUILD_PREBUILT)"
519	}
520	a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...)
521	a.Required = append(a.Required, amod.VintfFragmentModuleNames(ctx)...)
522	a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...)
523	a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...)
524
525	for _, distString := range a.GetDistForGoals(mod) {
526		fmt.Fprintln(&a.header, distString)
527	}
528
529	fmt.Fprintf(&a.header, "\ninclude $(CLEAR_VARS)  # type: %s, name: %s, variant: %s\n", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod))
530
531	// Collect make variable assignment entries.
532	a.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
533	a.SetString("LOCAL_MODULE", name+a.SubName)
534	a.SetString("LOCAL_MODULE_CLASS", a.Class)
535	a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
536	a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
537	a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
538	a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
539	a.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod))
540
541	// If the install rule was generated by Soong tell Make about it.
542	info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
543	if len(info.KatiInstalls) > 0 {
544		// Assume the primary install file is last since it probably needs to depend on any other
545		// installed files.  If that is not the case we can add a method to specify the primary
546		// installed file.
547		a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", info.KatiInstalls[len(info.KatiInstalls)-1].to)
548		a.SetString("LOCAL_SOONG_INSTALL_PAIRS", info.KatiInstalls.BuiltInstalled())
549		a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", info.KatiSymlinks.InstallPaths().Paths())
550	} else {
551		// Soong may not have generated the install rule also when `no_full_install: true`.
552		// Mark this module as uninstallable in order to prevent Make from creating an
553		// install rule there.
554		a.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install))
555	}
556
557	if info.UncheckedModule {
558		a.SetBool("LOCAL_DONT_CHECK_MODULE", true)
559	} else if info.CheckbuildTarget != nil {
560		a.SetPath("LOCAL_CHECKED_MODULE", info.CheckbuildTarget)
561	} else {
562		a.SetOptionalPath("LOCAL_CHECKED_MODULE", a.OutputFile)
563	}
564
565	if len(info.TestData) > 0 {
566		a.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...)
567	}
568
569	if am, ok := mod.(ApexModule); ok {
570		a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
571	}
572
573	archStr := base.Arch().ArchType.String()
574	host := false
575	switch base.Os().Class {
576	case Host:
577		if base.Target().HostCross {
578			// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
579			if base.Arch().ArchType != Common {
580				a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
581			}
582		} else {
583			// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
584			if base.Arch().ArchType != Common {
585				a.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
586			}
587		}
588		host = true
589	case Device:
590		// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
591		if base.Arch().ArchType != Common {
592			if base.Target().NativeBridge {
593				hostArchStr := base.Target().NativeBridgeHostArchName
594				if hostArchStr != "" {
595					a.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
596				}
597			} else {
598				a.SetString("LOCAL_MODULE_TARGET_ARCH", archStr)
599			}
600		}
601
602		if !base.InVendorRamdisk() {
603			a.AddPaths("LOCAL_FULL_INIT_RC", info.InitRcPaths)
604		}
605		if len(info.VintfFragmentsPaths) > 0 {
606			a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", info.VintfFragmentsPaths)
607		}
608		a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary))
609		if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) {
610			a.SetString("LOCAL_VENDOR_MODULE", "true")
611		}
612		a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific))
613		a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific))
614		a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific))
615		if base.commonProperties.Owner != nil {
616			a.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner)
617		}
618	}
619
620	if host {
621		makeOs := base.Os().String()
622		if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl {
623			makeOs = "linux"
624		}
625		a.SetString("LOCAL_MODULE_HOST_OS", makeOs)
626		a.SetString("LOCAL_IS_HOST_MODULE", "true")
627	}
628
629	prefix := ""
630	if base.ArchSpecific() {
631		switch base.Os().Class {
632		case Host:
633			if base.Target().HostCross {
634				prefix = "HOST_CROSS_"
635			} else {
636				prefix = "HOST_"
637			}
638		case Device:
639			prefix = "TARGET_"
640
641		}
642
643		if base.Arch().ArchType != ctx.Config().Targets[base.Os()][0].Arch.ArchType {
644			prefix = "2ND_" + prefix
645		}
646	}
647
648	if licenseMetadata, ok := OtherModuleProvider(ctx, mod, LicenseMetadataProvider); ok {
649		a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
650	}
651
652	if _, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
653		a.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true)
654	}
655
656	extraCtx := &androidMkExtraEntriesContext{
657		ctx: ctx,
658		mod: mod,
659	}
660
661	for _, extra := range a.ExtraEntries {
662		extra(extraCtx, a)
663	}
664
665	// Write to footer.
666	fmt.Fprintln(&a.footer, "include "+a.Include)
667	blueprintDir := ctx.ModuleDir(mod)
668	for _, footerFunc := range a.ExtraFooters {
669		footerFunc(&a.footer, name, prefix, blueprintDir)
670	}
671}
672
673func (a *AndroidMkEntries) disabled() bool {
674	return a.Disabled || !a.OutputFile.Valid()
675}
676
677// write  flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
678// given Writer object.
679func (a *AndroidMkEntries) write(w io.Writer) {
680	if a.disabled() {
681		return
682	}
683
684	w.Write(a.header.Bytes())
685	for _, name := range a.entryOrder {
686		AndroidMkEmitAssignList(w, name, a.EntryMap[name])
687	}
688	w.Write(a.footer.Bytes())
689}
690
691func (a *AndroidMkEntries) FooterLinesForTests() []string {
692	return strings.Split(string(a.footer.Bytes()), "\n")
693}
694
695// AndroidMkSingleton is a singleton to collect Android.mk data from all modules and dump them into
696// the final Android-<product_name>.mk file output.
697func AndroidMkSingleton() Singleton {
698	return &androidMkSingleton{}
699}
700
701type androidMkSingleton struct{}
702
703func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
704	// Skip if Soong wasn't invoked from Make.
705	if !ctx.Config().KatiEnabled() {
706		return
707	}
708
709	var androidMkModulesList []blueprint.Module
710
711	ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
712		androidMkModulesList = append(androidMkModulesList, module)
713	})
714
715	// Sort the module list by the module names to eliminate random churns, which may erroneously
716	// invoke additional build processes.
717	sort.SliceStable(androidMkModulesList, func(i, j int) bool {
718		return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
719	})
720
721	transMk := PathForOutput(ctx, "Android"+String(ctx.Config().productVariables.Make_suffix)+".mk")
722	if ctx.Failed() {
723		return
724	}
725
726	moduleInfoJSON := PathForOutput(ctx, "module-info"+String(ctx.Config().productVariables.Make_suffix)+".json")
727
728	err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, androidMkModulesList)
729	if err != nil {
730		ctx.Errorf(err.Error())
731	}
732
733	ctx.Build(pctx, BuildParams{
734		Rule:   blueprint.Phony,
735		Output: transMk,
736	})
737}
738
739func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []blueprint.Module) error {
740	buf := &bytes.Buffer{}
741
742	var moduleInfoJSONs []*ModuleInfoJSON
743
744	fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
745
746	typeStats := make(map[string]int)
747	for _, mod := range mods {
748		err := translateAndroidMkModule(ctx, buf, &moduleInfoJSONs, mod)
749		if err != nil {
750			os.Remove(absMkFile)
751			return err
752		}
753
754		if amod, ok := mod.(Module); ok && ctx.PrimaryModule(amod) == amod {
755			typeStats[ctx.ModuleType(amod)] += 1
756		}
757	}
758
759	keys := []string{}
760	fmt.Fprintln(buf, "\nSTATS.SOONG_MODULE_TYPE :=")
761	for k := range typeStats {
762		keys = append(keys, k)
763	}
764	sort.Strings(keys)
765	for _, mod_type := range keys {
766		fmt.Fprintln(buf, "STATS.SOONG_MODULE_TYPE +=", mod_type)
767		fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type])
768	}
769
770	err := pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666)
771	if err != nil {
772		return err
773	}
774
775	return writeModuleInfoJSON(ctx, moduleInfoJSONs, moduleInfoJSONPath)
776}
777
778func writeModuleInfoJSON(ctx SingletonContext, moduleInfoJSONs []*ModuleInfoJSON, moduleInfoJSONPath WritablePath) error {
779	moduleInfoJSONBuf := &strings.Builder{}
780	moduleInfoJSONBuf.WriteString("[")
781	for i, moduleInfoJSON := range moduleInfoJSONs {
782		if i != 0 {
783			moduleInfoJSONBuf.WriteString(",\n")
784		}
785		moduleInfoJSONBuf.WriteString("{")
786		moduleInfoJSONBuf.WriteString(strconv.Quote(moduleInfoJSON.core.RegisterName))
787		moduleInfoJSONBuf.WriteString(":")
788		err := encodeModuleInfoJSON(moduleInfoJSONBuf, moduleInfoJSON)
789		moduleInfoJSONBuf.WriteString("}")
790		if err != nil {
791			return err
792		}
793	}
794	moduleInfoJSONBuf.WriteString("]")
795	WriteFileRule(ctx, moduleInfoJSONPath, moduleInfoJSONBuf.String())
796	return nil
797}
798
799func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod blueprint.Module) error {
800	defer func() {
801		if r := recover(); r != nil {
802			panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s",
803				r, ctx.ModuleName(mod), ctx.ModuleSubDir(mod)))
804		}
805	}()
806
807	// Additional cases here require review for correct license propagation to make.
808	var err error
809
810	if info, ok := OtherModuleProvider(ctx, mod, AndroidMkInfoProvider); ok {
811		err = translateAndroidMkEntriesInfoModule(ctx, w, moduleInfoJSONs, mod, info)
812	} else {
813		switch x := mod.(type) {
814		case AndroidMkDataProvider:
815			err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x)
816		case AndroidMkEntriesProvider:
817			err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x)
818		default:
819			// Not exported to make so no make variables to set.
820		}
821	}
822
823	if err != nil {
824		return err
825	}
826
827	return err
828}
829
830func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod blueprint.Module) {
831	// Get the preamble content through AndroidMkEntries logic.
832	data.Entries = AndroidMkEntries{
833		Class:           data.Class,
834		SubName:         data.SubName,
835		DistFiles:       data.DistFiles,
836		OutputFile:      data.OutputFile,
837		Disabled:        data.Disabled,
838		Include:         data.Include,
839		Required:        data.Required,
840		Host_required:   data.Host_required,
841		Target_required: data.Target_required,
842	}
843	data.Entries.fillInEntries(ctx, mod)
844
845	// copy entries back to data since it is used in Custom
846	data.Required = data.Entries.Required
847	data.Host_required = data.Entries.Host_required
848	data.Target_required = data.Entries.Target_required
849}
850
851// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
852// instead.
853func translateAndroidModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
854	mod blueprint.Module, provider AndroidMkDataProvider) error {
855
856	amod := mod.(Module).base()
857	if shouldSkipAndroidMkProcessing(ctx, amod) {
858		return nil
859	}
860
861	data := provider.AndroidMk()
862
863	if data.Include == "" {
864		data.Include = "$(BUILD_PREBUILT)"
865	}
866
867	data.fillInData(ctx, mod)
868	aconfigUpdateAndroidMkData(ctx, mod.(Module), &data)
869
870	prefix := ""
871	if amod.ArchSpecific() {
872		switch amod.Os().Class {
873		case Host:
874			if amod.Target().HostCross {
875				prefix = "HOST_CROSS_"
876			} else {
877				prefix = "HOST_"
878			}
879		case Device:
880			prefix = "TARGET_"
881
882		}
883
884		if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType {
885			prefix = "2ND_" + prefix
886		}
887	}
888
889	name := provider.BaseModuleName()
890	blueprintDir := filepath.Dir(ctx.BlueprintFile(mod))
891
892	if data.Custom != nil {
893		// List of module types allowed to use .Custom(...)
894		// Additions to the list require careful review for proper license handling.
895		switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type
896		case "*aidl.aidlApi": // writes non-custom before adding .phony
897		case "*aidl.aidlMapping": // writes non-custom before adding .phony
898		case "*android.customModule": // appears in tests only
899		case "*android_sdk.sdkRepoHost": // doesn't go through base_rules
900		case "*apex.apexBundle": // license properties written
901		case "*bpf.bpf": // license properties written (both for module and objs)
902		case "*libbpf_prog.libbpfProg": // license properties written (both for module and objs)
903		case "*genrule.Module": // writes non-custom before adding .phony
904		case "*java.SystemModules": // doesn't go through base_rules
905		case "*java.systemModulesImport": // doesn't go through base_rules
906		case "*phony.phony": // license properties written
907		case "*phony.PhonyRule": // writes phony deps and acts like `.PHONY`
908		case "*selinux.selinuxContextsModule": // license properties written
909		case "*sysprop.syspropLibrary": // license properties written
910		case "*vintf.vintfCompatibilityMatrixRule": // use case like phony
911		default:
912			if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") {
913				return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod))
914			}
915		}
916		data.Custom(w, name, prefix, blueprintDir, data)
917	} else {
918		WriteAndroidMkData(w, data)
919	}
920
921	if !data.Entries.disabled() {
922		if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
923			*moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
924		}
925	}
926
927	return nil
928}
929
930// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
931// instead.
932func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
933	if data.Entries.disabled() {
934		return
935	}
936
937	// write preamble via Entries
938	data.Entries.footer = bytes.Buffer{}
939	data.Entries.write(w)
940
941	for _, extra := range data.Extra {
942		extra(w, data.OutputFile.Path())
943	}
944
945	fmt.Fprintln(w, "include "+data.Include)
946}
947
948func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
949	mod blueprint.Module, provider AndroidMkEntriesProvider) error {
950	if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) {
951		return nil
952	}
953
954	entriesList := provider.AndroidMkEntries()
955	aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList)
956
957	// Any new or special cases here need review to verify correct propagation of license information.
958	for _, entries := range entriesList {
959		entries.fillInEntries(ctx, mod)
960		entries.write(w)
961	}
962
963	if len(entriesList) > 0 && !entriesList[0].disabled() {
964		if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
965			*moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
966		}
967	}
968
969	return nil
970}
971
972func ShouldSkipAndroidMkProcessing(ctx ConfigurableEvaluatorContext, module Module) bool {
973	return shouldSkipAndroidMkProcessing(ctx, module.base())
974}
975
976func shouldSkipAndroidMkProcessing(ctx ConfigurableEvaluatorContext, module *ModuleBase) bool {
977	if !module.commonProperties.NamespaceExportedToMake {
978		// TODO(jeffrygaston) do we want to validate that there are no modules being
979		// exported to Kati that depend on this module?
980		return true
981	}
982
983	// On Mac, only expose host darwin modules to Make, as that's all we claim to support.
984	// In reality, some of them depend on device-built (Java) modules, so we can't disable all
985	// device modules in Soong, but we can hide them from Make (and thus the build user interface)
986	if runtime.GOOS == "darwin" && module.Os() != Darwin {
987		return true
988	}
989
990	// Only expose the primary Darwin target, as Make does not understand Darwin+Arm64
991	if module.Os() == Darwin && module.Target().HostCross {
992		return true
993	}
994
995	return !module.Enabled(ctx) ||
996		module.commonProperties.HideFromMake ||
997		// Make does not understand LinuxBionic
998		module.Os() == LinuxBionic ||
999		// Make does not understand LinuxMusl, except when we are building with USE_HOST_MUSL=true
1000		// and all host binaries are LinuxMusl
1001		(module.Os() == LinuxMusl && module.Target().HostCross)
1002}
1003
1004// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how
1005// to use this func.
1006func androidMkDataPaths(data []DataPath) []string {
1007	var testFiles []string
1008	for _, d := range data {
1009		rel := d.SrcPath.Rel()
1010		if d.WithoutRel {
1011			rel = d.SrcPath.Base()
1012		}
1013		path := d.SrcPath.String()
1014		// LOCAL_TEST_DATA requires the rel portion of the path to be removed from the path.
1015		if !strings.HasSuffix(path, rel) {
1016			panic(fmt.Errorf("path %q does not end with %q", path, rel))
1017		}
1018		path = strings.TrimSuffix(path, rel)
1019		testFileString := path + ":" + rel
1020		if len(d.RelativeInstallPath) > 0 {
1021			testFileString += ":" + d.RelativeInstallPath
1022		}
1023		testFiles = append(testFiles, testFileString)
1024	}
1025	return testFiles
1026}
1027
1028// AndroidMkEmitAssignList emits the line
1029//
1030//	VAR := ITEM ...
1031//
1032// Items are the elements to the given set of lists
1033// If all the passed lists are empty, no line will be emitted
1034func AndroidMkEmitAssignList(w io.Writer, varName string, lists ...[]string) {
1035	doPrint := false
1036	for _, l := range lists {
1037		if doPrint = len(l) > 0; doPrint {
1038			break
1039		}
1040	}
1041	if !doPrint {
1042		return
1043	}
1044	fmt.Fprint(w, varName, " :=")
1045	for _, l := range lists {
1046		for _, item := range l {
1047			fmt.Fprint(w, " ", item)
1048		}
1049	}
1050	fmt.Fprintln(w)
1051}
1052
1053type AndroidMkProviderInfo struct {
1054	PrimaryInfo AndroidMkInfo
1055	ExtraInfo   []AndroidMkInfo
1056}
1057
1058type AndroidMkInfo struct {
1059	// Android.mk class string, e.g. EXECUTABLES, JAVA_LIBRARIES, ETC
1060	Class string
1061	// Optional suffix to append to the module name. Useful when a module wants to return multiple
1062	// AndroidMkEntries objects. For example, when a java_library returns an additional entry for
1063	// its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a
1064	// different name than the parent's.
1065	SubName string
1066	// If set, this value overrides the base module name. SubName is still appended.
1067	OverrideName string
1068	// Dist files to output
1069	DistFiles TaggedDistFiles
1070	// The output file for Kati to process and/or install. If absent, the module is skipped.
1071	OutputFile OptionalPath
1072	// If true, the module is skipped and does not appear on the final Android-<product name>.mk
1073	// file. Useful when a module needs to be skipped conditionally.
1074	Disabled bool
1075	// The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk
1076	// If not set, $(BUILD_SYSTEM)/prebuilt.mk is used.
1077	Include string
1078	// Required modules that need to be built and included in the final build output when building
1079	// this module.
1080	Required []string
1081	// Required host modules that need to be built and included in the final build output when
1082	// building this module.
1083	Host_required []string
1084	// Required device modules that need to be built and included in the final build output when
1085	// building this module.
1086	Target_required []string
1087
1088	HeaderStrings []string
1089	FooterStrings []string
1090
1091	// A map that holds the up-to-date Make variable values. Can be accessed from tests.
1092	EntryMap map[string][]string
1093	// A list of EntryMap keys in insertion order. This serves a few purposes:
1094	// 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this,
1095	// the outputted Android-*.mk file may change even though there have been no content changes.
1096	// 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR),
1097	// without worrying about the variables being mixed up in the actual mk file.
1098	// 3. Makes troubleshooting and spotting errors easier.
1099	EntryOrder []string
1100}
1101
1102type AndroidMkProviderInfoProducer interface {
1103	PrepareAndroidMKProviderInfo(config Config) *AndroidMkProviderInfo
1104}
1105
1106// TODO: rename it to AndroidMkEntriesProvider after AndroidMkEntriesProvider interface is gone.
1107var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]()
1108
1109func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
1110	mod blueprint.Module, providerInfo *AndroidMkProviderInfo) error {
1111	if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) {
1112		return nil
1113	}
1114
1115	// Deep copy the provider info since we need to modify the info later
1116	info := deepCopyAndroidMkProviderInfo(providerInfo)
1117
1118	aconfigUpdateAndroidMkInfos(ctx, mod.(Module), &info)
1119
1120	// Any new or special cases here need review to verify correct propagation of license information.
1121	info.PrimaryInfo.fillInEntries(ctx, mod)
1122	info.PrimaryInfo.write(w)
1123	if len(info.ExtraInfo) > 0 {
1124		for _, ei := range info.ExtraInfo {
1125			ei.fillInEntries(ctx, mod)
1126			ei.write(w)
1127		}
1128	}
1129
1130	if !info.PrimaryInfo.disabled() {
1131		if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
1132			*moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
1133		}
1134	}
1135
1136	return nil
1137}
1138
1139// Utility funcs to manipulate Android.mk variable entries.
1140
1141// SetString sets a Make variable with the given name to the given value.
1142func (a *AndroidMkInfo) SetString(name, value string) {
1143	if _, ok := a.EntryMap[name]; !ok {
1144		a.EntryOrder = append(a.EntryOrder, name)
1145	}
1146	a.EntryMap[name] = []string{value}
1147}
1148
1149// SetPath sets a Make variable with the given name to the given path string.
1150func (a *AndroidMkInfo) SetPath(name string, path Path) {
1151	if _, ok := a.EntryMap[name]; !ok {
1152		a.EntryOrder = append(a.EntryOrder, name)
1153	}
1154	a.EntryMap[name] = []string{path.String()}
1155}
1156
1157// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid.
1158// It is a no-op if the given path is invalid.
1159func (a *AndroidMkInfo) SetOptionalPath(name string, path OptionalPath) {
1160	if path.Valid() {
1161		a.SetPath(name, path.Path())
1162	}
1163}
1164
1165// AddPath appends the given path string to a Make variable with the given name.
1166func (a *AndroidMkInfo) AddPath(name string, path Path) {
1167	if _, ok := a.EntryMap[name]; !ok {
1168		a.EntryOrder = append(a.EntryOrder, name)
1169	}
1170	a.EntryMap[name] = append(a.EntryMap[name], path.String())
1171}
1172
1173// AddOptionalPath appends the given path string to a Make variable with the given name if it is
1174// valid. It is a no-op if the given path is invalid.
1175func (a *AndroidMkInfo) AddOptionalPath(name string, path OptionalPath) {
1176	if path.Valid() {
1177		a.AddPath(name, path.Path())
1178	}
1179}
1180
1181// SetPaths sets a Make variable with the given name to a slice of the given path strings.
1182func (a *AndroidMkInfo) SetPaths(name string, paths Paths) {
1183	if _, ok := a.EntryMap[name]; !ok {
1184		a.EntryOrder = append(a.EntryOrder, name)
1185	}
1186	a.EntryMap[name] = paths.Strings()
1187}
1188
1189// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings
1190// only if there are a non-zero amount of paths.
1191func (a *AndroidMkInfo) SetOptionalPaths(name string, paths Paths) {
1192	if len(paths) > 0 {
1193		a.SetPaths(name, paths)
1194	}
1195}
1196
1197// AddPaths appends the given path strings to a Make variable with the given name.
1198func (a *AndroidMkInfo) AddPaths(name string, paths Paths) {
1199	if _, ok := a.EntryMap[name]; !ok {
1200		a.EntryOrder = append(a.EntryOrder, name)
1201	}
1202	a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...)
1203}
1204
1205// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true.
1206// It is a no-op if the given flag is false.
1207func (a *AndroidMkInfo) SetBoolIfTrue(name string, flag bool) {
1208	if flag {
1209		if _, ok := a.EntryMap[name]; !ok {
1210			a.EntryOrder = append(a.EntryOrder, name)
1211		}
1212		a.EntryMap[name] = []string{"true"}
1213	}
1214}
1215
1216// SetBool sets a Make variable with the given name to if the given bool flag value.
1217func (a *AndroidMkInfo) SetBool(name string, flag bool) {
1218	if _, ok := a.EntryMap[name]; !ok {
1219		a.EntryOrder = append(a.EntryOrder, name)
1220	}
1221	if flag {
1222		a.EntryMap[name] = []string{"true"}
1223	} else {
1224		a.EntryMap[name] = []string{"false"}
1225	}
1226}
1227
1228// AddStrings appends the given strings to a Make variable with the given name.
1229func (a *AndroidMkInfo) AddStrings(name string, value ...string) {
1230	if len(value) == 0 {
1231		return
1232	}
1233	if _, ok := a.EntryMap[name]; !ok {
1234		a.EntryOrder = append(a.EntryOrder, name)
1235	}
1236	a.EntryMap[name] = append(a.EntryMap[name], value...)
1237}
1238
1239// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling
1240// for partial MTS and MCTS test suites.
1241func (a *AndroidMkInfo) AddCompatibilityTestSuites(suites ...string) {
1242	// M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}.
1243	// To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite,
1244	// we add the full test suite to our list.
1245	if PrefixInList(suites, "mts-") && !InList("mts", suites) {
1246		suites = append(suites, "mts")
1247	}
1248	if PrefixInList(suites, "mcts-") && !InList("mcts", suites) {
1249		suites = append(suites, "mcts")
1250	}
1251	a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...)
1252}
1253
1254func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
1255	helperInfo := AndroidMkInfo{
1256		EntryMap: make(map[string][]string),
1257	}
1258
1259	amod := mod.(Module)
1260	base := amod.base()
1261	name := base.BaseModuleName()
1262	if a.OverrideName != "" {
1263		name = a.OverrideName
1264	}
1265
1266	if a.Include == "" {
1267		a.Include = "$(BUILD_PREBUILT)"
1268	}
1269	a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...)
1270	a.Required = append(a.Required, amod.VintfFragmentModuleNames(ctx)...)
1271	a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...)
1272	a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...)
1273
1274	for _, distString := range a.GetDistForGoals(ctx, mod) {
1275		a.HeaderStrings = append(a.HeaderStrings, distString)
1276	}
1277
1278	a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS)  # type: %s, name: %s, variant: %s", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod)))
1279
1280	// Collect make variable assignment entries.
1281	helperInfo.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
1282	helperInfo.SetString("LOCAL_MODULE", name+a.SubName)
1283	helperInfo.SetString("LOCAL_MODULE_CLASS", a.Class)
1284	helperInfo.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
1285	helperInfo.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
1286	helperInfo.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
1287	helperInfo.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
1288	helperInfo.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod))
1289
1290	// If the install rule was generated by Soong tell Make about it.
1291	info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
1292	if len(info.KatiInstalls) > 0 {
1293		// Assume the primary install file is last since it probably needs to depend on any other
1294		// installed files.  If that is not the case we can add a method to specify the primary
1295		// installed file.
1296		helperInfo.SetPath("LOCAL_SOONG_INSTALLED_MODULE", info.KatiInstalls[len(info.KatiInstalls)-1].to)
1297		helperInfo.SetString("LOCAL_SOONG_INSTALL_PAIRS", info.KatiInstalls.BuiltInstalled())
1298		helperInfo.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", info.KatiSymlinks.InstallPaths().Paths())
1299	} else {
1300		// Soong may not have generated the install rule also when `no_full_install: true`.
1301		// Mark this module as uninstallable in order to prevent Make from creating an
1302		// install rule there.
1303		helperInfo.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install))
1304	}
1305
1306	if info.UncheckedModule {
1307		helperInfo.SetBool("LOCAL_DONT_CHECK_MODULE", true)
1308	} else if info.CheckbuildTarget != nil {
1309		helperInfo.SetPath("LOCAL_CHECKED_MODULE", info.CheckbuildTarget)
1310	} else {
1311		helperInfo.SetOptionalPath("LOCAL_CHECKED_MODULE", a.OutputFile)
1312	}
1313
1314	if len(info.TestData) > 0 {
1315		helperInfo.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...)
1316	}
1317
1318	if am, ok := mod.(ApexModule); ok {
1319		helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
1320	}
1321
1322	archStr := base.Arch().ArchType.String()
1323	host := false
1324	switch base.Os().Class {
1325	case Host:
1326		if base.Target().HostCross {
1327			// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
1328			if base.Arch().ArchType != Common {
1329				helperInfo.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
1330			}
1331		} else {
1332			// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
1333			if base.Arch().ArchType != Common {
1334				helperInfo.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
1335			}
1336		}
1337		host = true
1338	case Device:
1339		// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
1340		if base.Arch().ArchType != Common {
1341			if base.Target().NativeBridge {
1342				hostArchStr := base.Target().NativeBridgeHostArchName
1343				if hostArchStr != "" {
1344					helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
1345				}
1346			} else {
1347				helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", archStr)
1348			}
1349		}
1350
1351		if !base.InVendorRamdisk() {
1352			helperInfo.AddPaths("LOCAL_FULL_INIT_RC", info.InitRcPaths)
1353		}
1354		if len(info.VintfFragmentsPaths) > 0 {
1355			helperInfo.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", info.VintfFragmentsPaths)
1356		}
1357		helperInfo.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary))
1358		if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) {
1359			helperInfo.SetString("LOCAL_VENDOR_MODULE", "true")
1360		}
1361		helperInfo.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific))
1362		helperInfo.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific))
1363		helperInfo.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific))
1364		if base.commonProperties.Owner != nil {
1365			helperInfo.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner)
1366		}
1367	}
1368
1369	if host {
1370		makeOs := base.Os().String()
1371		if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl {
1372			makeOs = "linux"
1373		}
1374		helperInfo.SetString("LOCAL_MODULE_HOST_OS", makeOs)
1375		helperInfo.SetString("LOCAL_IS_HOST_MODULE", "true")
1376	}
1377
1378	if licenseMetadata, ok := OtherModuleProvider(ctx, mod, LicenseMetadataProvider); ok {
1379		helperInfo.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
1380	}
1381
1382	if _, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
1383		helperInfo.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true)
1384	}
1385
1386	a.mergeEntries(&helperInfo)
1387
1388	// Write to footer.
1389	a.FooterStrings = append([]string{"include " + a.Include}, a.FooterStrings...)
1390}
1391
1392// This method merges the entries to helperInfo, then replaces a's EntryMap and
1393// EntryOrder with helperInfo's
1394func (a *AndroidMkInfo) mergeEntries(helperInfo *AndroidMkInfo) {
1395	for _, extraEntry := range a.EntryOrder {
1396		if v, ok := helperInfo.EntryMap[extraEntry]; ok {
1397			v = append(v, a.EntryMap[extraEntry]...)
1398		} else {
1399			helperInfo.EntryMap[extraEntry] = a.EntryMap[extraEntry]
1400			helperInfo.EntryOrder = append(helperInfo.EntryOrder, extraEntry)
1401		}
1402	}
1403	a.EntryOrder = helperInfo.EntryOrder
1404	a.EntryMap = helperInfo.EntryMap
1405}
1406
1407func (a *AndroidMkInfo) disabled() bool {
1408	return a.Disabled || !a.OutputFile.Valid()
1409}
1410
1411// write  flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
1412// given Writer object.
1413func (a *AndroidMkInfo) write(w io.Writer) {
1414	if a.disabled() {
1415		return
1416	}
1417
1418	combinedHeaderString := strings.Join(a.HeaderStrings, "\n") + "\n"
1419	combinedFooterString := strings.Join(a.FooterStrings, "\n") + "\n"
1420	w.Write([]byte(combinedHeaderString))
1421	for _, name := range a.EntryOrder {
1422		AndroidMkEmitAssignList(w, name, a.EntryMap[name])
1423	}
1424	w.Write([]byte(combinedFooterString))
1425}
1426
1427// Compute the list of Make strings to declare phony goals and dist-for-goals
1428// calls from the module's dist and dists properties.
1429func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod blueprint.Module) []string {
1430	distContributions := a.getDistContributions(ctx, mod)
1431	if distContributions == nil {
1432		return nil
1433	}
1434
1435	return generateDistContributionsForMake(distContributions)
1436}
1437
1438// Compute the contributions that the module makes to the dist.
1439func (a *AndroidMkInfo) getDistContributions(ctx fillInEntriesContext, mod blueprint.Module) *distContributions {
1440	amod := mod.(Module).base()
1441	name := amod.BaseModuleName()
1442
1443	// Collate the set of associated tag/paths available for copying to the dist.
1444	// Start with an empty (nil) set.
1445	var availableTaggedDists TaggedDistFiles
1446
1447	// Then merge in any that are provided explicitly by the module.
1448	if a.DistFiles != nil {
1449		// Merge the DistFiles into the set.
1450		availableTaggedDists = availableTaggedDists.merge(a.DistFiles)
1451	}
1452
1453	// If no paths have been provided for the DefaultDistTag and the output file is
1454	// valid then add that as the default dist path.
1455	if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() {
1456		availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path())
1457	}
1458
1459	info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
1460	// If the distFiles created by GenerateTaggedDistFiles contains paths for the
1461	// DefaultDistTag then that takes priority so delete any existing paths.
1462	if _, ok := info.DistFiles[DefaultDistTag]; ok {
1463		delete(availableTaggedDists, DefaultDistTag)
1464	}
1465
1466	// Finally, merge the distFiles created by GenerateTaggedDistFiles.
1467	availableTaggedDists = availableTaggedDists.merge(info.DistFiles)
1468
1469	if len(availableTaggedDists) == 0 {
1470		// Nothing dist-able for this module.
1471		return nil
1472	}
1473
1474	// Collate the contributions this module makes to the dist.
1475	distContributions := &distContributions{}
1476
1477	if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) {
1478		distContributions.licenseMetadataFile = info.LicenseMetadataFile
1479	}
1480
1481	// Iterate over this module's dist structs, merged from the dist and dists properties.
1482	for _, dist := range amod.Dists() {
1483		// Get the list of goals this dist should be enabled for. e.g. sdk, droidcore
1484		goals := strings.Join(dist.Targets, " ")
1485
1486		// Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map"
1487		var tag string
1488		if dist.Tag == nil {
1489			// If the dist struct does not specify a tag, use the default output files tag.
1490			tag = DefaultDistTag
1491		} else {
1492			tag = *dist.Tag
1493		}
1494
1495		// Get the paths of the output files to be dist'd, represented by the tag.
1496		// Can be an empty list.
1497		tagPaths := availableTaggedDists[tag]
1498		if len(tagPaths) == 0 {
1499			// Nothing to dist for this tag, continue to the next dist.
1500			continue
1501		}
1502
1503		if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) {
1504			errorMessage := "%s: Cannot apply dest/suffix for more than one dist " +
1505				"file for %q goals tag %q in module %s. The list of dist files, " +
1506				"which should have a single element, is:\n%s"
1507			panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths))
1508		}
1509
1510		copiesForGoals := distContributions.getCopiesForGoals(goals)
1511
1512		// Iterate over each path adding a copy instruction to copiesForGoals
1513		for _, path := range tagPaths {
1514			// It's possible that the Path is nil from errant modules. Be defensive here.
1515			if path == nil {
1516				tagName := "default" // for error message readability
1517				if dist.Tag != nil {
1518					tagName = *dist.Tag
1519				}
1520				panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name))
1521			}
1522
1523			dest := filepath.Base(path.String())
1524
1525			if dist.Dest != nil {
1526				var err error
1527				if dest, err = validateSafePath(*dist.Dest); err != nil {
1528					// This was checked in ModuleBase.GenerateBuildActions
1529					panic(err)
1530				}
1531			}
1532
1533			ext := filepath.Ext(dest)
1534			suffix := ""
1535			if dist.Suffix != nil {
1536				suffix = *dist.Suffix
1537			}
1538
1539			productString := ""
1540			if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product {
1541				productString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct())
1542			}
1543
1544			if suffix != "" || productString != "" {
1545				dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext
1546			}
1547
1548			if dist.Dir != nil {
1549				var err error
1550				if dest, err = validateSafePath(*dist.Dir, dest); err != nil {
1551					// This was checked in ModuleBase.GenerateBuildActions
1552					panic(err)
1553				}
1554			}
1555
1556			copiesForGoals.addCopyInstruction(path, dest)
1557		}
1558	}
1559
1560	return distContributions
1561}
1562
1563func deepCopyAndroidMkProviderInfo(providerInfo *AndroidMkProviderInfo) AndroidMkProviderInfo {
1564	info := AndroidMkProviderInfo{
1565		PrimaryInfo: deepCopyAndroidMkInfo(&providerInfo.PrimaryInfo),
1566	}
1567	if len(providerInfo.ExtraInfo) > 0 {
1568		for _, i := range providerInfo.ExtraInfo {
1569			info.ExtraInfo = append(info.ExtraInfo, deepCopyAndroidMkInfo(&i))
1570		}
1571	}
1572	return info
1573}
1574
1575func deepCopyAndroidMkInfo(mkinfo *AndroidMkInfo) AndroidMkInfo {
1576	info := AndroidMkInfo{
1577		Class:        mkinfo.Class,
1578		SubName:      mkinfo.SubName,
1579		OverrideName: mkinfo.OverrideName,
1580		// There is no modification on DistFiles or OutputFile, so no need to
1581		// make their deep copy.
1582		DistFiles:       mkinfo.DistFiles,
1583		OutputFile:      mkinfo.OutputFile,
1584		Disabled:        mkinfo.Disabled,
1585		Include:         mkinfo.Include,
1586		Required:        deepCopyStringSlice(mkinfo.Required),
1587		Host_required:   deepCopyStringSlice(mkinfo.Host_required),
1588		Target_required: deepCopyStringSlice(mkinfo.Target_required),
1589		HeaderStrings:   deepCopyStringSlice(mkinfo.HeaderStrings),
1590		FooterStrings:   deepCopyStringSlice(mkinfo.FooterStrings),
1591		EntryOrder:      deepCopyStringSlice(mkinfo.EntryOrder),
1592	}
1593	info.EntryMap = make(map[string][]string)
1594	for k, v := range mkinfo.EntryMap {
1595		info.EntryMap[k] = deepCopyStringSlice(v)
1596	}
1597
1598	return info
1599}
1600
1601func deepCopyStringSlice(original []string) []string {
1602	result := make([]string, len(original))
1603	copy(result, original)
1604	return result
1605}
1606