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