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