• 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	"strings"
34
35	"github.com/google/blueprint"
36	"github.com/google/blueprint/bootstrap"
37	"github.com/google/blueprint/pathtools"
38)
39
40func init() {
41	RegisterAndroidMkBuildComponents(InitRegistrationContext)
42}
43
44func RegisterAndroidMkBuildComponents(ctx RegistrationContext) {
45	ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
46}
47
48// Enable androidmk support.
49// * Register the singleton
50// * Configure that we are inside make
51var PrepareForTestWithAndroidMk = GroupFixturePreparers(
52	FixtureRegisterWithContext(RegisterAndroidMkBuildComponents),
53	FixtureModifyConfig(SetKatiEnabledForTests),
54)
55
56// Deprecated: Use AndroidMkEntriesProvider instead, especially if you're not going to use the
57// Custom function. It's easier to use and test.
58type AndroidMkDataProvider interface {
59	AndroidMk() AndroidMkData
60	BaseModuleName() string
61}
62
63type AndroidMkData struct {
64	Class           string
65	SubName         string
66	DistFiles       TaggedDistFiles
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 AndroidMkExtraFunc func(w io.Writer, outputFile Path)
82
83// Interface for modules to declare their Android.mk outputs. Note that every module needs to
84// implement this in order to be included in the final Android-<product_name>.mk output, even if
85// they only need to output the common set of entries without any customizations.
86type AndroidMkEntriesProvider interface {
87	// Returns AndroidMkEntries objects that contain all basic info plus extra customization data
88	// if needed. This is the core func to implement.
89	// Note that one can return multiple objects. For example, java_library may return an additional
90	// AndroidMkEntries object for its hostdex sub-module.
91	AndroidMkEntries() []AndroidMkEntries
92	// Modules don't need to implement this as it's already implemented by ModuleBase.
93	// AndroidMkEntries uses BaseModuleName() instead of ModuleName() because certain modules
94	// e.g. Prebuilts, override the Name() func and return modified names.
95	// If a different name is preferred, use SubName or OverrideName in AndroidMkEntries.
96	BaseModuleName() string
97}
98
99// The core data struct that modules use to provide their Android.mk data.
100type AndroidMkEntries struct {
101	// Android.mk class string, e.g EXECUTABLES, JAVA_LIBRARIES, ETC
102	Class string
103	// Optional suffix to append to the module name. Useful when a module wants to return multiple
104	// AndroidMkEntries objects. For example, when a java_library returns an additional entry for
105	// its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a
106	// different name than the parent's.
107	SubName string
108	// If set, this value overrides the base module name. SubName is still appended.
109	OverrideName string
110	// Dist files to output
111	DistFiles TaggedDistFiles
112	// The output file for Kati to process and/or install. If absent, the module is skipped.
113	OutputFile OptionalPath
114	// If true, the module is skipped and does not appear on the final Android-<product name>.mk
115	// file. Useful when a module needs to be skipped conditionally.
116	Disabled bool
117	// The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk
118	// If not set, $(BUILD_SYSTEM)/prebuilt.mk is used.
119	Include string
120	// Required modules that need to be built and included in the final build output when building
121	// this module.
122	Required []string
123	// Required host modules that need to be built and included in the final build output when
124	// building this module.
125	Host_required []string
126	// Required device modules that need to be built and included in the final build output when
127	// building this module.
128	Target_required []string
129
130	header bytes.Buffer
131	footer bytes.Buffer
132
133	// Funcs to append additional Android.mk entries or modify the common ones. Multiple funcs are
134	// accepted so that common logic can be factored out as a shared func.
135	ExtraEntries []AndroidMkExtraEntriesFunc
136	// Funcs to add extra lines to the module's Android.mk output. Unlike AndroidMkExtraEntriesFunc,
137	// which simply sets Make variable values, this can be used for anything since it can write any
138	// Make statements directly to the final Android-*.mk file.
139	// Primarily used to call macros or declare/update Make targets.
140	ExtraFooters []AndroidMkExtraFootersFunc
141
142	// A map that holds the up-to-date Make variable values. Can be accessed from tests.
143	EntryMap map[string][]string
144	// A list of EntryMap keys in insertion order. This serves a few purposes:
145	// 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this,
146	// the outputted Android-*.mk file may change even though there have been no content changes.
147	// 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR),
148	// without worrying about the variables being mixed up in the actual mk file.
149	// 3. Makes troubleshooting and spotting errors easier.
150	entryOrder []string
151
152	// Provides data typically stored by Context objects that are commonly needed by
153	//AndroidMkEntries objects.
154	entryContext AndroidMkEntriesContext
155}
156
157type AndroidMkEntriesContext interface {
158	Config() Config
159}
160
161type AndroidMkExtraEntriesContext interface {
162	Provider(provider blueprint.ProviderKey) interface{}
163}
164
165type androidMkExtraEntriesContext struct {
166	ctx fillInEntriesContext
167	mod blueprint.Module
168}
169
170func (a *androidMkExtraEntriesContext) Provider(provider blueprint.ProviderKey) interface{} {
171	return a.ctx.ModuleProvider(a.mod, provider)
172}
173
174type AndroidMkExtraEntriesFunc func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries)
175type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string)
176
177// Utility funcs to manipulate Android.mk variable entries.
178
179// SetString sets a Make variable with the given name to the given value.
180func (a *AndroidMkEntries) SetString(name, value string) {
181	if _, ok := a.EntryMap[name]; !ok {
182		a.entryOrder = append(a.entryOrder, name)
183	}
184	a.EntryMap[name] = []string{value}
185}
186
187// SetPath sets a Make variable with the given name to the given path string.
188func (a *AndroidMkEntries) SetPath(name string, path Path) {
189	if _, ok := a.EntryMap[name]; !ok {
190		a.entryOrder = append(a.entryOrder, name)
191	}
192	a.EntryMap[name] = []string{path.String()}
193}
194
195// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid.
196// It is a no-op if the given path is invalid.
197func (a *AndroidMkEntries) SetOptionalPath(name string, path OptionalPath) {
198	if path.Valid() {
199		a.SetPath(name, path.Path())
200	}
201}
202
203// AddPath appends the given path string to a Make variable with the given name.
204func (a *AndroidMkEntries) AddPath(name string, path Path) {
205	if _, ok := a.EntryMap[name]; !ok {
206		a.entryOrder = append(a.entryOrder, name)
207	}
208	a.EntryMap[name] = append(a.EntryMap[name], path.String())
209}
210
211// AddOptionalPath appends the given path string to a Make variable with the given name if it is
212// valid. It is a no-op if the given path is invalid.
213func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) {
214	if path.Valid() {
215		a.AddPath(name, path.Path())
216	}
217}
218
219// SetPaths sets a Make variable with the given name to a slice of the given path strings.
220func (a *AndroidMkEntries) SetPaths(name string, paths Paths) {
221	if _, ok := a.EntryMap[name]; !ok {
222		a.entryOrder = append(a.entryOrder, name)
223	}
224	a.EntryMap[name] = paths.Strings()
225}
226
227// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings
228// only if there are a non-zero amount of paths.
229func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) {
230	if len(paths) > 0 {
231		a.SetPaths(name, paths)
232	}
233}
234
235// AddPaths appends the given path strings to a Make variable with the given name.
236func (a *AndroidMkEntries) AddPaths(name string, paths Paths) {
237	if _, ok := a.EntryMap[name]; !ok {
238		a.entryOrder = append(a.entryOrder, name)
239	}
240	a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...)
241}
242
243// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true.
244// It is a no-op if the given flag is false.
245func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
246	if flag {
247		if _, ok := a.EntryMap[name]; !ok {
248			a.entryOrder = append(a.entryOrder, name)
249		}
250		a.EntryMap[name] = []string{"true"}
251	}
252}
253
254// SetBool sets a Make variable with the given name to if the given bool flag value.
255func (a *AndroidMkEntries) SetBool(name string, flag bool) {
256	if _, ok := a.EntryMap[name]; !ok {
257		a.entryOrder = append(a.entryOrder, name)
258	}
259	if flag {
260		a.EntryMap[name] = []string{"true"}
261	} else {
262		a.EntryMap[name] = []string{"false"}
263	}
264}
265
266// AddStrings appends the given strings to a Make variable with the given name.
267func (a *AndroidMkEntries) AddStrings(name string, value ...string) {
268	if len(value) == 0 {
269		return
270	}
271	if _, ok := a.EntryMap[name]; !ok {
272		a.entryOrder = append(a.entryOrder, name)
273	}
274	a.EntryMap[name] = append(a.EntryMap[name], value...)
275}
276
277// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling
278// for partial MTS test suites.
279func (a *AndroidMkEntries) AddCompatibilityTestSuites(suites ...string) {
280	// MTS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}.
281	// To reduce repetition, if we find a partial MTS test suite without an full MTS test suite,
282	// we add the full test suite to our list.
283	if PrefixInList(suites, "mts-") && !InList("mts", suites) {
284		suites = append(suites, "mts")
285	}
286	a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...)
287}
288
289// The contributions to the dist.
290type distContributions struct {
291	// Path to license metadata file.
292	licenseMetadataFile Path
293	// List of goals and the dist copy instructions.
294	copiesForGoals []*copiesForGoals
295}
296
297// getCopiesForGoals returns a copiesForGoals into which copy instructions that
298// must be processed when building one or more of those goals can be added.
299func (d *distContributions) getCopiesForGoals(goals string) *copiesForGoals {
300	copiesForGoals := &copiesForGoals{goals: goals}
301	d.copiesForGoals = append(d.copiesForGoals, copiesForGoals)
302	return copiesForGoals
303}
304
305// Associates a list of dist copy instructions with a set of goals for which they
306// should be run.
307type copiesForGoals struct {
308	// goals are a space separated list of build targets that will trigger the
309	// copy instructions.
310	goals string
311
312	// A list of instructions to copy a module's output files to somewhere in the
313	// dist directory.
314	copies []distCopy
315}
316
317// Adds a copy instruction.
318func (d *copiesForGoals) addCopyInstruction(from Path, dest string) {
319	d.copies = append(d.copies, distCopy{from, dest})
320}
321
322// Instruction on a path that must be copied into the dist.
323type distCopy struct {
324	// The path to copy from.
325	from Path
326
327	// The destination within the dist directory to copy to.
328	dest string
329}
330
331// Compute the contributions that the module makes to the dist.
332func (a *AndroidMkEntries) getDistContributions(mod blueprint.Module) *distContributions {
333	amod := mod.(Module).base()
334	name := amod.BaseModuleName()
335
336	// Collate the set of associated tag/paths available for copying to the dist.
337	// Start with an empty (nil) set.
338	var availableTaggedDists TaggedDistFiles
339
340	// Then merge in any that are provided explicitly by the module.
341	if a.DistFiles != nil {
342		// Merge the DistFiles into the set.
343		availableTaggedDists = availableTaggedDists.merge(a.DistFiles)
344	}
345
346	// If no paths have been provided for the DefaultDistTag and the output file is
347	// valid then add that as the default dist path.
348	if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() {
349		availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path())
350	}
351
352	// If the distFiles created by GenerateTaggedDistFiles contains paths for the
353	// DefaultDistTag then that takes priority so delete any existing paths.
354	if _, ok := amod.distFiles[DefaultDistTag]; ok {
355		delete(availableTaggedDists, DefaultDistTag)
356	}
357
358	// Finally, merge the distFiles created by GenerateTaggedDistFiles.
359	availableTaggedDists = availableTaggedDists.merge(amod.distFiles)
360
361	if len(availableTaggedDists) == 0 {
362		// Nothing dist-able for this module.
363		return nil
364	}
365
366	// Collate the contributions this module makes to the dist.
367	distContributions := &distContributions{}
368
369	if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) {
370		distContributions.licenseMetadataFile = amod.licenseMetadataFile
371	}
372
373	// Iterate over this module's dist structs, merged from the dist and dists properties.
374	for _, dist := range amod.Dists() {
375		// Get the list of goals this dist should be enabled for. e.g. sdk, droidcore
376		goals := strings.Join(dist.Targets, " ")
377
378		// Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map"
379		var tag string
380		if dist.Tag == nil {
381			// If the dist struct does not specify a tag, use the default output files tag.
382			tag = DefaultDistTag
383		} else {
384			tag = *dist.Tag
385		}
386
387		// Get the paths of the output files to be dist'd, represented by the tag.
388		// Can be an empty list.
389		tagPaths := availableTaggedDists[tag]
390		if len(tagPaths) == 0 {
391			// Nothing to dist for this tag, continue to the next dist.
392			continue
393		}
394
395		if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) {
396			errorMessage := "%s: Cannot apply dest/suffix for more than one dist " +
397				"file for %q goals tag %q in module %s. The list of dist files, " +
398				"which should have a single element, is:\n%s"
399			panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths))
400		}
401
402		copiesForGoals := distContributions.getCopiesForGoals(goals)
403
404		// Iterate over each path adding a copy instruction to copiesForGoals
405		for _, path := range tagPaths {
406			// It's possible that the Path is nil from errant modules. Be defensive here.
407			if path == nil {
408				tagName := "default" // for error message readability
409				if dist.Tag != nil {
410					tagName = *dist.Tag
411				}
412				panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name))
413			}
414
415			dest := filepath.Base(path.String())
416
417			if dist.Dest != nil {
418				var err error
419				if dest, err = validateSafePath(*dist.Dest); err != nil {
420					// This was checked in ModuleBase.GenerateBuildActions
421					panic(err)
422				}
423			}
424
425			ext := filepath.Ext(dest)
426			suffix := ""
427			if dist.Suffix != nil {
428				suffix = *dist.Suffix
429			}
430
431			productString := ""
432			if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product {
433				productString = fmt.Sprintf("_%s", a.entryContext.Config().DeviceProduct())
434			}
435
436			if suffix != "" || productString != "" {
437				dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext
438			}
439
440			if dist.Dir != nil {
441				var err error
442				if dest, err = validateSafePath(*dist.Dir, dest); err != nil {
443					// This was checked in ModuleBase.GenerateBuildActions
444					panic(err)
445				}
446			}
447
448			copiesForGoals.addCopyInstruction(path, dest)
449		}
450	}
451
452	return distContributions
453}
454
455// generateDistContributionsForMake generates make rules that will generate the
456// dist according to the instructions in the supplied distContribution.
457func generateDistContributionsForMake(distContributions *distContributions) []string {
458	var ret []string
459	for _, d := range distContributions.copiesForGoals {
460		ret = append(ret, fmt.Sprintf(".PHONY: %s\n", d.goals))
461		// Create dist-for-goals calls for each of the copy instructions.
462		for _, c := range d.copies {
463			if distContributions.licenseMetadataFile != nil {
464				ret = append(
465					ret,
466					fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))\n",
467						c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String()))
468			}
469			ret = append(
470				ret,
471				fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", d.goals, c.from.String(), c.dest))
472		}
473	}
474
475	return ret
476}
477
478// Compute the list of Make strings to declare phony goals and dist-for-goals
479// calls from the module's dist and dists properties.
480func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
481	distContributions := a.getDistContributions(mod)
482	if distContributions == nil {
483		return nil
484	}
485
486	return generateDistContributionsForMake(distContributions)
487}
488
489// Write the license variables to Make for AndroidMkData.Custom(..) methods that do not call WriteAndroidMkData(..)
490// It's required to propagate the license metadata even for module types that have non-standard interfaces to Make.
491func (a *AndroidMkEntries) WriteLicenseVariables(w io.Writer) {
492	AndroidMkEmitAssignList(w, "LOCAL_LICENSE_KINDS", a.EntryMap["LOCAL_LICENSE_KINDS"])
493	AndroidMkEmitAssignList(w, "LOCAL_LICENSE_CONDITIONS", a.EntryMap["LOCAL_LICENSE_CONDITIONS"])
494	AndroidMkEmitAssignList(w, "LOCAL_NOTICE_FILE", a.EntryMap["LOCAL_NOTICE_FILE"])
495	if pn, ok := a.EntryMap["LOCAL_LICENSE_PACKAGE_NAME"]; ok {
496		AndroidMkEmitAssignList(w, "LOCAL_LICENSE_PACKAGE_NAME", pn)
497	}
498}
499
500// fillInEntries goes through the common variable processing and calls the extra data funcs to
501// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
502type fillInEntriesContext interface {
503	ModuleDir(module blueprint.Module) string
504	ModuleSubDir(module blueprint.Module) string
505	Config() Config
506	ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
507	ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
508	ModuleType(module blueprint.Module) string
509}
510
511func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
512	a.entryContext = ctx
513	a.EntryMap = make(map[string][]string)
514	amod := mod.(Module)
515	base := amod.base()
516	name := base.BaseModuleName()
517	if a.OverrideName != "" {
518		name = a.OverrideName
519	}
520
521	if a.Include == "" {
522		a.Include = "$(BUILD_PREBUILT)"
523	}
524	a.Required = append(a.Required, amod.RequiredModuleNames()...)
525	a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...)
526	a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...)
527
528	for _, distString := range a.GetDistForGoals(mod) {
529		fmt.Fprintf(&a.header, distString)
530	}
531
532	fmt.Fprintf(&a.header, "\ninclude $(CLEAR_VARS)  # type: %s, name: %s, variant: %s\n", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod))
533
534	// Collect make variable assignment entries.
535	a.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
536	a.SetString("LOCAL_MODULE", name+a.SubName)
537	a.AddStrings("LOCAL_LICENSE_KINDS", base.commonProperties.Effective_license_kinds...)
538	a.AddStrings("LOCAL_LICENSE_CONDITIONS", base.commonProperties.Effective_license_conditions...)
539	a.AddStrings("LOCAL_NOTICE_FILE", base.commonProperties.Effective_license_text.Strings()...)
540	// TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ?
541	if base.commonProperties.Effective_package_name != nil {
542		a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *base.commonProperties.Effective_package_name)
543	} else if len(base.commonProperties.Effective_licenses) > 0 {
544		a.SetString("LOCAL_LICENSE_PACKAGE_NAME", strings.Join(base.commonProperties.Effective_licenses, " "))
545	}
546	a.SetString("LOCAL_MODULE_CLASS", a.Class)
547	a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
548	a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
549	a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
550	a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
551	a.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod))
552
553	// If the install rule was generated by Soong tell Make about it.
554	if len(base.katiInstalls) > 0 {
555		// Assume the primary install file is last since it probably needs to depend on any other
556		// installed files.  If that is not the case we can add a method to specify the primary
557		// installed file.
558		a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", base.katiInstalls[len(base.katiInstalls)-1].to)
559		a.SetString("LOCAL_SOONG_INSTALL_PAIRS", base.katiInstalls.BuiltInstalled())
560		a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths())
561	}
562
563	if am, ok := mod.(ApexModule); ok {
564		a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
565	}
566
567	archStr := base.Arch().ArchType.String()
568	host := false
569	switch base.Os().Class {
570	case Host:
571		if base.Target().HostCross {
572			// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
573			if base.Arch().ArchType != Common {
574				a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
575			}
576		} else {
577			// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
578			if base.Arch().ArchType != Common {
579				a.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
580			}
581		}
582		host = true
583	case Device:
584		// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
585		if base.Arch().ArchType != Common {
586			if base.Target().NativeBridge {
587				hostArchStr := base.Target().NativeBridgeHostArchName
588				if hostArchStr != "" {
589					a.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
590				}
591			} else {
592				a.SetString("LOCAL_MODULE_TARGET_ARCH", archStr)
593			}
594		}
595
596		if !base.InVendorRamdisk() {
597			a.AddPaths("LOCAL_FULL_INIT_RC", base.initRcPaths)
598		}
599		if len(base.vintfFragmentsPaths) > 0 {
600			a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", base.vintfFragmentsPaths)
601		}
602		a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary))
603		if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) {
604			a.SetString("LOCAL_VENDOR_MODULE", "true")
605		}
606		a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific))
607		a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific))
608		a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific))
609		if base.commonProperties.Owner != nil {
610			a.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner)
611		}
612	}
613
614	if host {
615		makeOs := base.Os().String()
616		if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl {
617			makeOs = "linux"
618		}
619		a.SetString("LOCAL_MODULE_HOST_OS", makeOs)
620		a.SetString("LOCAL_IS_HOST_MODULE", "true")
621	}
622
623	prefix := ""
624	if base.ArchSpecific() {
625		switch base.Os().Class {
626		case Host:
627			if base.Target().HostCross {
628				prefix = "HOST_CROSS_"
629			} else {
630				prefix = "HOST_"
631			}
632		case Device:
633			prefix = "TARGET_"
634
635		}
636
637		if base.Arch().ArchType != ctx.Config().Targets[base.Os()][0].Arch.ArchType {
638			prefix = "2ND_" + prefix
639		}
640	}
641
642	if ctx.ModuleHasProvider(mod, LicenseMetadataProvider) {
643		licenseMetadata := ctx.ModuleProvider(mod, LicenseMetadataProvider).(*LicenseMetadataInfo)
644		a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
645	}
646
647	extraCtx := &androidMkExtraEntriesContext{
648		ctx: ctx,
649		mod: mod,
650	}
651
652	for _, extra := range a.ExtraEntries {
653		extra(extraCtx, a)
654	}
655
656	// Write to footer.
657	fmt.Fprintln(&a.footer, "include "+a.Include)
658	blueprintDir := ctx.ModuleDir(mod)
659	for _, footerFunc := range a.ExtraFooters {
660		footerFunc(&a.footer, name, prefix, blueprintDir)
661	}
662}
663
664// write  flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
665// given Writer object.
666func (a *AndroidMkEntries) write(w io.Writer) {
667	if a.Disabled {
668		return
669	}
670
671	if !a.OutputFile.Valid() {
672		return
673	}
674
675	w.Write(a.header.Bytes())
676	for _, name := range a.entryOrder {
677		AndroidMkEmitAssignList(w, name, a.EntryMap[name])
678	}
679	w.Write(a.footer.Bytes())
680}
681
682func (a *AndroidMkEntries) FooterLinesForTests() []string {
683	return strings.Split(string(a.footer.Bytes()), "\n")
684}
685
686// AndroidMkSingleton is a singleton to collect Android.mk data from all modules and dump them into
687// the final Android-<product_name>.mk file output.
688func AndroidMkSingleton() Singleton {
689	return &androidMkSingleton{}
690}
691
692type androidMkSingleton struct{}
693
694func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
695	// Skip if Soong wasn't invoked from Make.
696	if !ctx.Config().KatiEnabled() {
697		return
698	}
699
700	var androidMkModulesList []blueprint.Module
701
702	ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
703		androidMkModulesList = append(androidMkModulesList, module)
704	})
705
706	// Sort the module list by the module names to eliminate random churns, which may erroneously
707	// invoke additional build processes.
708	sort.SliceStable(androidMkModulesList, func(i, j int) bool {
709		return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
710	})
711
712	transMk := PathForOutput(ctx, "Android"+String(ctx.Config().productVariables.Make_suffix)+".mk")
713	if ctx.Failed() {
714		return
715	}
716
717	err := translateAndroidMk(ctx, absolutePath(transMk.String()), androidMkModulesList)
718	if err != nil {
719		ctx.Errorf(err.Error())
720	}
721
722	ctx.Build(pctx, BuildParams{
723		Rule:   blueprint.Phony,
724		Output: transMk,
725	})
726}
727
728func translateAndroidMk(ctx SingletonContext, absMkFile string, mods []blueprint.Module) error {
729	buf := &bytes.Buffer{}
730
731	fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
732
733	typeStats := make(map[string]int)
734	for _, mod := range mods {
735		err := translateAndroidMkModule(ctx, buf, mod)
736		if err != nil {
737			os.Remove(absMkFile)
738			return err
739		}
740
741		if amod, ok := mod.(Module); ok && ctx.PrimaryModule(amod) == amod {
742			typeStats[ctx.ModuleType(amod)] += 1
743		}
744	}
745
746	keys := []string{}
747	fmt.Fprintln(buf, "\nSTATS.SOONG_MODULE_TYPE :=")
748	for k := range typeStats {
749		keys = append(keys, k)
750	}
751	sort.Strings(keys)
752	for _, mod_type := range keys {
753		fmt.Fprintln(buf, "STATS.SOONG_MODULE_TYPE +=", mod_type)
754		fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type])
755	}
756
757	return pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666)
758}
759
760func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.Module) error {
761	defer func() {
762		if r := recover(); r != nil {
763			panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s",
764				r, ctx.ModuleName(mod), ctx.ModuleSubDir(mod)))
765		}
766	}()
767
768	// Additional cases here require review for correct license propagation to make.
769	switch x := mod.(type) {
770	case AndroidMkDataProvider:
771		return translateAndroidModule(ctx, w, mod, x)
772	case bootstrap.GoBinaryTool:
773		return translateGoBinaryModule(ctx, w, mod, x)
774	case AndroidMkEntriesProvider:
775		return translateAndroidMkEntriesModule(ctx, w, mod, x)
776	default:
777		// Not exported to make so no make variables to set.
778		return nil
779	}
780}
781
782// A simple, special Android.mk entry output func to make it possible to build blueprint tools using
783// m by making them phony targets.
784func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
785	goBinary bootstrap.GoBinaryTool) error {
786
787	name := ctx.ModuleName(mod)
788	fmt.Fprintln(w, ".PHONY:", name)
789	fmt.Fprintln(w, name+":", goBinary.InstallPath())
790	fmt.Fprintln(w, "")
791	// Assuming no rules in make include go binaries in distributables.
792	// If the assumption is wrong, make will fail to build without the necessary .meta_lic and .meta_module files.
793	// In that case, add the targets and rules here to build a .meta_lic file for `name` and a .meta_module for
794	// `goBinary.InstallPath()` pointing to the `name`.meta_lic file.
795
796	return nil
797}
798
799func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod blueprint.Module) {
800	// Get the preamble content through AndroidMkEntries logic.
801	data.Entries = AndroidMkEntries{
802		Class:           data.Class,
803		SubName:         data.SubName,
804		DistFiles:       data.DistFiles,
805		OutputFile:      data.OutputFile,
806		Disabled:        data.Disabled,
807		Include:         data.Include,
808		Required:        data.Required,
809		Host_required:   data.Host_required,
810		Target_required: data.Target_required,
811	}
812	data.Entries.fillInEntries(ctx, mod)
813
814	// copy entries back to data since it is used in Custom
815	data.Required = data.Entries.Required
816	data.Host_required = data.Entries.Host_required
817	data.Target_required = data.Entries.Target_required
818}
819
820// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
821// instead.
822func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
823	provider AndroidMkDataProvider) error {
824
825	amod := mod.(Module).base()
826	if shouldSkipAndroidMkProcessing(amod) {
827		return nil
828	}
829
830	data := provider.AndroidMk()
831	if data.Include == "" {
832		data.Include = "$(BUILD_PREBUILT)"
833	}
834
835	data.fillInData(ctx, mod)
836
837	prefix := ""
838	if amod.ArchSpecific() {
839		switch amod.Os().Class {
840		case Host:
841			if amod.Target().HostCross {
842				prefix = "HOST_CROSS_"
843			} else {
844				prefix = "HOST_"
845			}
846		case Device:
847			prefix = "TARGET_"
848
849		}
850
851		if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType {
852			prefix = "2ND_" + prefix
853		}
854	}
855
856	name := provider.BaseModuleName()
857	blueprintDir := filepath.Dir(ctx.BlueprintFile(mod))
858
859	if data.Custom != nil {
860		// List of module types allowed to use .Custom(...)
861		// Additions to the list require careful review for proper license handling.
862		switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type
863		case "*aidl.aidlApi": // writes non-custom before adding .phony
864		case "*aidl.aidlMapping": // writes non-custom before adding .phony
865		case "*android.customModule": // appears in tests only
866		case "*android_sdk.sdkRepoHost": // doesn't go through base_rules
867		case "*apex.apexBundle": // license properties written
868		case "*bpf.bpf": // license properties written (both for module and objs)
869		case "*genrule.Module": // writes non-custom before adding .phony
870		case "*java.SystemModules": // doesn't go through base_rules
871		case "*java.systemModulesImport": // doesn't go through base_rules
872		case "*phony.phony": // license properties written
873		case "*selinux.selinuxContextsModule": // license properties written
874		case "*sysprop.syspropLibrary": // license properties written
875		default:
876			if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") {
877				return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod))
878			}
879		}
880		data.Custom(w, name, prefix, blueprintDir, data)
881	} else {
882		WriteAndroidMkData(w, data)
883	}
884
885	return nil
886}
887
888// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
889// instead.
890func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
891	if data.Disabled {
892		return
893	}
894
895	if !data.OutputFile.Valid() {
896		return
897	}
898
899	// write preamble via Entries
900	data.Entries.footer = bytes.Buffer{}
901	data.Entries.write(w)
902
903	for _, extra := range data.Extra {
904		extra(w, data.OutputFile.Path())
905	}
906
907	fmt.Fprintln(w, "include "+data.Include)
908}
909
910func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
911	provider AndroidMkEntriesProvider) error {
912	if shouldSkipAndroidMkProcessing(mod.(Module).base()) {
913		return nil
914	}
915
916	// Any new or special cases here need review to verify correct propagation of license information.
917	for _, entries := range provider.AndroidMkEntries() {
918		entries.fillInEntries(ctx, mod)
919		entries.write(w)
920	}
921
922	return nil
923}
924
925func ShouldSkipAndroidMkProcessing(module Module) bool {
926	return shouldSkipAndroidMkProcessing(module.base())
927}
928
929func shouldSkipAndroidMkProcessing(module *ModuleBase) bool {
930	if !module.commonProperties.NamespaceExportedToMake {
931		// TODO(jeffrygaston) do we want to validate that there are no modules being
932		// exported to Kati that depend on this module?
933		return true
934	}
935
936	// On Mac, only expose host darwin modules to Make, as that's all we claim to support.
937	// In reality, some of them depend on device-built (Java) modules, so we can't disable all
938	// device modules in Soong, but we can hide them from Make (and thus the build user interface)
939	if runtime.GOOS == "darwin" && module.Os() != Darwin {
940		return true
941	}
942
943	// Only expose the primary Darwin target, as Make does not understand Darwin+Arm64
944	if module.Os() == Darwin && module.Target().HostCross {
945		return true
946	}
947
948	return !module.Enabled() ||
949		module.commonProperties.HideFromMake ||
950		// Make does not understand LinuxBionic
951		module.Os() == LinuxBionic ||
952		// Make does not understand LinuxMusl, except when we are building with USE_HOST_MUSL=true
953		// and all host binaries are LinuxMusl
954		(module.Os() == LinuxMusl && module.Target().HostCross)
955}
956
957// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how
958// to use this func.
959func AndroidMkDataPaths(data []DataPath) []string {
960	var testFiles []string
961	for _, d := range data {
962		rel := d.SrcPath.Rel()
963		path := d.SrcPath.String()
964		// LOCAL_TEST_DATA requires the rel portion of the path to be removed from the path.
965		if !strings.HasSuffix(path, rel) {
966			panic(fmt.Errorf("path %q does not end with %q", path, rel))
967		}
968		path = strings.TrimSuffix(path, rel)
969		testFileString := path + ":" + rel
970		if len(d.RelativeInstallPath) > 0 {
971			testFileString += ":" + d.RelativeInstallPath
972		}
973		testFiles = append(testFiles, testFileString)
974	}
975	return testFiles
976}
977
978// AndroidMkEmitAssignList emits the line
979//
980//	VAR := ITEM ...
981//
982// Items are the elements to the given set of lists
983// If all the passed lists are empty, no line will be emitted
984func AndroidMkEmitAssignList(w io.Writer, varName string, lists ...[]string) {
985	doPrint := false
986	for _, l := range lists {
987		if doPrint = len(l) > 0; doPrint {
988			break
989		}
990	}
991	if !doPrint {
992		return
993	}
994	fmt.Fprint(w, varName, " :=")
995	for _, l := range lists {
996		for _, item := range l {
997			fmt.Fprint(w, " ", item)
998		}
999	}
1000	fmt.Fprintln(w)
1001}
1002