• 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	// List of goals and the dist copy instructions.
292	copiesForGoals []*copiesForGoals
293}
294
295// getCopiesForGoals returns a copiesForGoals into which copy instructions that
296// must be processed when building one or more of those goals can be added.
297func (d *distContributions) getCopiesForGoals(goals string) *copiesForGoals {
298	copiesForGoals := &copiesForGoals{goals: goals}
299	d.copiesForGoals = append(d.copiesForGoals, copiesForGoals)
300	return copiesForGoals
301}
302
303// Associates a list of dist copy instructions with a set of goals for which they
304// should be run.
305type copiesForGoals struct {
306	// goals are a space separated list of build targets that will trigger the
307	// copy instructions.
308	goals string
309
310	// A list of instructions to copy a module's output files to somewhere in the
311	// dist directory.
312	copies []distCopy
313}
314
315// Adds a copy instruction.
316func (d *copiesForGoals) addCopyInstruction(from Path, dest string) {
317	d.copies = append(d.copies, distCopy{from, dest})
318}
319
320// Instruction on a path that must be copied into the dist.
321type distCopy struct {
322	// The path to copy from.
323	from Path
324
325	// The destination within the dist directory to copy to.
326	dest string
327}
328
329// Compute the contributions that the module makes to the dist.
330func (a *AndroidMkEntries) getDistContributions(mod blueprint.Module) *distContributions {
331	amod := mod.(Module).base()
332	name := amod.BaseModuleName()
333
334	// Collate the set of associated tag/paths available for copying to the dist.
335	// Start with an empty (nil) set.
336	var availableTaggedDists TaggedDistFiles
337
338	// Then merge in any that are provided explicitly by the module.
339	if a.DistFiles != nil {
340		// Merge the DistFiles into the set.
341		availableTaggedDists = availableTaggedDists.merge(a.DistFiles)
342	}
343
344	// If no paths have been provided for the DefaultDistTag and the output file is
345	// valid then add that as the default dist path.
346	if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() {
347		availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path())
348	}
349
350	// If the distFiles created by GenerateTaggedDistFiles contains paths for the
351	// DefaultDistTag then that takes priority so delete any existing paths.
352	if _, ok := amod.distFiles[DefaultDistTag]; ok {
353		delete(availableTaggedDists, DefaultDistTag)
354	}
355
356	// Finally, merge the distFiles created by GenerateTaggedDistFiles.
357	availableTaggedDists = availableTaggedDists.merge(amod.distFiles)
358
359	if len(availableTaggedDists) == 0 {
360		// Nothing dist-able for this module.
361		return nil
362	}
363
364	// Collate the contributions this module makes to the dist.
365	distContributions := &distContributions{}
366
367	// Iterate over this module's dist structs, merged from the dist and dists properties.
368	for _, dist := range amod.Dists() {
369		// Get the list of goals this dist should be enabled for. e.g. sdk, droidcore
370		goals := strings.Join(dist.Targets, " ")
371
372		// Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map"
373		var tag string
374		if dist.Tag == nil {
375			// If the dist struct does not specify a tag, use the default output files tag.
376			tag = DefaultDistTag
377		} else {
378			tag = *dist.Tag
379		}
380
381		// Get the paths of the output files to be dist'd, represented by the tag.
382		// Can be an empty list.
383		tagPaths := availableTaggedDists[tag]
384		if len(tagPaths) == 0 {
385			// Nothing to dist for this tag, continue to the next dist.
386			continue
387		}
388
389		if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) {
390			errorMessage := "%s: Cannot apply dest/suffix for more than one dist " +
391				"file for %q goals tag %q in module %s. The list of dist files, " +
392				"which should have a single element, is:\n%s"
393			panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths))
394		}
395
396		copiesForGoals := distContributions.getCopiesForGoals(goals)
397
398		// Iterate over each path adding a copy instruction to copiesForGoals
399		for _, path := range tagPaths {
400			// It's possible that the Path is nil from errant modules. Be defensive here.
401			if path == nil {
402				tagName := "default" // for error message readability
403				if dist.Tag != nil {
404					tagName = *dist.Tag
405				}
406				panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name))
407			}
408
409			dest := filepath.Base(path.String())
410
411			if dist.Dest != nil {
412				var err error
413				if dest, err = validateSafePath(*dist.Dest); err != nil {
414					// This was checked in ModuleBase.GenerateBuildActions
415					panic(err)
416				}
417			}
418
419			ext := filepath.Ext(dest)
420			suffix := ""
421			if dist.Suffix != nil {
422				suffix = *dist.Suffix
423			}
424
425			productString := ""
426			if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product {
427				productString = fmt.Sprintf("_%s", a.entryContext.Config().DeviceProduct())
428			}
429
430			if suffix != "" || productString != "" {
431				dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext
432			}
433
434			if dist.Dir != nil {
435				var err error
436				if dest, err = validateSafePath(*dist.Dir, dest); err != nil {
437					// This was checked in ModuleBase.GenerateBuildActions
438					panic(err)
439				}
440			}
441
442			copiesForGoals.addCopyInstruction(path, dest)
443		}
444	}
445
446	return distContributions
447}
448
449// generateDistContributionsForMake generates make rules that will generate the
450// dist according to the instructions in the supplied distContribution.
451func generateDistContributionsForMake(distContributions *distContributions) []string {
452	var ret []string
453	for _, d := range distContributions.copiesForGoals {
454		ret = append(ret, fmt.Sprintf(".PHONY: %s\n", d.goals))
455		// Create dist-for-goals calls for each of the copy instructions.
456		for _, c := range d.copies {
457			ret = append(
458				ret,
459				fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", d.goals, c.from.String(), c.dest))
460		}
461	}
462
463	return ret
464}
465
466// Compute the list of Make strings to declare phony goals and dist-for-goals
467// calls from the module's dist and dists properties.
468func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
469	distContributions := a.getDistContributions(mod)
470	if distContributions == nil {
471		return nil
472	}
473
474	return generateDistContributionsForMake(distContributions)
475}
476
477// Write the license variables to Make for AndroidMkData.Custom(..) methods that do not call WriteAndroidMkData(..)
478// It's required to propagate the license metadata even for module types that have non-standard interfaces to Make.
479func (a *AndroidMkEntries) WriteLicenseVariables(w io.Writer) {
480	fmt.Fprintln(w, "LOCAL_LICENSE_KINDS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_KINDS"], " "))
481	fmt.Fprintln(w, "LOCAL_LICENSE_CONDITIONS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_CONDITIONS"], " "))
482	fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(a.EntryMap["LOCAL_NOTICE_FILE"], " "))
483	if pn, ok := a.EntryMap["LOCAL_LICENSE_PACKAGE_NAME"]; ok {
484		fmt.Fprintln(w, "LOCAL_LICENSE_PACKAGE_NAME :=", strings.Join(pn, " "))
485	}
486}
487
488// fillInEntries goes through the common variable processing and calls the extra data funcs to
489// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
490type fillInEntriesContext interface {
491	ModuleDir(module blueprint.Module) string
492	Config() Config
493	ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
494	ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
495}
496
497func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
498	a.entryContext = ctx
499	a.EntryMap = make(map[string][]string)
500	amod := mod.(Module)
501	base := amod.base()
502	name := base.BaseModuleName()
503	if a.OverrideName != "" {
504		name = a.OverrideName
505	}
506
507	if a.Include == "" {
508		a.Include = "$(BUILD_PREBUILT)"
509	}
510	a.Required = append(a.Required, amod.RequiredModuleNames()...)
511	a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...)
512	a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...)
513
514	for _, distString := range a.GetDistForGoals(mod) {
515		fmt.Fprintf(&a.header, distString)
516	}
517
518	fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)")
519
520	// Collect make variable assignment entries.
521	a.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
522	a.SetString("LOCAL_MODULE", name+a.SubName)
523	a.AddStrings("LOCAL_LICENSE_KINDS", base.commonProperties.Effective_license_kinds...)
524	a.AddStrings("LOCAL_LICENSE_CONDITIONS", base.commonProperties.Effective_license_conditions...)
525	a.AddStrings("LOCAL_NOTICE_FILE", base.commonProperties.Effective_license_text.Strings()...)
526	// TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ?
527	if base.commonProperties.Effective_package_name != nil {
528		a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *base.commonProperties.Effective_package_name)
529	} else if len(base.commonProperties.Effective_licenses) > 0 {
530		a.SetString("LOCAL_LICENSE_PACKAGE_NAME", strings.Join(base.commonProperties.Effective_licenses, " "))
531	}
532	a.SetString("LOCAL_MODULE_CLASS", a.Class)
533	a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
534	a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
535	a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
536	a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
537
538	// If the install rule was generated by Soong tell Make about it.
539	if len(base.katiInstalls) > 0 {
540		// Assume the primary install file is last since it probably needs to depend on any other
541		// installed files.  If that is not the case we can add a method to specify the primary
542		// installed file.
543		a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", base.katiInstalls[len(base.katiInstalls)-1].to)
544		a.SetString("LOCAL_SOONG_INSTALL_PAIRS", base.katiInstalls.BuiltInstalled())
545		a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths())
546	}
547
548	if am, ok := mod.(ApexModule); ok {
549		a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
550	}
551
552	archStr := base.Arch().ArchType.String()
553	host := false
554	switch base.Os().Class {
555	case Host:
556		if base.Target().HostCross {
557			// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
558			if base.Arch().ArchType != Common {
559				a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
560			}
561		} else {
562			// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
563			if base.Arch().ArchType != Common {
564				a.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
565			}
566		}
567		host = true
568	case Device:
569		// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
570		if base.Arch().ArchType != Common {
571			if base.Target().NativeBridge {
572				hostArchStr := base.Target().NativeBridgeHostArchName
573				if hostArchStr != "" {
574					a.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
575				}
576			} else {
577				a.SetString("LOCAL_MODULE_TARGET_ARCH", archStr)
578			}
579		}
580
581		if !base.InVendorRamdisk() {
582			a.AddPaths("LOCAL_FULL_INIT_RC", base.initRcPaths)
583		}
584		if len(base.vintfFragmentsPaths) > 0 {
585			a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", base.vintfFragmentsPaths)
586		}
587		a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary))
588		if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) {
589			a.SetString("LOCAL_VENDOR_MODULE", "true")
590		}
591		a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific))
592		a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific))
593		a.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific))
594		if base.commonProperties.Owner != nil {
595			a.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner)
596		}
597	}
598
599	if len(base.noticeFiles) > 0 {
600		a.SetString("LOCAL_NOTICE_FILE", strings.Join(base.noticeFiles.Strings(), " "))
601	}
602
603	if host {
604		makeOs := base.Os().String()
605		if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl {
606			makeOs = "linux"
607		}
608		a.SetString("LOCAL_MODULE_HOST_OS", makeOs)
609		a.SetString("LOCAL_IS_HOST_MODULE", "true")
610	}
611
612	prefix := ""
613	if base.ArchSpecific() {
614		switch base.Os().Class {
615		case Host:
616			if base.Target().HostCross {
617				prefix = "HOST_CROSS_"
618			} else {
619				prefix = "HOST_"
620			}
621		case Device:
622			prefix = "TARGET_"
623
624		}
625
626		if base.Arch().ArchType != ctx.Config().Targets[base.Os()][0].Arch.ArchType {
627			prefix = "2ND_" + prefix
628		}
629	}
630
631	if ctx.ModuleHasProvider(mod, LicenseMetadataProvider) {
632		licenseMetadata := ctx.ModuleProvider(mod, LicenseMetadataProvider).(*LicenseMetadataInfo)
633		a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
634	}
635
636	extraCtx := &androidMkExtraEntriesContext{
637		ctx: ctx,
638		mod: mod,
639	}
640
641	for _, extra := range a.ExtraEntries {
642		extra(extraCtx, a)
643	}
644
645	// Write to footer.
646	fmt.Fprintln(&a.footer, "include "+a.Include)
647	blueprintDir := ctx.ModuleDir(mod)
648	for _, footerFunc := range a.ExtraFooters {
649		footerFunc(&a.footer, name, prefix, blueprintDir)
650	}
651}
652
653// write  flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
654// given Writer object.
655func (a *AndroidMkEntries) write(w io.Writer) {
656	if a.Disabled {
657		return
658	}
659
660	if !a.OutputFile.Valid() {
661		return
662	}
663
664	w.Write(a.header.Bytes())
665	for _, name := range a.entryOrder {
666		fmt.Fprintln(w, name+" := "+strings.Join(a.EntryMap[name], " "))
667	}
668	w.Write(a.footer.Bytes())
669}
670
671func (a *AndroidMkEntries) FooterLinesForTests() []string {
672	return strings.Split(string(a.footer.Bytes()), "\n")
673}
674
675// AndroidMkSingleton is a singleton to collect Android.mk data from all modules and dump them into
676// the final Android-<product_name>.mk file output.
677func AndroidMkSingleton() Singleton {
678	return &androidMkSingleton{}
679}
680
681type androidMkSingleton struct{}
682
683func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
684	// Skip if Soong wasn't invoked from Make.
685	if !ctx.Config().KatiEnabled() {
686		return
687	}
688
689	var androidMkModulesList []blueprint.Module
690
691	ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
692		androidMkModulesList = append(androidMkModulesList, module)
693	})
694
695	// Sort the module list by the module names to eliminate random churns, which may erroneously
696	// invoke additional build processes.
697	sort.SliceStable(androidMkModulesList, func(i, j int) bool {
698		return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
699	})
700
701	transMk := PathForOutput(ctx, "Android"+String(ctx.Config().productVariables.Make_suffix)+".mk")
702	if ctx.Failed() {
703		return
704	}
705
706	err := translateAndroidMk(ctx, absolutePath(transMk.String()), androidMkModulesList)
707	if err != nil {
708		ctx.Errorf(err.Error())
709	}
710
711	ctx.Build(pctx, BuildParams{
712		Rule:   blueprint.Phony,
713		Output: transMk,
714	})
715}
716
717func translateAndroidMk(ctx SingletonContext, absMkFile string, mods []blueprint.Module) error {
718	buf := &bytes.Buffer{}
719
720	fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
721
722	typeStats := make(map[string]int)
723	for _, mod := range mods {
724		err := translateAndroidMkModule(ctx, buf, mod)
725		if err != nil {
726			os.Remove(absMkFile)
727			return err
728		}
729
730		if amod, ok := mod.(Module); ok && ctx.PrimaryModule(amod) == amod {
731			typeStats[ctx.ModuleType(amod)] += 1
732		}
733	}
734
735	keys := []string{}
736	fmt.Fprintln(buf, "\nSTATS.SOONG_MODULE_TYPE :=")
737	for k := range typeStats {
738		keys = append(keys, k)
739	}
740	sort.Strings(keys)
741	for _, mod_type := range keys {
742		fmt.Fprintln(buf, "STATS.SOONG_MODULE_TYPE +=", mod_type)
743		fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type])
744	}
745
746	return pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666)
747}
748
749func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.Module) error {
750	defer func() {
751		if r := recover(); r != nil {
752			panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s",
753				r, ctx.ModuleName(mod), ctx.ModuleSubDir(mod)))
754		}
755	}()
756
757	// Additional cases here require review for correct license propagation to make.
758	switch x := mod.(type) {
759	case AndroidMkDataProvider:
760		return translateAndroidModule(ctx, w, mod, x)
761	case bootstrap.GoBinaryTool:
762		return translateGoBinaryModule(ctx, w, mod, x)
763	case AndroidMkEntriesProvider:
764		return translateAndroidMkEntriesModule(ctx, w, mod, x)
765	default:
766		// Not exported to make so no make variables to set.
767		return nil
768	}
769}
770
771// A simple, special Android.mk entry output func to make it possible to build blueprint tools using
772// m by making them phony targets.
773func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
774	goBinary bootstrap.GoBinaryTool) error {
775
776	name := ctx.ModuleName(mod)
777	fmt.Fprintln(w, ".PHONY:", name)
778	fmt.Fprintln(w, name+":", goBinary.InstallPath())
779	fmt.Fprintln(w, "")
780	// Assuming no rules in make include go binaries in distributables.
781	// If the assumption is wrong, make will fail to build without the necessary .meta_lic and .meta_module files.
782	// In that case, add the targets and rules here to build a .meta_lic file for `name` and a .meta_module for
783	// `goBinary.InstallPath()` pointing to the `name`.meta_lic file.
784
785	return nil
786}
787
788func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod blueprint.Module) {
789	// Get the preamble content through AndroidMkEntries logic.
790	data.Entries = AndroidMkEntries{
791		Class:           data.Class,
792		SubName:         data.SubName,
793		DistFiles:       data.DistFiles,
794		OutputFile:      data.OutputFile,
795		Disabled:        data.Disabled,
796		Include:         data.Include,
797		Required:        data.Required,
798		Host_required:   data.Host_required,
799		Target_required: data.Target_required,
800	}
801	data.Entries.fillInEntries(ctx, mod)
802
803	// copy entries back to data since it is used in Custom
804	data.Required = data.Entries.Required
805	data.Host_required = data.Entries.Host_required
806	data.Target_required = data.Entries.Target_required
807}
808
809// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
810// instead.
811func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
812	provider AndroidMkDataProvider) error {
813
814	amod := mod.(Module).base()
815	if shouldSkipAndroidMkProcessing(amod) {
816		return nil
817	}
818
819	data := provider.AndroidMk()
820	if data.Include == "" {
821		data.Include = "$(BUILD_PREBUILT)"
822	}
823
824	data.fillInData(ctx, mod)
825
826	prefix := ""
827	if amod.ArchSpecific() {
828		switch amod.Os().Class {
829		case Host:
830			if amod.Target().HostCross {
831				prefix = "HOST_CROSS_"
832			} else {
833				prefix = "HOST_"
834			}
835		case Device:
836			prefix = "TARGET_"
837
838		}
839
840		if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType {
841			prefix = "2ND_" + prefix
842		}
843	}
844
845	name := provider.BaseModuleName()
846	blueprintDir := filepath.Dir(ctx.BlueprintFile(mod))
847
848	if data.Custom != nil {
849		// List of module types allowed to use .Custom(...)
850		// Additions to the list require careful review for proper license handling.
851		switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type
852		case "*aidl.aidlApi": // writes non-custom before adding .phony
853		case "*aidl.aidlMapping": // writes non-custom before adding .phony
854		case "*android.customModule": // appears in tests only
855		case "*android_sdk.sdkRepoHost": // doesn't go through base_rules
856		case "*apex.apexBundle": // license properties written
857		case "*bpf.bpf": // license properties written (both for module and objs)
858		case "*genrule.Module": // writes non-custom before adding .phony
859		case "*java.SystemModules": // doesn't go through base_rules
860		case "*java.systemModulesImport": // doesn't go through base_rules
861		case "*phony.phony": // license properties written
862		case "*selinux.selinuxContextsModule": // license properties written
863		case "*sysprop.syspropLibrary": // license properties written
864		default:
865			if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") {
866				return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod))
867			}
868		}
869		data.Custom(w, name, prefix, blueprintDir, data)
870	} else {
871		WriteAndroidMkData(w, data)
872	}
873
874	return nil
875}
876
877// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
878// instead.
879func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
880	if data.Disabled {
881		return
882	}
883
884	if !data.OutputFile.Valid() {
885		return
886	}
887
888	// write preamble via Entries
889	data.Entries.footer = bytes.Buffer{}
890	data.Entries.write(w)
891
892	for _, extra := range data.Extra {
893		extra(w, data.OutputFile.Path())
894	}
895
896	fmt.Fprintln(w, "include "+data.Include)
897}
898
899func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
900	provider AndroidMkEntriesProvider) error {
901	if shouldSkipAndroidMkProcessing(mod.(Module).base()) {
902		return nil
903	}
904
905	// Any new or special cases here need review to verify correct propagation of license information.
906	for _, entries := range provider.AndroidMkEntries() {
907		entries.fillInEntries(ctx, mod)
908		entries.write(w)
909	}
910
911	return nil
912}
913
914func ShouldSkipAndroidMkProcessing(module Module) bool {
915	return shouldSkipAndroidMkProcessing(module.base())
916}
917
918func shouldSkipAndroidMkProcessing(module *ModuleBase) bool {
919	if !module.commonProperties.NamespaceExportedToMake {
920		// TODO(jeffrygaston) do we want to validate that there are no modules being
921		// exported to Kati that depend on this module?
922		return true
923	}
924
925	// On Mac, only expose host darwin modules to Make, as that's all we claim to support.
926	// In reality, some of them depend on device-built (Java) modules, so we can't disable all
927	// device modules in Soong, but we can hide them from Make (and thus the build user interface)
928	if runtime.GOOS == "darwin" && module.Os() != Darwin {
929		return true
930	}
931
932	// Only expose the primary Darwin target, as Make does not understand Darwin+Arm64
933	if module.Os() == Darwin && module.Target().HostCross {
934		return true
935	}
936
937	return !module.Enabled() ||
938		module.commonProperties.HideFromMake ||
939		// Make does not understand LinuxBionic
940		module.Os() == LinuxBionic
941}
942
943// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how
944// to use this func.
945func AndroidMkDataPaths(data []DataPath) []string {
946	var testFiles []string
947	for _, d := range data {
948		rel := d.SrcPath.Rel()
949		path := d.SrcPath.String()
950		// LOCAL_TEST_DATA requires the rel portion of the path to be removed from the path.
951		if !strings.HasSuffix(path, rel) {
952			panic(fmt.Errorf("path %q does not end with %q", path, rel))
953		}
954		path = strings.TrimSuffix(path, rel)
955		testFileString := path + ":" + rel
956		if len(d.RelativeInstallPath) > 0 {
957			testFileString += ":" + d.RelativeInstallPath
958		}
959		testFiles = append(testFiles, testFileString)
960	}
961	return testFiles
962}
963