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/filepath"
20	"strings"
21
22	"github.com/google/blueprint"
23	"github.com/google/blueprint/pathtools"
24)
25
26var (
27	DeviceSharedLibrary = "shared_library"
28	DeviceStaticLibrary = "static_library"
29	DeviceExecutable    = "executable"
30	HostSharedLibrary   = "host_shared_library"
31	HostStaticLibrary   = "host_static_library"
32	HostExecutable      = "host_executable"
33)
34
35type ModuleBuildParams struct {
36	Rule            blueprint.Rule
37	Deps            blueprint.Deps
38	Depfile         WritablePath
39	Output          WritablePath
40	Outputs         WritablePaths
41	ImplicitOutput  WritablePath
42	ImplicitOutputs WritablePaths
43	Input           Path
44	Inputs          Paths
45	Implicit        Path
46	Implicits       Paths
47	OrderOnly       Paths
48	Default         bool
49	Args            map[string]string
50}
51
52type androidBaseContext interface {
53	Target() Target
54	TargetPrimary() bool
55	Arch() Arch
56	Os() OsType
57	Host() bool
58	Device() bool
59	Darwin() bool
60	Debug() bool
61	PrimaryArch() bool
62	Vendor() bool
63	AConfig() Config
64	DeviceConfig() DeviceConfig
65}
66
67type BaseContext interface {
68	blueprint.BaseModuleContext
69	androidBaseContext
70}
71
72type ModuleContext interface {
73	blueprint.ModuleContext
74	androidBaseContext
75
76	// Similar to Build, but takes Paths instead of []string,
77	// and performs more verification.
78	ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams)
79
80	ExpandSources(srcFiles, excludes []string) Paths
81	ExpandSourcesSubDir(srcFiles, excludes []string, subDir string) Paths
82	Glob(globPattern string, excludes []string) Paths
83
84	InstallFile(installPath OutputPath, srcPath Path, deps ...Path) OutputPath
85	InstallFileName(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
86	InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath
87	CheckbuildFile(srcPath Path)
88
89	AddMissingDependencies(deps []string)
90
91	InstallInData() bool
92	InstallInSanitizerDir() bool
93
94	RequiredModuleNames() []string
95}
96
97type Module interface {
98	blueprint.Module
99
100	GenerateAndroidBuildActions(ModuleContext)
101	DepsMutator(BottomUpMutatorContext)
102
103	base() *ModuleBase
104	Enabled() bool
105	Target() Target
106	InstallInData() bool
107	InstallInSanitizerDir() bool
108	SkipInstall()
109}
110
111type nameProperties struct {
112	// The name of the module.  Must be unique across all modules.
113	Name string
114}
115
116type commonProperties struct {
117	Tags []string
118
119	// emit build rules for this module
120	Enabled *bool `android:"arch_variant"`
121
122	// control whether this module compiles for 32-bit, 64-bit, or both.  Possible values
123	// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
124	// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
125	// platform
126	Compile_multilib string `android:"arch_variant"`
127
128	Target struct {
129		Host struct {
130			Compile_multilib string
131		}
132		Android struct {
133			Compile_multilib string
134		}
135	}
136
137	Default_multilib string `blueprint:"mutated"`
138
139	// whether this is a proprietary vendor module, and should be installed into /vendor
140	Proprietary bool
141
142	// vendor who owns this module
143	Owner string
144
145	// whether this module is device specific and should be installed into /vendor
146	Vendor bool
147
148	// *.logtags files, to combine together in order to generate the /system/etc/event-log-tags
149	// file
150	Logtags []string
151
152	// init.rc files to be installed if this module is installed
153	Init_rc []string
154
155	// names of other modules to install if this module is installed
156	Required []string
157
158	// Set by TargetMutator
159	CompileTarget  Target `blueprint:"mutated"`
160	CompilePrimary bool   `blueprint:"mutated"`
161
162	// Set by InitAndroidModule
163	HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
164	ArchSpecific          bool                  `blueprint:"mutated"`
165
166	SkipInstall bool `blueprint:"mutated"`
167}
168
169type hostAndDeviceProperties struct {
170	Host_supported   *bool
171	Device_supported *bool
172}
173
174type Multilib string
175
176const (
177	MultilibBoth    Multilib = "both"
178	MultilibFirst   Multilib = "first"
179	MultilibCommon  Multilib = "common"
180	MultilibDefault Multilib = ""
181)
182
183type HostOrDeviceSupported int
184
185const (
186	_ HostOrDeviceSupported = iota
187	HostSupported
188	HostSupportedNoCross
189	DeviceSupported
190	HostAndDeviceSupported
191	HostAndDeviceDefault
192	NeitherHostNorDeviceSupported
193)
194
195func InitAndroidModule(m Module,
196	propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
197
198	base := m.base()
199	base.module = m
200
201	propertyStructs = append(propertyStructs,
202		&base.nameProperties,
203		&base.commonProperties,
204		&base.variableProperties)
205
206	return m, propertyStructs
207}
208
209func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib,
210	propertyStructs ...interface{}) (blueprint.Module, []interface{}) {
211
212	_, propertyStructs = InitAndroidModule(m, propertyStructs...)
213
214	base := m.base()
215	base.commonProperties.HostOrDeviceSupported = hod
216	base.commonProperties.Default_multilib = string(defaultMultilib)
217	base.commonProperties.ArchSpecific = true
218
219	switch hod {
220	case HostAndDeviceSupported:
221		// Default to module to device supported, host not supported, can override in module
222		// properties
223		base.hostAndDeviceProperties.Device_supported = boolPtr(true)
224		fallthrough
225	case HostAndDeviceDefault:
226		propertyStructs = append(propertyStructs, &base.hostAndDeviceProperties)
227	}
228
229	return InitArchModule(m, propertyStructs...)
230}
231
232// A ModuleBase object contains the properties that are common to all Android
233// modules.  It should be included as an anonymous field in every module
234// struct definition.  InitAndroidModule should then be called from the module's
235// factory function, and the return values from InitAndroidModule should be
236// returned from the factory function.
237//
238// The ModuleBase type is responsible for implementing the GenerateBuildActions
239// method to support the blueprint.Module interface. This method will then call
240// the module's GenerateAndroidBuildActions method once for each build variant
241// that is to be built. GenerateAndroidBuildActions is passed a
242// AndroidModuleContext rather than the usual blueprint.ModuleContext.
243// AndroidModuleContext exposes extra functionality specific to the Android build
244// system including details about the particular build variant that is to be
245// generated.
246//
247// For example:
248//
249//     import (
250//         "android/soong/android"
251//         "github.com/google/blueprint"
252//     )
253//
254//     type myModule struct {
255//         android.ModuleBase
256//         properties struct {
257//             MyProperty string
258//         }
259//     }
260//
261//     func NewMyModule() (blueprint.Module, []interface{}) {
262//         m := &myModule{}
263//         return android.InitAndroidModule(m, &m.properties)
264//     }
265//
266//     func (m *myModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
267//         // Get the CPU architecture for the current build variant.
268//         variantArch := ctx.Arch()
269//
270//         // ...
271//     }
272type ModuleBase struct {
273	// Putting the curiously recurring thing pointing to the thing that contains
274	// the thing pattern to good use.
275	module Module
276
277	nameProperties          nameProperties
278	commonProperties        commonProperties
279	variableProperties      variableProperties
280	hostAndDeviceProperties hostAndDeviceProperties
281	generalProperties       []interface{}
282	archProperties          []interface{}
283	customizableProperties  []interface{}
284
285	noAddressSanitizer bool
286	installFiles       Paths
287	checkbuildFiles    Paths
288
289	// Used by buildTargetSingleton to create checkbuild and per-directory build targets
290	// Only set on the final variant of each module
291	installTarget    string
292	checkbuildTarget string
293	blueprintDir     string
294
295	hooks hooks
296}
297
298// Name returns the name of the module.  It may be overridden by individual module types, for
299// example prebuilts will prepend prebuilt_ to the name.
300func (a *ModuleBase) Name() string {
301	return a.nameProperties.Name
302}
303
304// BaseModuleName returns the name of the module as specified in the blueprints file.
305func (a *ModuleBase) BaseModuleName() string {
306	return a.nameProperties.Name
307}
308
309func (a *ModuleBase) base() *ModuleBase {
310	return a
311}
312
313func (a *ModuleBase) SetTarget(target Target, primary bool) {
314	a.commonProperties.CompileTarget = target
315	a.commonProperties.CompilePrimary = primary
316}
317
318func (a *ModuleBase) Target() Target {
319	return a.commonProperties.CompileTarget
320}
321
322func (a *ModuleBase) TargetPrimary() bool {
323	return a.commonProperties.CompilePrimary
324}
325
326func (a *ModuleBase) Os() OsType {
327	return a.Target().Os
328}
329
330func (a *ModuleBase) Host() bool {
331	return a.Os().Class == Host || a.Os().Class == HostCross
332}
333
334func (a *ModuleBase) Arch() Arch {
335	return a.Target().Arch
336}
337
338func (a *ModuleBase) ArchSpecific() bool {
339	return a.commonProperties.ArchSpecific
340}
341
342func (a *ModuleBase) OsClassSupported() []OsClass {
343	switch a.commonProperties.HostOrDeviceSupported {
344	case HostSupported:
345		return []OsClass{Host, HostCross}
346	case HostSupportedNoCross:
347		return []OsClass{Host}
348	case DeviceSupported:
349		return []OsClass{Device}
350	case HostAndDeviceSupported:
351		var supported []OsClass
352		if Bool(a.hostAndDeviceProperties.Host_supported) {
353			supported = append(supported, Host, HostCross)
354		}
355		if Bool(a.hostAndDeviceProperties.Device_supported) {
356			supported = append(supported, Device)
357		}
358		return supported
359	default:
360		return nil
361	}
362}
363
364func (a *ModuleBase) DeviceSupported() bool {
365	return a.commonProperties.HostOrDeviceSupported == DeviceSupported ||
366		a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
367			Bool(a.hostAndDeviceProperties.Device_supported)
368}
369
370func (a *ModuleBase) Enabled() bool {
371	if a.commonProperties.Enabled == nil {
372		return !a.Os().DefaultDisabled
373	}
374	return *a.commonProperties.Enabled
375}
376
377func (a *ModuleBase) SkipInstall() {
378	a.commonProperties.SkipInstall = true
379}
380
381func (a *ModuleBase) computeInstallDeps(
382	ctx blueprint.ModuleContext) Paths {
383
384	result := Paths{}
385	ctx.VisitDepsDepthFirstIf(isFileInstaller,
386		func(m blueprint.Module) {
387			fileInstaller := m.(fileInstaller)
388			files := fileInstaller.filesToInstall()
389			result = append(result, files...)
390		})
391
392	return result
393}
394
395func (a *ModuleBase) filesToInstall() Paths {
396	return a.installFiles
397}
398
399func (p *ModuleBase) NoAddressSanitizer() bool {
400	return p.noAddressSanitizer
401}
402
403func (p *ModuleBase) InstallInData() bool {
404	return false
405}
406
407func (p *ModuleBase) InstallInSanitizerDir() bool {
408	return false
409}
410
411func (a *ModuleBase) generateModuleTarget(ctx blueprint.ModuleContext) {
412	allInstalledFiles := Paths{}
413	allCheckbuildFiles := Paths{}
414	ctx.VisitAllModuleVariants(func(module blueprint.Module) {
415		a := module.(Module).base()
416		allInstalledFiles = append(allInstalledFiles, a.installFiles...)
417		allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
418	})
419
420	deps := []string{}
421
422	if len(allInstalledFiles) > 0 {
423		name := ctx.ModuleName() + "-install"
424		ctx.Build(pctx, blueprint.BuildParams{
425			Rule:      blueprint.Phony,
426			Outputs:   []string{name},
427			Implicits: allInstalledFiles.Strings(),
428			Optional:  ctx.Config().(Config).EmbeddedInMake(),
429		})
430		deps = append(deps, name)
431		a.installTarget = name
432	}
433
434	if len(allCheckbuildFiles) > 0 {
435		name := ctx.ModuleName() + "-checkbuild"
436		ctx.Build(pctx, blueprint.BuildParams{
437			Rule:      blueprint.Phony,
438			Outputs:   []string{name},
439			Implicits: allCheckbuildFiles.Strings(),
440			Optional:  true,
441		})
442		deps = append(deps, name)
443		a.checkbuildTarget = name
444	}
445
446	if len(deps) > 0 {
447		suffix := ""
448		if ctx.Config().(Config).EmbeddedInMake() {
449			suffix = "-soong"
450		}
451
452		ctx.Build(pctx, blueprint.BuildParams{
453			Rule:      blueprint.Phony,
454			Outputs:   []string{ctx.ModuleName() + suffix},
455			Implicits: deps,
456			Optional:  true,
457		})
458
459		a.blueprintDir = ctx.ModuleDir()
460	}
461}
462
463func (a *ModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl {
464	return androidBaseContextImpl{
465		target:        a.commonProperties.CompileTarget,
466		targetPrimary: a.commonProperties.CompilePrimary,
467		vendor:        a.commonProperties.Proprietary || a.commonProperties.Vendor,
468		config:        ctx.Config().(Config),
469	}
470}
471
472func (a *ModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
473	androidCtx := &androidModuleContext{
474		module:                 a.module,
475		ModuleContext:          ctx,
476		androidBaseContextImpl: a.androidBaseContextFactory(ctx),
477		installDeps:            a.computeInstallDeps(ctx),
478		installFiles:           a.installFiles,
479		missingDeps:            ctx.GetMissingDependencies(),
480	}
481
482	if a.Enabled() {
483		a.module.GenerateAndroidBuildActions(androidCtx)
484		if ctx.Failed() {
485			return
486		}
487
488		a.installFiles = append(a.installFiles, androidCtx.installFiles...)
489		a.checkbuildFiles = append(a.checkbuildFiles, androidCtx.checkbuildFiles...)
490	}
491
492	if a == ctx.FinalModule().(Module).base() {
493		a.generateModuleTarget(ctx)
494		if ctx.Failed() {
495			return
496		}
497	}
498}
499
500type androidBaseContextImpl struct {
501	target        Target
502	targetPrimary bool
503	debug         bool
504	vendor        bool
505	config        Config
506}
507
508type androidModuleContext struct {
509	blueprint.ModuleContext
510	androidBaseContextImpl
511	installDeps     Paths
512	installFiles    Paths
513	checkbuildFiles Paths
514	missingDeps     []string
515	module          Module
516}
517
518func (a *androidModuleContext) ninjaError(outputs []string, err error) {
519	a.ModuleContext.Build(pctx, blueprint.BuildParams{
520		Rule:     ErrorRule,
521		Outputs:  outputs,
522		Optional: true,
523		Args: map[string]string{
524			"error": err.Error(),
525		},
526	})
527	return
528}
529
530func (a *androidModuleContext) Build(pctx blueprint.PackageContext, params blueprint.BuildParams) {
531	if a.missingDeps != nil {
532		a.ninjaError(params.Outputs, fmt.Errorf("module %s missing dependencies: %s\n",
533			a.ModuleName(), strings.Join(a.missingDeps, ", ")))
534		return
535	}
536
537	params.Optional = true
538	a.ModuleContext.Build(pctx, params)
539}
540
541func (a *androidModuleContext) ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) {
542	bparams := blueprint.BuildParams{
543		Rule:            params.Rule,
544		Deps:            params.Deps,
545		Outputs:         params.Outputs.Strings(),
546		ImplicitOutputs: params.ImplicitOutputs.Strings(),
547		Inputs:          params.Inputs.Strings(),
548		Implicits:       params.Implicits.Strings(),
549		OrderOnly:       params.OrderOnly.Strings(),
550		Args:            params.Args,
551		Optional:        !params.Default,
552	}
553
554	if params.Depfile != nil {
555		bparams.Depfile = params.Depfile.String()
556	}
557	if params.Output != nil {
558		bparams.Outputs = append(bparams.Outputs, params.Output.String())
559	}
560	if params.ImplicitOutput != nil {
561		bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
562	}
563	if params.Input != nil {
564		bparams.Inputs = append(bparams.Inputs, params.Input.String())
565	}
566	if params.Implicit != nil {
567		bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
568	}
569
570	if a.missingDeps != nil {
571		a.ninjaError(bparams.Outputs, fmt.Errorf("module %s missing dependencies: %s\n",
572			a.ModuleName(), strings.Join(a.missingDeps, ", ")))
573		return
574	}
575
576	a.ModuleContext.Build(pctx, bparams)
577}
578
579func (a *androidModuleContext) GetMissingDependencies() []string {
580	return a.missingDeps
581}
582
583func (a *androidModuleContext) AddMissingDependencies(deps []string) {
584	if deps != nil {
585		a.missingDeps = append(a.missingDeps, deps...)
586	}
587}
588
589func (a *androidBaseContextImpl) Target() Target {
590	return a.target
591}
592
593func (a *androidBaseContextImpl) TargetPrimary() bool {
594	return a.targetPrimary
595}
596
597func (a *androidBaseContextImpl) Arch() Arch {
598	return a.target.Arch
599}
600
601func (a *androidBaseContextImpl) Os() OsType {
602	return a.target.Os
603}
604
605func (a *androidBaseContextImpl) Host() bool {
606	return a.target.Os.Class == Host || a.target.Os.Class == HostCross
607}
608
609func (a *androidBaseContextImpl) Device() bool {
610	return a.target.Os.Class == Device
611}
612
613func (a *androidBaseContextImpl) Darwin() bool {
614	return a.target.Os == Darwin
615}
616
617func (a *androidBaseContextImpl) Debug() bool {
618	return a.debug
619}
620
621func (a *androidBaseContextImpl) PrimaryArch() bool {
622	return a.target.Arch.ArchType == a.config.Targets[a.target.Os.Class][0].Arch.ArchType
623}
624
625func (a *androidBaseContextImpl) AConfig() Config {
626	return a.config
627}
628
629func (a *androidBaseContextImpl) DeviceConfig() DeviceConfig {
630	return DeviceConfig{a.config.deviceConfig}
631}
632
633func (a *androidBaseContextImpl) Vendor() bool {
634	return a.vendor
635}
636
637func (a *androidModuleContext) InstallInData() bool {
638	return a.module.InstallInData()
639}
640
641func (a *androidModuleContext) InstallInSanitizerDir() bool {
642	return a.module.InstallInSanitizerDir()
643}
644
645func (a *androidModuleContext) InstallFileName(installPath OutputPath, name string, srcPath Path,
646	deps ...Path) OutputPath {
647
648	fullInstallPath := installPath.Join(a, name)
649	a.module.base().hooks.runInstallHooks(a, fullInstallPath, false)
650
651	if !a.module.base().commonProperties.SkipInstall &&
652		(!a.Device() || !a.AConfig().SkipDeviceInstall()) {
653
654		deps = append(deps, a.installDeps...)
655
656		var implicitDeps, orderOnlyDeps Paths
657
658		if a.Host() {
659			// Installed host modules might be used during the build, depend directly on their
660			// dependencies so their timestamp is updated whenever their dependency is updated
661			implicitDeps = deps
662		} else {
663			orderOnlyDeps = deps
664		}
665
666		a.ModuleBuild(pctx, ModuleBuildParams{
667			Rule:      Cp,
668			Output:    fullInstallPath,
669			Input:     srcPath,
670			Implicits: implicitDeps,
671			OrderOnly: orderOnlyDeps,
672			Default:   !a.AConfig().EmbeddedInMake(),
673		})
674
675		a.installFiles = append(a.installFiles, fullInstallPath)
676	}
677	a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
678	return fullInstallPath
679}
680
681func (a *androidModuleContext) InstallFile(installPath OutputPath, srcPath Path, deps ...Path) OutputPath {
682	return a.InstallFileName(installPath, filepath.Base(srcPath.String()), srcPath, deps...)
683}
684
685func (a *androidModuleContext) InstallSymlink(installPath OutputPath, name string, srcPath OutputPath) OutputPath {
686	fullInstallPath := installPath.Join(a, name)
687	a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
688
689	if !a.module.base().commonProperties.SkipInstall &&
690		(!a.Device() || !a.AConfig().SkipDeviceInstall()) {
691
692		a.ModuleBuild(pctx, ModuleBuildParams{
693			Rule:      Symlink,
694			Output:    fullInstallPath,
695			OrderOnly: Paths{srcPath},
696			Default:   !a.AConfig().EmbeddedInMake(),
697			Args: map[string]string{
698				"fromPath": srcPath.String(),
699			},
700		})
701
702		a.installFiles = append(a.installFiles, fullInstallPath)
703		a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
704	}
705	return fullInstallPath
706}
707
708func (a *androidModuleContext) CheckbuildFile(srcPath Path) {
709	a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
710}
711
712type fileInstaller interface {
713	filesToInstall() Paths
714}
715
716func isFileInstaller(m blueprint.Module) bool {
717	_, ok := m.(fileInstaller)
718	return ok
719}
720
721func isAndroidModule(m blueprint.Module) bool {
722	_, ok := m.(Module)
723	return ok
724}
725
726func findStringInSlice(str string, slice []string) int {
727	for i, s := range slice {
728		if s == str {
729			return i
730		}
731	}
732	return -1
733}
734
735func SrcIsModule(s string) string {
736	if len(s) > 1 && s[0] == ':' {
737		return s[1:]
738	}
739	return ""
740}
741
742type sourceDependencyTag struct {
743	blueprint.BaseDependencyTag
744}
745
746var SourceDepTag sourceDependencyTag
747
748// Returns a list of modules that must be depended on to satisfy filegroup or generated sources
749// modules listed in srcFiles using ":module" syntax
750func ExtractSourcesDeps(ctx BottomUpMutatorContext, srcFiles []string) {
751	var deps []string
752	for _, s := range srcFiles {
753		if m := SrcIsModule(s); m != "" {
754			deps = append(deps, m)
755		}
756	}
757
758	ctx.AddDependency(ctx.Module(), SourceDepTag, deps...)
759}
760
761type SourceFileProducer interface {
762	Srcs() Paths
763}
764
765// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.
766// ExtractSourcesDeps must have already been called during the dependency resolution phase.
767func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) Paths {
768	return ctx.ExpandSourcesSubDir(srcFiles, excludes, "")
769}
770
771func (ctx *androidModuleContext) ExpandSourcesSubDir(srcFiles, excludes []string, subDir string) Paths {
772	prefix := PathForModuleSrc(ctx).String()
773
774	for i, e := range excludes {
775		j := findStringInSlice(e, srcFiles)
776		if j != -1 {
777			srcFiles = append(srcFiles[:j], srcFiles[j+1:]...)
778		}
779
780		excludes[i] = filepath.Join(prefix, e)
781	}
782
783	expandedSrcFiles := make(Paths, 0, len(srcFiles))
784	for _, s := range srcFiles {
785		if m := SrcIsModule(s); m != "" {
786			module := ctx.GetDirectDepWithTag(m, SourceDepTag)
787			if srcProducer, ok := module.(SourceFileProducer); ok {
788				expandedSrcFiles = append(expandedSrcFiles, srcProducer.Srcs()...)
789			} else {
790				ctx.ModuleErrorf("srcs dependency %q is not a source file producing module", m)
791			}
792		} else if pathtools.IsGlob(s) {
793			globbedSrcFiles := ctx.Glob(filepath.Join(prefix, s), excludes)
794			expandedSrcFiles = append(expandedSrcFiles, globbedSrcFiles...)
795			for i, s := range expandedSrcFiles {
796				expandedSrcFiles[i] = s.(ModuleSrcPath).WithSubDir(ctx, subDir)
797			}
798		} else {
799			s := PathForModuleSrc(ctx, s).WithSubDir(ctx, subDir)
800			expandedSrcFiles = append(expandedSrcFiles, s)
801		}
802	}
803
804	return expandedSrcFiles
805}
806
807func (ctx *androidModuleContext) RequiredModuleNames() []string {
808	return ctx.module.base().commonProperties.Required
809}
810
811func (ctx *androidModuleContext) Glob(globPattern string, excludes []string) Paths {
812	ret, err := ctx.GlobWithDeps(globPattern, excludes)
813	if err != nil {
814		ctx.ModuleErrorf("glob: %s", err.Error())
815	}
816	return pathsForModuleSrcFromFullPath(ctx, ret)
817}
818
819func init() {
820	RegisterSingletonType("buildtarget", BuildTargetSingleton)
821}
822
823func BuildTargetSingleton() blueprint.Singleton {
824	return &buildTargetSingleton{}
825}
826
827type buildTargetSingleton struct{}
828
829func (c *buildTargetSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
830	checkbuildDeps := []string{}
831
832	dirModules := make(map[string][]string)
833
834	ctx.VisitAllModules(func(module blueprint.Module) {
835		if a, ok := module.(Module); ok {
836			blueprintDir := a.base().blueprintDir
837			installTarget := a.base().installTarget
838			checkbuildTarget := a.base().checkbuildTarget
839
840			if checkbuildTarget != "" {
841				checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
842				dirModules[blueprintDir] = append(dirModules[blueprintDir], checkbuildTarget)
843			}
844
845			if installTarget != "" {
846				dirModules[blueprintDir] = append(dirModules[blueprintDir], installTarget)
847			}
848		}
849	})
850
851	suffix := ""
852	if ctx.Config().(Config).EmbeddedInMake() {
853		suffix = "-soong"
854	}
855
856	// Create a top-level checkbuild target that depends on all modules
857	ctx.Build(pctx, blueprint.BuildParams{
858		Rule:      blueprint.Phony,
859		Outputs:   []string{"checkbuild" + suffix},
860		Implicits: checkbuildDeps,
861		Optional:  true,
862	})
863
864	// Create a mm/<directory> target that depends on all modules in a directory
865	dirs := sortedKeys(dirModules)
866	for _, dir := range dirs {
867		ctx.Build(pctx, blueprint.BuildParams{
868			Rule:      blueprint.Phony,
869			Outputs:   []string{filepath.Join("mm", dir)},
870			Implicits: dirModules[dir],
871			// HACK: checkbuild should be an optional build, but force it
872			// enabled for now in standalone builds
873			Optional: ctx.Config().(Config).EmbeddedInMake(),
874		})
875	}
876}
877
878type AndroidModulesByName struct {
879	slice []Module
880	ctx   interface {
881		ModuleName(blueprint.Module) string
882		ModuleSubDir(blueprint.Module) string
883	}
884}
885
886func (s AndroidModulesByName) Len() int { return len(s.slice) }
887func (s AndroidModulesByName) Less(i, j int) bool {
888	mi, mj := s.slice[i], s.slice[j]
889	ni, nj := s.ctx.ModuleName(mi), s.ctx.ModuleName(mj)
890
891	if ni != nj {
892		return ni < nj
893	} else {
894		return s.ctx.ModuleSubDir(mi) < s.ctx.ModuleSubDir(mj)
895	}
896}
897func (s AndroidModulesByName) Swap(i, j int) { s.slice[i], s.slice[j] = s.slice[j], s.slice[i] }
898