• 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
15package android
16
17import (
18	"fmt"
19	"path"
20	"path/filepath"
21	"sort"
22	"strings"
23	"text/scanner"
24
25	"github.com/google/blueprint"
26	"github.com/google/blueprint/pathtools"
27	"github.com/google/blueprint/proptools"
28)
29
30var (
31	DeviceSharedLibrary = "shared_library"
32	DeviceStaticLibrary = "static_library"
33	DeviceExecutable    = "executable"
34	HostSharedLibrary   = "host_shared_library"
35	HostStaticLibrary   = "host_static_library"
36	HostExecutable      = "host_executable"
37)
38
39type BuildParams struct {
40	Rule            blueprint.Rule
41	Deps            blueprint.Deps
42	Depfile         WritablePath
43	Description     string
44	Output          WritablePath
45	Outputs         WritablePaths
46	ImplicitOutput  WritablePath
47	ImplicitOutputs WritablePaths
48	Input           Path
49	Inputs          Paths
50	Implicit        Path
51	Implicits       Paths
52	OrderOnly       Paths
53	Default         bool
54	Args            map[string]string
55}
56
57type ModuleBuildParams BuildParams
58
59type androidBaseContext interface {
60	Target() Target
61	TargetPrimary() bool
62	MultiTargets() []Target
63	Arch() Arch
64	Os() OsType
65	Host() bool
66	Device() bool
67	Darwin() bool
68	Fuchsia() bool
69	Windows() bool
70	Debug() bool
71	PrimaryArch() bool
72	Platform() bool
73	DeviceSpecific() bool
74	SocSpecific() bool
75	ProductSpecific() bool
76	ProductServicesSpecific() bool
77	AConfig() Config
78	DeviceConfig() DeviceConfig
79}
80
81type BaseContext interface {
82	BaseModuleContext
83	androidBaseContext
84}
85
86// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
87// a Config instead of an interface{}.
88type BaseModuleContext interface {
89	ModuleName() string
90	ModuleDir() string
91	ModuleType() string
92	Config() Config
93
94	ContainsProperty(name string) bool
95	Errorf(pos scanner.Position, fmt string, args ...interface{})
96	ModuleErrorf(fmt string, args ...interface{})
97	PropertyErrorf(property, fmt string, args ...interface{})
98	Failed() bool
99
100	// GlobWithDeps returns a list of files that match the specified pattern but do not match any
101	// of the patterns in excludes.  It also adds efficient dependencies to rerun the primary
102	// builder whenever a file matching the pattern as added or removed, without rerunning if a
103	// file that does not match the pattern is added to a searched directory.
104	GlobWithDeps(pattern string, excludes []string) ([]string, error)
105
106	Fs() pathtools.FileSystem
107	AddNinjaFileDeps(deps ...string)
108}
109
110type ModuleContext interface {
111	androidBaseContext
112	BaseModuleContext
113
114	// Deprecated: use ModuleContext.Build instead.
115	ModuleBuild(pctx PackageContext, params ModuleBuildParams)
116
117	ExpandSources(srcFiles, excludes []string) Paths
118	ExpandSource(srcFile, prop string) Path
119	ExpandOptionalSource(srcFile *string, prop string) OptionalPath
120	Glob(globPattern string, excludes []string) Paths
121	GlobFiles(globPattern string, excludes []string) Paths
122
123	InstallExecutable(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
124	InstallFile(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
125	InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath
126	InstallAbsoluteSymlink(installPath OutputPath, name string, absPath string) OutputPath
127	CheckbuildFile(srcPath Path)
128
129	AddMissingDependencies(deps []string)
130
131	InstallInData() bool
132	InstallInSanitizerDir() bool
133	InstallInRecovery() bool
134
135	RequiredModuleNames() []string
136
137	// android.ModuleContext methods
138	// These are duplicated instead of embedded so that can eventually be wrapped to take an
139	// android.Module instead of a blueprint.Module
140	OtherModuleName(m blueprint.Module) string
141	OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
142	OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
143
144	GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
145	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
146
147	ModuleSubDir() string
148
149	VisitDirectDepsBlueprint(visit func(blueprint.Module))
150	VisitDirectDeps(visit func(Module))
151	VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
152	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
153	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
154	VisitDepsDepthFirst(visit func(Module))
155	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
156	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
157	WalkDeps(visit func(Module, Module) bool)
158	WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
159
160	Variable(pctx PackageContext, name, value string)
161	Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
162	// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
163	// and performs more verification.
164	Build(pctx PackageContext, params BuildParams)
165
166	PrimaryModule() Module
167	FinalModule() Module
168	VisitAllModuleVariants(visit func(Module))
169
170	GetMissingDependencies() []string
171	Namespace() blueprint.Namespace
172}
173
174type Module interface {
175	blueprint.Module
176
177	// GenerateAndroidBuildActions is analogous to Blueprints' GenerateBuildActions,
178	// but GenerateAndroidBuildActions also has access to Android-specific information.
179	// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
180	GenerateAndroidBuildActions(ModuleContext)
181
182	DepsMutator(BottomUpMutatorContext)
183
184	base() *ModuleBase
185	Enabled() bool
186	Target() Target
187	InstallInData() bool
188	InstallInSanitizerDir() bool
189	InstallInRecovery() bool
190	SkipInstall()
191	ExportedToMake() bool
192	NoticeFile() OptionalPath
193
194	AddProperties(props ...interface{})
195	GetProperties() []interface{}
196
197	BuildParamsForTests() []BuildParams
198	RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
199	VariablesForTests() map[string]string
200}
201
202type nameProperties struct {
203	// The name of the module.  Must be unique across all modules.
204	Name *string
205}
206
207type commonProperties struct {
208	// emit build rules for this module
209	Enabled *bool `android:"arch_variant"`
210
211	// control whether this module compiles for 32-bit, 64-bit, or both.  Possible values
212	// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
213	// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
214	// platform
215	Compile_multilib *string `android:"arch_variant"`
216
217	Target struct {
218		Host struct {
219			Compile_multilib *string
220		}
221		Android struct {
222			Compile_multilib *string
223		}
224	}
225
226	UseTargetVariants bool   `blueprint:"mutated"`
227	Default_multilib  string `blueprint:"mutated"`
228
229	// whether this is a proprietary vendor module, and should be installed into /vendor
230	Proprietary *bool
231
232	// vendor who owns this module
233	Owner *string
234
235	// whether this module is specific to an SoC (System-On-a-Chip). When set to true,
236	// it is installed into /vendor (or /system/vendor if vendor partition does not exist).
237	// Use `soc_specific` instead for better meaning.
238	Vendor *bool
239
240	// whether this module is specific to an SoC (System-On-a-Chip). When set to true,
241	// it is installed into /vendor (or /system/vendor if vendor partition does not exist).
242	Soc_specific *bool
243
244	// whether this module is specific to a device, not only for SoC, but also for off-chip
245	// peripherals. When set to true, it is installed into /odm (or /vendor/odm if odm partition
246	// does not exist, or /system/vendor/odm if both odm and vendor partitions do not exist).
247	// This implies `soc_specific:true`.
248	Device_specific *bool
249
250	// whether this module is specific to a software configuration of a product (e.g. country,
251	// network operator, etc). When set to true, it is installed into /product (or
252	// /system/product if product partition does not exist).
253	Product_specific *bool
254
255	// whether this module provides services owned by the OS provider to the core platform. When set
256	// to true, it is installed into  /product_services (or /system/product_services if
257	// product_services partition does not exist).
258	Product_services_specific *bool
259
260	// Whether this module is installed to recovery partition
261	Recovery *bool
262
263	// init.rc files to be installed if this module is installed
264	Init_rc []string `android:"path"`
265
266	// VINTF manifest fragments to be installed if this module is installed
267	Vintf_fragments []string `android:"path"`
268
269	// names of other modules to install if this module is installed
270	Required []string `android:"arch_variant"`
271
272	// relative path to a file to include in the list of notices for the device
273	Notice *string `android:"path"`
274
275	Dist struct {
276		// copy the output of this module to the $DIST_DIR when `dist` is specified on the
277		// command line and  any of these targets are also on the command line, or otherwise
278		// built
279		Targets []string `android:"arch_variant"`
280
281		// The name of the output artifact. This defaults to the basename of the output of
282		// the module.
283		Dest *string `android:"arch_variant"`
284
285		// The directory within the dist directory to store the artifact. Defaults to the
286		// top level directory ("").
287		Dir *string `android:"arch_variant"`
288
289		// A suffix to add to the artifact file name (before any extension).
290		Suffix *string `android:"arch_variant"`
291	} `android:"arch_variant"`
292
293	// Set by TargetMutator
294	CompileTarget       Target   `blueprint:"mutated"`
295	CompileMultiTargets []Target `blueprint:"mutated"`
296	CompilePrimary      bool     `blueprint:"mutated"`
297
298	// Set by InitAndroidModule
299	HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
300	ArchSpecific          bool                  `blueprint:"mutated"`
301
302	SkipInstall bool `blueprint:"mutated"`
303
304	NamespaceExportedToMake bool `blueprint:"mutated"`
305}
306
307type hostAndDeviceProperties struct {
308	// If set to true, build a variant of the module for the host.  Defaults to false.
309	Host_supported *bool
310
311	// If set to true, build a variant of the module for the device.  Defaults to true.
312	Device_supported *bool
313}
314
315type Multilib string
316
317const (
318	MultilibBoth        Multilib = "both"
319	MultilibFirst       Multilib = "first"
320	MultilibCommon      Multilib = "common"
321	MultilibCommonFirst Multilib = "common_first"
322	MultilibDefault     Multilib = ""
323)
324
325type HostOrDeviceSupported int
326
327const (
328	_ HostOrDeviceSupported = iota
329
330	// Host and HostCross are built by default. Device is not supported.
331	HostSupported
332
333	// Host is built by default. HostCross and Device are not supported.
334	HostSupportedNoCross
335
336	// Device is built by default. Host and HostCross are not supported.
337	DeviceSupported
338
339	// Device is built by default. Host and HostCross are supported.
340	HostAndDeviceSupported
341
342	// Host, HostCross, and Device are built by default.
343	HostAndDeviceDefault
344
345	// Nothing is supported. This is not exposed to the user, but used to mark a
346	// host only module as unsupported when the module type is not supported on
347	// the host OS. E.g. benchmarks are supported on Linux but not Darwin.
348	NeitherHostNorDeviceSupported
349)
350
351type moduleKind int
352
353const (
354	platformModule moduleKind = iota
355	deviceSpecificModule
356	socSpecificModule
357	productSpecificModule
358	productServicesSpecificModule
359)
360
361func (k moduleKind) String() string {
362	switch k {
363	case platformModule:
364		return "platform"
365	case deviceSpecificModule:
366		return "device-specific"
367	case socSpecificModule:
368		return "soc-specific"
369	case productSpecificModule:
370		return "product-specific"
371	case productServicesSpecificModule:
372		return "productservices-specific"
373	default:
374		panic(fmt.Errorf("unknown module kind %d", k))
375	}
376}
377
378func InitAndroidModule(m Module) {
379	base := m.base()
380	base.module = m
381
382	m.AddProperties(
383		&base.nameProperties,
384		&base.commonProperties,
385		&base.variableProperties)
386	base.generalProperties = m.GetProperties()
387	base.customizableProperties = m.GetProperties()
388}
389
390func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
391	InitAndroidModule(m)
392
393	base := m.base()
394	base.commonProperties.HostOrDeviceSupported = hod
395	base.commonProperties.Default_multilib = string(defaultMultilib)
396	base.commonProperties.ArchSpecific = true
397	base.commonProperties.UseTargetVariants = true
398
399	switch hod {
400	case HostAndDeviceSupported, HostAndDeviceDefault:
401		m.AddProperties(&base.hostAndDeviceProperties)
402	}
403
404	InitArchModule(m)
405}
406
407func InitAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
408	InitAndroidArchModule(m, hod, defaultMultilib)
409	m.base().commonProperties.UseTargetVariants = false
410}
411
412// A ModuleBase object contains the properties that are common to all Android
413// modules.  It should be included as an anonymous field in every module
414// struct definition.  InitAndroidModule should then be called from the module's
415// factory function, and the return values from InitAndroidModule should be
416// returned from the factory function.
417//
418// The ModuleBase type is responsible for implementing the GenerateBuildActions
419// method to support the blueprint.Module interface. This method will then call
420// the module's GenerateAndroidBuildActions method once for each build variant
421// that is to be built. GenerateAndroidBuildActions is passed a
422// AndroidModuleContext rather than the usual blueprint.ModuleContext.
423// AndroidModuleContext exposes extra functionality specific to the Android build
424// system including details about the particular build variant that is to be
425// generated.
426//
427// For example:
428//
429//     import (
430//         "android/soong/android"
431//     )
432//
433//     type myModule struct {
434//         android.ModuleBase
435//         properties struct {
436//             MyProperty string
437//         }
438//     }
439//
440//     func NewMyModule() android.Module) {
441//         m := &myModule{}
442//         m.AddProperties(&m.properties)
443//         android.InitAndroidModule(m)
444//         return m
445//     }
446//
447//     func (m *myModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
448//         // Get the CPU architecture for the current build variant.
449//         variantArch := ctx.Arch()
450//
451//         // ...
452//     }
453type ModuleBase struct {
454	// Putting the curiously recurring thing pointing to the thing that contains
455	// the thing pattern to good use.
456	// TODO: remove this
457	module Module
458
459	nameProperties          nameProperties
460	commonProperties        commonProperties
461	variableProperties      variableProperties
462	hostAndDeviceProperties hostAndDeviceProperties
463	generalProperties       []interface{}
464	archProperties          [][]interface{}
465	customizableProperties  []interface{}
466
467	noAddressSanitizer bool
468	installFiles       Paths
469	checkbuildFiles    Paths
470	noticeFile         OptionalPath
471
472	// Used by buildTargetSingleton to create checkbuild and per-directory build targets
473	// Only set on the final variant of each module
474	installTarget    WritablePath
475	checkbuildTarget WritablePath
476	blueprintDir     string
477
478	hooks hooks
479
480	registerProps []interface{}
481
482	// For tests
483	buildParams []BuildParams
484	ruleParams  map[blueprint.Rule]blueprint.RuleParams
485	variables   map[string]string
486
487	prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
488}
489
490func (a *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
491
492func (a *ModuleBase) AddProperties(props ...interface{}) {
493	a.registerProps = append(a.registerProps, props...)
494}
495
496func (a *ModuleBase) GetProperties() []interface{} {
497	return a.registerProps
498}
499
500func (a *ModuleBase) BuildParamsForTests() []BuildParams {
501	return a.buildParams
502}
503
504func (a *ModuleBase) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams {
505	return a.ruleParams
506}
507
508func (a *ModuleBase) VariablesForTests() map[string]string {
509	return a.variables
510}
511
512func (a *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) {
513	a.prefer32 = prefer32
514}
515
516// Name returns the name of the module.  It may be overridden by individual module types, for
517// example prebuilts will prepend prebuilt_ to the name.
518func (a *ModuleBase) Name() string {
519	return String(a.nameProperties.Name)
520}
521
522// BaseModuleName returns the name of the module as specified in the blueprints file.
523func (a *ModuleBase) BaseModuleName() string {
524	return String(a.nameProperties.Name)
525}
526
527func (a *ModuleBase) base() *ModuleBase {
528	return a
529}
530
531func (a *ModuleBase) SetTarget(target Target, multiTargets []Target, primary bool) {
532	a.commonProperties.CompileTarget = target
533	a.commonProperties.CompileMultiTargets = multiTargets
534	a.commonProperties.CompilePrimary = primary
535}
536
537func (a *ModuleBase) Target() Target {
538	return a.commonProperties.CompileTarget
539}
540
541func (a *ModuleBase) TargetPrimary() bool {
542	return a.commonProperties.CompilePrimary
543}
544
545func (a *ModuleBase) MultiTargets() []Target {
546	return a.commonProperties.CompileMultiTargets
547}
548
549func (a *ModuleBase) Os() OsType {
550	return a.Target().Os
551}
552
553func (a *ModuleBase) Host() bool {
554	return a.Os().Class == Host || a.Os().Class == HostCross
555}
556
557func (a *ModuleBase) Arch() Arch {
558	return a.Target().Arch
559}
560
561func (a *ModuleBase) ArchSpecific() bool {
562	return a.commonProperties.ArchSpecific
563}
564
565func (a *ModuleBase) OsClassSupported() []OsClass {
566	switch a.commonProperties.HostOrDeviceSupported {
567	case HostSupported:
568		return []OsClass{Host, HostCross}
569	case HostSupportedNoCross:
570		return []OsClass{Host}
571	case DeviceSupported:
572		return []OsClass{Device}
573	case HostAndDeviceSupported, HostAndDeviceDefault:
574		var supported []OsClass
575		if Bool(a.hostAndDeviceProperties.Host_supported) ||
576			(a.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault &&
577				a.hostAndDeviceProperties.Host_supported == nil) {
578			supported = append(supported, Host, HostCross)
579		}
580		if a.hostAndDeviceProperties.Device_supported == nil ||
581			*a.hostAndDeviceProperties.Device_supported {
582			supported = append(supported, Device)
583		}
584		return supported
585	default:
586		return nil
587	}
588}
589
590func (a *ModuleBase) DeviceSupported() bool {
591	return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
592		a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
593			(a.hostAndDeviceProperties.Device_supported == nil ||
594				*a.hostAndDeviceProperties.Device_supported)
595}
596
597func (a *ModuleBase) Platform() bool {
598	return !a.DeviceSpecific() && !a.SocSpecific() && !a.ProductSpecific() && !a.ProductServicesSpecific()
599}
600
601func (a *ModuleBase) DeviceSpecific() bool {
602	return Bool(a.commonProperties.Device_specific)
603}
604
605func (a *ModuleBase) SocSpecific() bool {
606	return Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific)
607}
608
609func (a *ModuleBase) ProductSpecific() bool {
610	return Bool(a.commonProperties.Product_specific)
611}
612
613func (a *ModuleBase) ProductServicesSpecific() bool {
614	return Bool(a.commonProperties.Product_services_specific)
615}
616
617func (a *ModuleBase) Enabled() bool {
618	if a.commonProperties.Enabled == nil {
619		return !a.Os().DefaultDisabled
620	}
621	return *a.commonProperties.Enabled
622}
623
624func (a *ModuleBase) SkipInstall() {
625	a.commonProperties.SkipInstall = true
626}
627
628func (a *ModuleBase) ExportedToMake() bool {
629	return a.commonProperties.NamespaceExportedToMake
630}
631
632func (a *ModuleBase) computeInstallDeps(
633	ctx blueprint.ModuleContext) Paths {
634
635	result := Paths{}
636	// TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
637	ctx.VisitDepsDepthFirstIf(isFileInstaller,
638		func(m blueprint.Module) {
639			fileInstaller := m.(fileInstaller)
640			files := fileInstaller.filesToInstall()
641			result = append(result, files...)
642		})
643
644	return result
645}
646
647func (a *ModuleBase) filesToInstall() Paths {
648	return a.installFiles
649}
650
651func (p *ModuleBase) NoAddressSanitizer() bool {
652	return p.noAddressSanitizer
653}
654
655func (p *ModuleBase) InstallInData() bool {
656	return false
657}
658
659func (p *ModuleBase) InstallInSanitizerDir() bool {
660	return false
661}
662
663func (p *ModuleBase) InstallInRecovery() bool {
664	return Bool(p.commonProperties.Recovery)
665}
666
667func (a *ModuleBase) Owner() string {
668	return String(a.commonProperties.Owner)
669}
670
671func (a *ModuleBase) NoticeFile() OptionalPath {
672	return a.noticeFile
673}
674
675func (a *ModuleBase) generateModuleTarget(ctx ModuleContext) {
676	allInstalledFiles := Paths{}
677	allCheckbuildFiles := Paths{}
678	ctx.VisitAllModuleVariants(func(module Module) {
679		a := module.base()
680		allInstalledFiles = append(allInstalledFiles, a.installFiles...)
681		allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
682	})
683
684	var deps Paths
685
686	namespacePrefix := ctx.Namespace().(*Namespace).id
687	if namespacePrefix != "" {
688		namespacePrefix = namespacePrefix + "-"
689	}
690
691	if len(allInstalledFiles) > 0 {
692		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-install")
693		ctx.Build(pctx, BuildParams{
694			Rule:      blueprint.Phony,
695			Output:    name,
696			Implicits: allInstalledFiles,
697			Default:   !ctx.Config().EmbeddedInMake(),
698		})
699		deps = append(deps, name)
700		a.installTarget = name
701	}
702
703	if len(allCheckbuildFiles) > 0 {
704		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-checkbuild")
705		ctx.Build(pctx, BuildParams{
706			Rule:      blueprint.Phony,
707			Output:    name,
708			Implicits: allCheckbuildFiles,
709		})
710		deps = append(deps, name)
711		a.checkbuildTarget = name
712	}
713
714	if len(deps) > 0 {
715		suffix := ""
716		if ctx.Config().EmbeddedInMake() {
717			suffix = "-soong"
718		}
719
720		name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+suffix)
721		ctx.Build(pctx, BuildParams{
722			Rule:      blueprint.Phony,
723			Outputs:   []WritablePath{name},
724			Implicits: deps,
725		})
726
727		a.blueprintDir = ctx.ModuleDir()
728	}
729}
730
731func determineModuleKind(a *ModuleBase, ctx blueprint.BaseModuleContext) moduleKind {
732	var socSpecific = Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific)
733	var deviceSpecific = Bool(a.commonProperties.Device_specific)
734	var productSpecific = Bool(a.commonProperties.Product_specific)
735	var productServicesSpecific = Bool(a.commonProperties.Product_services_specific)
736
737	msg := "conflicting value set here"
738	if socSpecific && deviceSpecific {
739		ctx.PropertyErrorf("device_specific", "a module cannot be specific to SoC and device at the same time.")
740		if Bool(a.commonProperties.Vendor) {
741			ctx.PropertyErrorf("vendor", msg)
742		}
743		if Bool(a.commonProperties.Proprietary) {
744			ctx.PropertyErrorf("proprietary", msg)
745		}
746		if Bool(a.commonProperties.Soc_specific) {
747			ctx.PropertyErrorf("soc_specific", msg)
748		}
749	}
750
751	if productSpecific && productServicesSpecific {
752		ctx.PropertyErrorf("product_specific", "a module cannot be specific to product and product_services at the same time.")
753		ctx.PropertyErrorf("product_services_specific", msg)
754	}
755
756	if (socSpecific || deviceSpecific) && (productSpecific || productServicesSpecific) {
757		if productSpecific {
758			ctx.PropertyErrorf("product_specific", "a module cannot be specific to SoC or device and product at the same time.")
759		} else {
760			ctx.PropertyErrorf("product_services_specific", "a module cannot be specific to SoC or device and product_services at the same time.")
761		}
762		if deviceSpecific {
763			ctx.PropertyErrorf("device_specific", msg)
764		} else {
765			if Bool(a.commonProperties.Vendor) {
766				ctx.PropertyErrorf("vendor", msg)
767			}
768			if Bool(a.commonProperties.Proprietary) {
769				ctx.PropertyErrorf("proprietary", msg)
770			}
771			if Bool(a.commonProperties.Soc_specific) {
772				ctx.PropertyErrorf("soc_specific", msg)
773			}
774		}
775	}
776
777	if productSpecific {
778		return productSpecificModule
779	} else if productServicesSpecific {
780		return productServicesSpecificModule
781	} else if deviceSpecific {
782		return deviceSpecificModule
783	} else if socSpecific {
784		return socSpecificModule
785	} else {
786		return platformModule
787	}
788}
789
790func (a *ModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl {
791	return androidBaseContextImpl{
792		target:        a.commonProperties.CompileTarget,
793		targetPrimary: a.commonProperties.CompilePrimary,
794		multiTargets:  a.commonProperties.CompileMultiTargets,
795		kind:          determineModuleKind(a, ctx),
796		config:        ctx.Config().(Config),
797	}
798}
799
800func (a *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
801	ctx := &androidModuleContext{
802		module:                 a.module,
803		ModuleContext:          blueprintCtx,
804		androidBaseContextImpl: a.androidBaseContextFactory(blueprintCtx),
805		installDeps:            a.computeInstallDeps(blueprintCtx),
806		installFiles:           a.installFiles,
807		missingDeps:            blueprintCtx.GetMissingDependencies(),
808		variables:              make(map[string]string),
809	}
810
811	if ctx.config.captureBuild {
812		ctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams)
813	}
814
815	desc := "//" + ctx.ModuleDir() + ":" + ctx.ModuleName() + " "
816	var suffix []string
817	if ctx.Os().Class != Device && ctx.Os().Class != Generic {
818		suffix = append(suffix, ctx.Os().String())
819	}
820	if !ctx.PrimaryArch() {
821		suffix = append(suffix, ctx.Arch().ArchType.String())
822	}
823
824	ctx.Variable(pctx, "moduleDesc", desc)
825
826	s := ""
827	if len(suffix) > 0 {
828		s = " [" + strings.Join(suffix, " ") + "]"
829	}
830	ctx.Variable(pctx, "moduleDescSuffix", s)
831
832	// Some common property checks for properties that will be used later in androidmk.go
833	if a.commonProperties.Dist.Dest != nil {
834		_, err := validateSafePath(*a.commonProperties.Dist.Dest)
835		if err != nil {
836			ctx.PropertyErrorf("dist.dest", "%s", err.Error())
837		}
838	}
839	if a.commonProperties.Dist.Dir != nil {
840		_, err := validateSafePath(*a.commonProperties.Dist.Dir)
841		if err != nil {
842			ctx.PropertyErrorf("dist.dir", "%s", err.Error())
843		}
844	}
845	if a.commonProperties.Dist.Suffix != nil {
846		if strings.Contains(*a.commonProperties.Dist.Suffix, "/") {
847			ctx.PropertyErrorf("dist.suffix", "Suffix may not contain a '/' character.")
848		}
849	}
850
851	if a.Enabled() {
852		notice := proptools.StringDefault(a.commonProperties.Notice, "NOTICE")
853		if m := SrcIsModule(notice); m != "" {
854			a.noticeFile = ctx.ExpandOptionalSource(&notice, "notice")
855		} else {
856			noticePath := filepath.Join(ctx.ModuleDir(), notice)
857			a.noticeFile = ExistentPathForSource(ctx, noticePath)
858		}
859
860		a.module.GenerateAndroidBuildActions(ctx)
861		if ctx.Failed() {
862			return
863		}
864
865		a.installFiles = append(a.installFiles, ctx.installFiles...)
866		a.checkbuildFiles = append(a.checkbuildFiles, ctx.checkbuildFiles...)
867	}
868
869	if a == ctx.FinalModule().(Module).base() {
870		a.generateModuleTarget(ctx)
871		if ctx.Failed() {
872			return
873		}
874	}
875
876	a.buildParams = ctx.buildParams
877	a.ruleParams = ctx.ruleParams
878	a.variables = ctx.variables
879}
880
881type androidBaseContextImpl struct {
882	target        Target
883	multiTargets  []Target
884	targetPrimary bool
885	debug         bool
886	kind          moduleKind
887	config        Config
888}
889
890type androidModuleContext struct {
891	blueprint.ModuleContext
892	androidBaseContextImpl
893	installDeps     Paths
894	installFiles    Paths
895	checkbuildFiles Paths
896	missingDeps     []string
897	module          Module
898
899	// For tests
900	buildParams []BuildParams
901	ruleParams  map[blueprint.Rule]blueprint.RuleParams
902	variables   map[string]string
903}
904
905func (a *androidModuleContext) ninjaError(desc string, outputs []string, err error) {
906	a.ModuleContext.Build(pctx.PackageContext, blueprint.BuildParams{
907		Rule:        ErrorRule,
908		Description: desc,
909		Outputs:     outputs,
910		Optional:    true,
911		Args: map[string]string{
912			"error": err.Error(),
913		},
914	})
915	return
916}
917
918func (a *androidModuleContext) Config() Config {
919	return a.ModuleContext.Config().(Config)
920}
921
922func (a *androidModuleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
923	a.Build(pctx, BuildParams(params))
924}
925
926func convertBuildParams(params BuildParams) blueprint.BuildParams {
927	bparams := blueprint.BuildParams{
928		Rule:            params.Rule,
929		Description:     params.Description,
930		Deps:            params.Deps,
931		Outputs:         params.Outputs.Strings(),
932		ImplicitOutputs: params.ImplicitOutputs.Strings(),
933		Inputs:          params.Inputs.Strings(),
934		Implicits:       params.Implicits.Strings(),
935		OrderOnly:       params.OrderOnly.Strings(),
936		Args:            params.Args,
937		Optional:        !params.Default,
938	}
939
940	if params.Depfile != nil {
941		bparams.Depfile = params.Depfile.String()
942	}
943	if params.Output != nil {
944		bparams.Outputs = append(bparams.Outputs, params.Output.String())
945	}
946	if params.ImplicitOutput != nil {
947		bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
948	}
949	if params.Input != nil {
950		bparams.Inputs = append(bparams.Inputs, params.Input.String())
951	}
952	if params.Implicit != nil {
953		bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
954	}
955
956	bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
957	bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
958	bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
959	bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
960	bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
961	bparams.Depfile = proptools.NinjaEscapeList([]string{bparams.Depfile})[0]
962
963	return bparams
964}
965
966func (a *androidModuleContext) Variable(pctx PackageContext, name, value string) {
967	if a.config.captureBuild {
968		a.variables[name] = value
969	}
970
971	a.ModuleContext.Variable(pctx.PackageContext, name, value)
972}
973
974func (a *androidModuleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
975	argNames ...string) blueprint.Rule {
976
977	rule := a.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...)
978
979	if a.config.captureBuild {
980		a.ruleParams[rule] = params
981	}
982
983	return rule
984}
985
986func (a *androidModuleContext) Build(pctx PackageContext, params BuildParams) {
987	if a.config.captureBuild {
988		a.buildParams = append(a.buildParams, params)
989	}
990
991	bparams := convertBuildParams(params)
992
993	if bparams.Description != "" {
994		bparams.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
995	}
996
997	if a.missingDeps != nil {
998		a.ninjaError(bparams.Description, bparams.Outputs,
999			fmt.Errorf("module %s missing dependencies: %s\n",
1000				a.ModuleName(), strings.Join(a.missingDeps, ", ")))
1001		return
1002	}
1003
1004	a.ModuleContext.Build(pctx.PackageContext, bparams)
1005}
1006
1007func (a *androidModuleContext) GetMissingDependencies() []string {
1008	return a.missingDeps
1009}
1010
1011func (a *androidModuleContext) AddMissingDependencies(deps []string) {
1012	if deps != nil {
1013		a.missingDeps = append(a.missingDeps, deps...)
1014		a.missingDeps = FirstUniqueStrings(a.missingDeps)
1015	}
1016}
1017
1018func (a *androidModuleContext) validateAndroidModule(module blueprint.Module) Module {
1019	aModule, _ := module.(Module)
1020	if aModule == nil {
1021		a.ModuleErrorf("module %q not an android module", a.OtherModuleName(aModule))
1022		return nil
1023	}
1024
1025	if !aModule.Enabled() {
1026		if a.Config().AllowMissingDependencies() {
1027			a.AddMissingDependencies([]string{a.OtherModuleName(aModule)})
1028		} else {
1029			a.ModuleErrorf("depends on disabled module %q", a.OtherModuleName(aModule))
1030		}
1031		return nil
1032	}
1033
1034	return aModule
1035}
1036
1037func (a *androidModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
1038	type dep struct {
1039		mod blueprint.Module
1040		tag blueprint.DependencyTag
1041	}
1042	var deps []dep
1043	a.VisitDirectDepsBlueprint(func(m blueprint.Module) {
1044		if aModule, _ := m.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
1045			returnedTag := a.ModuleContext.OtherModuleDependencyTag(aModule)
1046			if tag == nil || returnedTag == tag {
1047				deps = append(deps, dep{aModule, returnedTag})
1048			}
1049		}
1050	})
1051	if len(deps) == 1 {
1052		return deps[0].mod, deps[0].tag
1053	} else if len(deps) >= 2 {
1054		panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
1055			name, a.ModuleName()))
1056	} else {
1057		return nil, nil
1058	}
1059}
1060
1061func (a *androidModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
1062	m, _ := a.getDirectDepInternal(name, tag)
1063	return m
1064}
1065
1066func (a *androidModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
1067	return a.getDirectDepInternal(name, nil)
1068}
1069
1070func (a *androidModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
1071	a.ModuleContext.VisitDirectDeps(visit)
1072}
1073
1074func (a *androidModuleContext) VisitDirectDeps(visit func(Module)) {
1075	a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
1076		if aModule := a.validateAndroidModule(module); aModule != nil {
1077			visit(aModule)
1078		}
1079	})
1080}
1081
1082func (a *androidModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
1083	a.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
1084		if aModule := a.validateAndroidModule(module); aModule != nil {
1085			if a.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
1086				visit(aModule)
1087			}
1088		}
1089	})
1090}
1091
1092func (a *androidModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
1093	a.ModuleContext.VisitDirectDepsIf(
1094		// pred
1095		func(module blueprint.Module) bool {
1096			if aModule := a.validateAndroidModule(module); aModule != nil {
1097				return pred(aModule)
1098			} else {
1099				return false
1100			}
1101		},
1102		// visit
1103		func(module blueprint.Module) {
1104			visit(module.(Module))
1105		})
1106}
1107
1108func (a *androidModuleContext) VisitDepsDepthFirst(visit func(Module)) {
1109	a.ModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) {
1110		if aModule := a.validateAndroidModule(module); aModule != nil {
1111			visit(aModule)
1112		}
1113	})
1114}
1115
1116func (a *androidModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
1117	a.ModuleContext.VisitDepsDepthFirstIf(
1118		// pred
1119		func(module blueprint.Module) bool {
1120			if aModule := a.validateAndroidModule(module); aModule != nil {
1121				return pred(aModule)
1122			} else {
1123				return false
1124			}
1125		},
1126		// visit
1127		func(module blueprint.Module) {
1128			visit(module.(Module))
1129		})
1130}
1131
1132func (a *androidModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
1133	a.ModuleContext.WalkDeps(visit)
1134}
1135
1136func (a *androidModuleContext) WalkDeps(visit func(Module, Module) bool) {
1137	a.ModuleContext.WalkDeps(func(child, parent blueprint.Module) bool {
1138		childAndroidModule := a.validateAndroidModule(child)
1139		parentAndroidModule := a.validateAndroidModule(parent)
1140		if childAndroidModule != nil && parentAndroidModule != nil {
1141			return visit(childAndroidModule, parentAndroidModule)
1142		} else {
1143			return false
1144		}
1145	})
1146}
1147
1148func (a *androidModuleContext) VisitAllModuleVariants(visit func(Module)) {
1149	a.ModuleContext.VisitAllModuleVariants(func(module blueprint.Module) {
1150		visit(module.(Module))
1151	})
1152}
1153
1154func (a *androidModuleContext) PrimaryModule() Module {
1155	return a.ModuleContext.PrimaryModule().(Module)
1156}
1157
1158func (a *androidModuleContext) FinalModule() Module {
1159	return a.ModuleContext.FinalModule().(Module)
1160}
1161
1162func (a *androidBaseContextImpl) Target() Target {
1163	return a.target
1164}
1165
1166func (a *androidBaseContextImpl) TargetPrimary() bool {
1167	return a.targetPrimary
1168}
1169
1170func (a *androidBaseContextImpl) MultiTargets() []Target {
1171	return a.multiTargets
1172}
1173
1174func (a *androidBaseContextImpl) Arch() Arch {
1175	return a.target.Arch
1176}
1177
1178func (a *androidBaseContextImpl) Os() OsType {
1179	return a.target.Os
1180}
1181
1182func (a *androidBaseContextImpl) Host() bool {
1183	return a.target.Os.Class == Host || a.target.Os.Class == HostCross
1184}
1185
1186func (a *androidBaseContextImpl) Device() bool {
1187	return a.target.Os.Class == Device
1188}
1189
1190func (a *androidBaseContextImpl) Darwin() bool {
1191	return a.target.Os == Darwin
1192}
1193
1194func (a *androidBaseContextImpl) Fuchsia() bool {
1195	return a.target.Os == Fuchsia
1196}
1197
1198func (a *androidBaseContextImpl) Windows() bool {
1199	return a.target.Os == Windows
1200}
1201
1202func (a *androidBaseContextImpl) Debug() bool {
1203	return a.debug
1204}
1205
1206func (a *androidBaseContextImpl) PrimaryArch() bool {
1207	if len(a.config.Targets[a.target.Os]) <= 1 {
1208		return true
1209	}
1210	return a.target.Arch.ArchType == a.config.Targets[a.target.Os][0].Arch.ArchType
1211}
1212
1213func (a *androidBaseContextImpl) AConfig() Config {
1214	return a.config
1215}
1216
1217func (a *androidBaseContextImpl) DeviceConfig() DeviceConfig {
1218	return DeviceConfig{a.config.deviceConfig}
1219}
1220
1221func (a *androidBaseContextImpl) Platform() bool {
1222	return a.kind == platformModule
1223}
1224
1225func (a *androidBaseContextImpl) DeviceSpecific() bool {
1226	return a.kind == deviceSpecificModule
1227}
1228
1229func (a *androidBaseContextImpl) SocSpecific() bool {
1230	return a.kind == socSpecificModule
1231}
1232
1233func (a *androidBaseContextImpl) ProductSpecific() bool {
1234	return a.kind == productSpecificModule
1235}
1236
1237func (a *androidBaseContextImpl) ProductServicesSpecific() bool {
1238	return a.kind == productServicesSpecificModule
1239}
1240
1241// Makes this module a platform module, i.e. not specific to soc, device,
1242// product, or product_services.
1243func (a *ModuleBase) MakeAsPlatform() {
1244	a.commonProperties.Vendor = boolPtr(false)
1245	a.commonProperties.Proprietary = boolPtr(false)
1246	a.commonProperties.Soc_specific = boolPtr(false)
1247	a.commonProperties.Product_specific = boolPtr(false)
1248	a.commonProperties.Product_services_specific = boolPtr(false)
1249}
1250
1251func (a *androidModuleContext) InstallInData() bool {
1252	return a.module.InstallInData()
1253}
1254
1255func (a *androidModuleContext) InstallInSanitizerDir() bool {
1256	return a.module.InstallInSanitizerDir()
1257}
1258
1259func (a *androidModuleContext) InstallInRecovery() bool {
1260	return a.module.InstallInRecovery()
1261}
1262
1263func (a *androidModuleContext) skipInstall(fullInstallPath OutputPath) bool {
1264	if a.module.base().commonProperties.SkipInstall {
1265		return true
1266	}
1267
1268	// We'll need a solution for choosing which of modules with the same name in different
1269	// namespaces to install.  For now, reuse the list of namespaces exported to Make as the
1270	// list of namespaces to install in a Soong-only build.
1271	if !a.module.base().commonProperties.NamespaceExportedToMake {
1272		return true
1273	}
1274
1275	if a.Device() {
1276		if a.Config().SkipDeviceInstall() {
1277			return true
1278		}
1279
1280		if a.Config().SkipMegaDeviceInstall(fullInstallPath.String()) {
1281			return true
1282		}
1283	}
1284
1285	return false
1286}
1287
1288func (a *androidModuleContext) InstallFile(installPath OutputPath, name string, srcPath Path,
1289	deps ...Path) OutputPath {
1290	return a.installFile(installPath, name, srcPath, Cp, deps)
1291}
1292
1293func (a *androidModuleContext) InstallExecutable(installPath OutputPath, name string, srcPath Path,
1294	deps ...Path) OutputPath {
1295	return a.installFile(installPath, name, srcPath, CpExecutable, deps)
1296}
1297
1298func (a *androidModuleContext) installFile(installPath OutputPath, name string, srcPath Path,
1299	rule blueprint.Rule, deps []Path) OutputPath {
1300
1301	fullInstallPath := installPath.Join(a, name)
1302	a.module.base().hooks.runInstallHooks(a, fullInstallPath, false)
1303
1304	if !a.skipInstall(fullInstallPath) {
1305
1306		deps = append(deps, a.installDeps...)
1307
1308		var implicitDeps, orderOnlyDeps Paths
1309
1310		if a.Host() {
1311			// Installed host modules might be used during the build, depend directly on their
1312			// dependencies so their timestamp is updated whenever their dependency is updated
1313			implicitDeps = deps
1314		} else {
1315			orderOnlyDeps = deps
1316		}
1317
1318		a.Build(pctx, BuildParams{
1319			Rule:        rule,
1320			Description: "install " + fullInstallPath.Base(),
1321			Output:      fullInstallPath,
1322			Input:       srcPath,
1323			Implicits:   implicitDeps,
1324			OrderOnly:   orderOnlyDeps,
1325			Default:     !a.Config().EmbeddedInMake(),
1326		})
1327
1328		a.installFiles = append(a.installFiles, fullInstallPath)
1329	}
1330	a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
1331	return fullInstallPath
1332}
1333
1334func (a *androidModuleContext) InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath {
1335	fullInstallPath := installPath.Join(a, name)
1336	a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
1337
1338	if !a.skipInstall(fullInstallPath) {
1339
1340		relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
1341		if err != nil {
1342			panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
1343		}
1344		a.Build(pctx, BuildParams{
1345			Rule:        Symlink,
1346			Description: "install symlink " + fullInstallPath.Base(),
1347			Output:      fullInstallPath,
1348			OrderOnly:   Paths{srcPath},
1349			Default:     !a.Config().EmbeddedInMake(),
1350			Args: map[string]string{
1351				"fromPath": relPath,
1352			},
1353		})
1354
1355		a.installFiles = append(a.installFiles, fullInstallPath)
1356		a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
1357	}
1358	return fullInstallPath
1359}
1360
1361// installPath/name -> absPath where absPath might be a path that is available only at runtime
1362// (e.g. /apex/...)
1363func (a *androidModuleContext) InstallAbsoluteSymlink(installPath OutputPath, name string, absPath string) OutputPath {
1364	fullInstallPath := installPath.Join(a, name)
1365	a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
1366
1367	if !a.skipInstall(fullInstallPath) {
1368		a.Build(pctx, BuildParams{
1369			Rule:        Symlink,
1370			Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
1371			Output:      fullInstallPath,
1372			Default:     !a.Config().EmbeddedInMake(),
1373			Args: map[string]string{
1374				"fromPath": absPath,
1375			},
1376		})
1377
1378		a.installFiles = append(a.installFiles, fullInstallPath)
1379	}
1380	return fullInstallPath
1381}
1382
1383func (a *androidModuleContext) CheckbuildFile(srcPath Path) {
1384	a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
1385}
1386
1387type fileInstaller interface {
1388	filesToInstall() Paths
1389}
1390
1391func isFileInstaller(m blueprint.Module) bool {
1392	_, ok := m.(fileInstaller)
1393	return ok
1394}
1395
1396func isAndroidModule(m blueprint.Module) bool {
1397	_, ok := m.(Module)
1398	return ok
1399}
1400
1401func findStringInSlice(str string, slice []string) int {
1402	for i, s := range slice {
1403		if s == str {
1404			return i
1405		}
1406	}
1407	return -1
1408}
1409
1410func SrcIsModule(s string) string {
1411	if len(s) > 1 && s[0] == ':' {
1412		return s[1:]
1413	}
1414	return ""
1415}
1416
1417type sourceDependencyTag struct {
1418	blueprint.BaseDependencyTag
1419}
1420
1421var SourceDepTag sourceDependencyTag
1422
1423// Adds necessary dependencies to satisfy filegroup or generated sources modules listed in srcFiles
1424// using ":module" syntax, if any.
1425//
1426// Deprecated: tag the property with `android:"path"` instead.
1427func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) {
1428	var deps []string
1429	set := make(map[string]bool)
1430
1431	for _, s := range srcFiles {
1432		if m := SrcIsModule(s); m != "" {
1433			if _, found := set[m]; found {
1434				ctx.ModuleErrorf("found source dependency duplicate: %q!", m)
1435			} else {
1436				set[m] = true
1437				deps = append(deps, m)
1438			}
1439		}
1440	}
1441
1442	ctx.AddDependency(ctx.Module(), SourceDepTag, deps...)
1443}
1444
1445// Adds necessary dependencies to satisfy filegroup or generated sources modules specified in s
1446// using ":module" syntax, if any.
1447//
1448// Deprecated: tag the property with `android:"path"` instead.
1449func ExtractSourceDeps(ctx BottomUpMutatorContext, s *string) {
1450	if s != nil {
1451		if m := SrcIsModule(*s); m != "" {
1452			ctx.AddDependency(ctx.Module(), SourceDepTag, m)
1453		}
1454	}
1455}
1456
1457type SourceFileProducer interface {
1458	Srcs() Paths
1459}
1460
1461type HostToolProvider interface {
1462	HostToolPath() OptionalPath
1463}
1464
1465// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.  The property must
1466// be tagged with `android:"path" to support automatic source module dependency resolution.
1467//
1468// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
1469func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths {
1470	return PathsForModuleSrcExcludes(ctx, srcFiles, excludes)
1471}
1472
1473// Returns a single path expanded from globs and modules referenced using ":module" syntax.  The property must
1474// be tagged with `android:"path" to support automatic source module dependency resolution.
1475//
1476// Deprecated: use PathForModuleSrc instead.
1477func (ctx *androidModuleContext) ExpandSource(srcFile, prop string) Path {
1478	return PathForModuleSrc(ctx, srcFile)
1479}
1480
1481// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
1482// the srcFile is non-nil.  The property must be tagged with `android:"path" to support automatic source module
1483// dependency resolution.
1484func (ctx *androidModuleContext) ExpandOptionalSource(srcFile *string, prop string) OptionalPath {
1485	if srcFile != nil {
1486		return OptionalPathForPath(PathForModuleSrc(ctx, *srcFile))
1487	}
1488	return OptionalPath{}
1489}
1490
1491func (ctx *androidModuleContext) RequiredModuleNames() []string {
1492	return ctx.module.base().commonProperties.Required
1493}
1494
1495func (ctx *androidModuleContext) Glob(globPattern string, excludes []string) Paths {
1496	ret, err := ctx.GlobWithDeps(globPattern, excludes)
1497	if err != nil {
1498		ctx.ModuleErrorf("glob: %s", err.Error())
1499	}
1500	return pathsForModuleSrcFromFullPath(ctx, ret, true)
1501}
1502
1503func (ctx *androidModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
1504	ret, err := ctx.GlobWithDeps(globPattern, excludes)
1505	if err != nil {
1506		ctx.ModuleErrorf("glob: %s", err.Error())
1507	}
1508	return pathsForModuleSrcFromFullPath(ctx, ret, false)
1509}
1510
1511func init() {
1512	RegisterSingletonType("buildtarget", BuildTargetSingleton)
1513}
1514
1515func BuildTargetSingleton() Singleton {
1516	return &buildTargetSingleton{}
1517}
1518
1519func parentDir(dir string) string {
1520	dir, _ = filepath.Split(dir)
1521	return filepath.Clean(dir)
1522}
1523
1524type buildTargetSingleton struct{}
1525
1526func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
1527	var checkbuildDeps Paths
1528
1529	mmTarget := func(dir string) WritablePath {
1530		return PathForPhony(ctx,
1531			"MODULES-IN-"+strings.Replace(filepath.Clean(dir), "/", "-", -1))
1532	}
1533
1534	modulesInDir := make(map[string]Paths)
1535
1536	ctx.VisitAllModules(func(module Module) {
1537		blueprintDir := module.base().blueprintDir
1538		installTarget := module.base().installTarget
1539		checkbuildTarget := module.base().checkbuildTarget
1540
1541		if checkbuildTarget != nil {
1542			checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
1543			modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], checkbuildTarget)
1544		}
1545
1546		if installTarget != nil {
1547			modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], installTarget)
1548		}
1549	})
1550
1551	suffix := ""
1552	if ctx.Config().EmbeddedInMake() {
1553		suffix = "-soong"
1554	}
1555
1556	// Create a top-level checkbuild target that depends on all modules
1557	ctx.Build(pctx, BuildParams{
1558		Rule:      blueprint.Phony,
1559		Output:    PathForPhony(ctx, "checkbuild"+suffix),
1560		Implicits: checkbuildDeps,
1561	})
1562
1563	// Make will generate the MODULES-IN-* targets
1564	if ctx.Config().EmbeddedInMake() {
1565		return
1566	}
1567
1568	sortedKeys := func(m map[string]Paths) []string {
1569		s := make([]string, 0, len(m))
1570		for k := range m {
1571			s = append(s, k)
1572		}
1573		sort.Strings(s)
1574		return s
1575	}
1576
1577	// Ensure ancestor directories are in modulesInDir
1578	dirs := sortedKeys(modulesInDir)
1579	for _, dir := range dirs {
1580		dir := parentDir(dir)
1581		for dir != "." && dir != "/" {
1582			if _, exists := modulesInDir[dir]; exists {
1583				break
1584			}
1585			modulesInDir[dir] = nil
1586			dir = parentDir(dir)
1587		}
1588	}
1589
1590	// Make directories build their direct subdirectories
1591	dirs = sortedKeys(modulesInDir)
1592	for _, dir := range dirs {
1593		p := parentDir(dir)
1594		if p != "." && p != "/" {
1595			modulesInDir[p] = append(modulesInDir[p], mmTarget(dir))
1596		}
1597	}
1598
1599	// Create a MODULES-IN-<directory> target that depends on all modules in a directory, and
1600	// depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp
1601	// files.
1602	for _, dir := range dirs {
1603		ctx.Build(pctx, BuildParams{
1604			Rule:      blueprint.Phony,
1605			Output:    mmTarget(dir),
1606			Implicits: modulesInDir[dir],
1607			// HACK: checkbuild should be an optional build, but force it
1608			// enabled for now in standalone builds
1609			Default: !ctx.Config().EmbeddedInMake(),
1610		})
1611	}
1612
1613	// Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild.
1614	osDeps := map[OsType]Paths{}
1615	ctx.VisitAllModules(func(module Module) {
1616		if module.Enabled() {
1617			os := module.Target().Os
1618			osDeps[os] = append(osDeps[os], module.base().checkbuildFiles...)
1619		}
1620	})
1621
1622	osClass := make(map[string]Paths)
1623	for os, deps := range osDeps {
1624		var className string
1625
1626		switch os.Class {
1627		case Host:
1628			className = "host"
1629		case HostCross:
1630			className = "host-cross"
1631		case Device:
1632			className = "target"
1633		default:
1634			continue
1635		}
1636
1637		name := PathForPhony(ctx, className+"-"+os.Name)
1638		osClass[className] = append(osClass[className], name)
1639
1640		ctx.Build(pctx, BuildParams{
1641			Rule:      blueprint.Phony,
1642			Output:    name,
1643			Implicits: deps,
1644		})
1645	}
1646
1647	// Wrap those into host|host-cross|target phony rules
1648	osClasses := sortedKeys(osClass)
1649	for _, class := range osClasses {
1650		ctx.Build(pctx, BuildParams{
1651			Rule:      blueprint.Phony,
1652			Output:    PathForPhony(ctx, class),
1653			Implicits: osClass[class],
1654		})
1655	}
1656}
1657
1658// Collect information for opening IDE project files in java/jdeps.go.
1659type IDEInfo interface {
1660	IDEInfo(ideInfo *IdeInfo)
1661	BaseModuleName() string
1662}
1663
1664// Extract the base module name from the Import name.
1665// Often the Import name has a prefix "prebuilt_".
1666// Remove the prefix explicitly if needed
1667// until we find a better solution to get the Import name.
1668type IDECustomizedModuleName interface {
1669	IDECustomizedModuleName() string
1670}
1671
1672type IdeInfo struct {
1673	Deps              []string `json:"dependencies,omitempty"`
1674	Srcs              []string `json:"srcs,omitempty"`
1675	Aidl_include_dirs []string `json:"aidl_include_dirs,omitempty"`
1676	Jarjar_rules      []string `json:"jarjar_rules,omitempty"`
1677	Jars              []string `json:"jars,omitempty"`
1678	Classes           []string `json:"class,omitempty"`
1679	Installed_paths   []string `json:"installed,omitempty"`
1680}
1681