• 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	"os"
20	"path/filepath"
21	"reflect"
22	"regexp"
23	"sort"
24	"strings"
25
26	"github.com/google/blueprint"
27	"github.com/google/blueprint/bootstrap"
28	"github.com/google/blueprint/pathtools"
29)
30
31var absSrcDir string
32
33// PathContext is the subset of a (Module|Singleton)Context required by the
34// Path methods.
35type PathContext interface {
36	Config() Config
37	AddNinjaFileDeps(deps ...string)
38}
39
40type PathGlobContext interface {
41	PathContext
42	GlobWithDeps(globPattern string, excludes []string) ([]string, error)
43}
44
45var _ PathContext = SingletonContext(nil)
46var _ PathContext = ModuleContext(nil)
47
48// "Null" path context is a minimal path context for a given config.
49type NullPathContext struct {
50	config Config
51}
52
53func (NullPathContext) AddNinjaFileDeps(...string) {}
54func (ctx NullPathContext) Config() Config         { return ctx.config }
55
56// EarlyModulePathContext is a subset of EarlyModuleContext methods required by the
57// Path methods. These path methods can be called before any mutators have run.
58type EarlyModulePathContext interface {
59	PathGlobContext
60
61	ModuleDir() string
62	ModuleErrorf(fmt string, args ...interface{})
63}
64
65var _ EarlyModulePathContext = ModuleContext(nil)
66
67// Glob globs files and directories matching globPattern relative to ModuleDir(),
68// paths in the excludes parameter will be omitted.
69func Glob(ctx EarlyModulePathContext, globPattern string, excludes []string) Paths {
70	ret, err := ctx.GlobWithDeps(globPattern, excludes)
71	if err != nil {
72		ctx.ModuleErrorf("glob: %s", err.Error())
73	}
74	return pathsForModuleSrcFromFullPath(ctx, ret, true)
75}
76
77// GlobFiles globs *only* files (not directories) matching globPattern relative to ModuleDir().
78// Paths in the excludes parameter will be omitted.
79func GlobFiles(ctx EarlyModulePathContext, globPattern string, excludes []string) Paths {
80	ret, err := ctx.GlobWithDeps(globPattern, excludes)
81	if err != nil {
82		ctx.ModuleErrorf("glob: %s", err.Error())
83	}
84	return pathsForModuleSrcFromFullPath(ctx, ret, false)
85}
86
87// ModuleWithDepsPathContext is a subset of *ModuleContext methods required by
88// the Path methods that rely on module dependencies having been resolved.
89type ModuleWithDepsPathContext interface {
90	EarlyModulePathContext
91	VisitDirectDepsBlueprint(visit func(blueprint.Module))
92	OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
93}
94
95// ModuleMissingDepsPathContext is a subset of *ModuleContext methods required by
96// the Path methods that rely on module dependencies having been resolved and ability to report
97// missing dependency errors.
98type ModuleMissingDepsPathContext interface {
99	ModuleWithDepsPathContext
100	AddMissingDependencies(missingDeps []string)
101}
102
103type ModuleInstallPathContext interface {
104	BaseModuleContext
105
106	InstallInData() bool
107	InstallInTestcases() bool
108	InstallInSanitizerDir() bool
109	InstallInRamdisk() bool
110	InstallInVendorRamdisk() bool
111	InstallInDebugRamdisk() bool
112	InstallInRecovery() bool
113	InstallInRoot() bool
114	InstallForceOS() (*OsType, *ArchType)
115}
116
117var _ ModuleInstallPathContext = ModuleContext(nil)
118
119// errorfContext is the interface containing the Errorf method matching the
120// Errorf method in blueprint.SingletonContext.
121type errorfContext interface {
122	Errorf(format string, args ...interface{})
123}
124
125var _ errorfContext = blueprint.SingletonContext(nil)
126
127// moduleErrorf is the interface containing the ModuleErrorf method matching
128// the ModuleErrorf method in blueprint.ModuleContext.
129type moduleErrorf interface {
130	ModuleErrorf(format string, args ...interface{})
131}
132
133var _ moduleErrorf = blueprint.ModuleContext(nil)
134
135// reportPathError will register an error with the attached context. It
136// attempts ctx.ModuleErrorf for a better error message first, then falls
137// back to ctx.Errorf.
138func reportPathError(ctx PathContext, err error) {
139	ReportPathErrorf(ctx, "%s", err.Error())
140}
141
142// ReportPathErrorf will register an error with the attached context. It
143// attempts ctx.ModuleErrorf for a better error message first, then falls
144// back to ctx.Errorf.
145func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) {
146	if mctx, ok := ctx.(moduleErrorf); ok {
147		mctx.ModuleErrorf(format, args...)
148	} else if ectx, ok := ctx.(errorfContext); ok {
149		ectx.Errorf(format, args...)
150	} else {
151		panic(fmt.Sprintf(format, args...))
152	}
153}
154
155func pathContextName(ctx PathContext, module blueprint.Module) string {
156	if x, ok := ctx.(interface{ ModuleName(blueprint.Module) string }); ok {
157		return x.ModuleName(module)
158	} else if x, ok := ctx.(interface{ OtherModuleName(blueprint.Module) string }); ok {
159		return x.OtherModuleName(module)
160	}
161	return "unknown"
162}
163
164type Path interface {
165	// Returns the path in string form
166	String() string
167
168	// Ext returns the extension of the last element of the path
169	Ext() string
170
171	// Base returns the last element of the path
172	Base() string
173
174	// Rel returns the portion of the path relative to the directory it was created from.  For
175	// example, Rel on a PathsForModuleSrc would return the path relative to the module source
176	// directory, and OutputPath.Join("foo").Rel() would return "foo".
177	Rel() string
178
179	// RelativeToTop returns a new path relative to the top, it is provided solely for use in tests.
180	//
181	// It is guaranteed to always return the same type as it is called on, e.g. if called on an
182	// InstallPath then the returned value can be converted to an InstallPath.
183	//
184	// A standard build has the following structure:
185	//   ../top/
186	//          out/ - make install files go here.
187	//          out/soong - this is the soongOutDir passed to NewTestConfig()
188	//          ... - the source files
189	//
190	// This function converts a path so that it appears relative to the ../top/ directory, i.e.
191	// * Make install paths, which have the pattern "soongOutDir/../<path>" are converted into the top
192	//   relative path "out/<path>"
193	// * Soong install paths and other writable paths, which have the pattern "soongOutDir/<path>" are
194	//   converted into the top relative path "out/soong/<path>".
195	// * Source paths are already relative to the top.
196	// * Phony paths are not relative to anything.
197	// * toolDepPath have an absolute but known value in so don't need making relative to anything in
198	//   order to test.
199	RelativeToTop() Path
200}
201
202const (
203	OutDir      = "out"
204	OutSoongDir = OutDir + "/soong"
205)
206
207// WritablePath is a type of path that can be used as an output for build rules.
208type WritablePath interface {
209	Path
210
211	// return the path to the build directory.
212	getSoongOutDir() string
213
214	// the writablePath method doesn't directly do anything,
215	// but it allows a struct to distinguish between whether or not it implements the WritablePath interface
216	writablePath()
217
218	ReplaceExtension(ctx PathContext, ext string) OutputPath
219}
220
221type genPathProvider interface {
222	genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath
223}
224type objPathProvider interface {
225	objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath
226}
227type resPathProvider interface {
228	resPathWithName(ctx ModuleOutPathContext, name string) ModuleResPath
229}
230
231// GenPathWithExt derives a new file path in ctx's generated sources directory
232// from the current path, but with the new extension.
233func GenPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleGenPath {
234	if path, ok := p.(genPathProvider); ok {
235		return path.genPathWithExt(ctx, subdir, ext)
236	}
237	ReportPathErrorf(ctx, "Tried to create generated file from unsupported path: %s(%s)", reflect.TypeOf(p).Name(), p)
238	return PathForModuleGen(ctx)
239}
240
241// ObjPathWithExt derives a new file path in ctx's object directory from the
242// current path, but with the new extension.
243func ObjPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleObjPath {
244	if path, ok := p.(objPathProvider); ok {
245		return path.objPathWithExt(ctx, subdir, ext)
246	}
247	ReportPathErrorf(ctx, "Tried to create object file from unsupported path: %s (%s)", reflect.TypeOf(p).Name(), p)
248	return PathForModuleObj(ctx)
249}
250
251// ResPathWithName derives a new path in ctx's output resource directory, using
252// the current path to create the directory name, and the `name` argument for
253// the filename.
254func ResPathWithName(ctx ModuleOutPathContext, p Path, name string) ModuleResPath {
255	if path, ok := p.(resPathProvider); ok {
256		return path.resPathWithName(ctx, name)
257	}
258	ReportPathErrorf(ctx, "Tried to create res file from unsupported path: %s (%s)", reflect.TypeOf(p).Name(), p)
259	return PathForModuleRes(ctx)
260}
261
262// OptionalPath is a container that may or may not contain a valid Path.
263type OptionalPath struct {
264	path          Path   // nil if invalid.
265	invalidReason string // Not applicable if path != nil. "" if the reason is unknown.
266}
267
268// OptionalPathForPath returns an OptionalPath containing the path.
269func OptionalPathForPath(path Path) OptionalPath {
270	return OptionalPath{path: path}
271}
272
273// InvalidOptionalPath returns an OptionalPath that is invalid with the given reason.
274func InvalidOptionalPath(reason string) OptionalPath {
275
276	return OptionalPath{invalidReason: reason}
277}
278
279// Valid returns whether there is a valid path
280func (p OptionalPath) Valid() bool {
281	return p.path != nil
282}
283
284// Path returns the Path embedded in this OptionalPath. You must be sure that
285// there is a valid path, since this method will panic if there is not.
286func (p OptionalPath) Path() Path {
287	if p.path == nil {
288		msg := "Requesting an invalid path"
289		if p.invalidReason != "" {
290			msg += ": " + p.invalidReason
291		}
292		panic(msg)
293	}
294	return p.path
295}
296
297// InvalidReason returns the reason that the optional path is invalid, or "" if it is valid.
298func (p OptionalPath) InvalidReason() string {
299	if p.path != nil {
300		return ""
301	}
302	if p.invalidReason == "" {
303		return "unknown"
304	}
305	return p.invalidReason
306}
307
308// AsPaths converts the OptionalPath into Paths.
309//
310// It returns nil if this is not valid, or a single length slice containing the Path embedded in
311// this OptionalPath.
312func (p OptionalPath) AsPaths() Paths {
313	if p.path == nil {
314		return nil
315	}
316	return Paths{p.path}
317}
318
319// RelativeToTop returns an OptionalPath with the path that was embedded having been replaced by the
320// result of calling Path.RelativeToTop on it.
321func (p OptionalPath) RelativeToTop() OptionalPath {
322	if p.path == nil {
323		return p
324	}
325	p.path = p.path.RelativeToTop()
326	return p
327}
328
329// String returns the string version of the Path, or "" if it isn't valid.
330func (p OptionalPath) String() string {
331	if p.path != nil {
332		return p.path.String()
333	} else {
334		return ""
335	}
336}
337
338// Paths is a slice of Path objects, with helpers to operate on the collection.
339type Paths []Path
340
341// RelativeToTop creates a new Paths containing the result of calling Path.RelativeToTop on each
342// item in this slice.
343func (p Paths) RelativeToTop() Paths {
344	ensureTestOnly()
345	if p == nil {
346		return p
347	}
348	ret := make(Paths, len(p))
349	for i, path := range p {
350		ret[i] = path.RelativeToTop()
351	}
352	return ret
353}
354
355func (paths Paths) containsPath(path Path) bool {
356	for _, p := range paths {
357		if p == path {
358			return true
359		}
360	}
361	return false
362}
363
364// PathsForSource returns Paths rooted from SrcDir, *not* rooted from the module's local source
365// directory
366func PathsForSource(ctx PathContext, paths []string) Paths {
367	ret := make(Paths, len(paths))
368	for i, path := range paths {
369		ret[i] = PathForSource(ctx, path)
370	}
371	return ret
372}
373
374// ExistentPathsForSources returns a list of Paths rooted from SrcDir, *not* rooted from the
375// module's local source directory, that are found in the tree. If any are not found, they are
376// omitted from the list, and dependencies are added so that we're re-run when they are added.
377func ExistentPathsForSources(ctx PathGlobContext, paths []string) Paths {
378	ret := make(Paths, 0, len(paths))
379	for _, path := range paths {
380		p := ExistentPathForSource(ctx, path)
381		if p.Valid() {
382			ret = append(ret, p.Path())
383		}
384	}
385	return ret
386}
387
388// PathsForModuleSrc returns a Paths{} containing the resolved references in paths:
389//   - filepath, relative to local module directory, resolves as a filepath relative to the local
390//     source directory
391//   - glob, relative to the local module directory, resolves as filepath(s), relative to the local
392//     source directory.
393//   - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer
394//     or OutputFileProducer. These resolve as a filepath to an output filepath or generated source
395//     filepath.
396//
397// Properties passed as the paths argument must have been annotated with struct tag
398// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
399// path_deps mutator.
400// If a requested module is not found as a dependency:
401//   - if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having
402//     missing dependencies
403//   - otherwise, a ModuleError is thrown.
404func PathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string) Paths {
405	return PathsForModuleSrcExcludes(ctx, paths, nil)
406}
407
408type SourceInput struct {
409	Context      ModuleMissingDepsPathContext
410	Paths        []string
411	ExcludePaths []string
412	IncludeDirs  bool
413}
414
415// PathsForModuleSrcExcludes returns a Paths{} containing the resolved references in paths, minus
416// those listed in excludes. Elements of paths and excludes are resolved as:
417//   - filepath, relative to local module directory, resolves as a filepath relative to the local
418//     source directory
419//   - glob, relative to the local module directory, resolves as filepath(s), relative to the local
420//     source directory. Not valid in excludes.
421//   - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer
422//     or OutputFileProducer. These resolve as a filepath to an output filepath or generated source
423//     filepath.
424//
425// excluding the items (similarly resolved
426// Properties passed as the paths argument must have been annotated with struct tag
427// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
428// path_deps mutator.
429// If a requested module is not found as a dependency:
430//   - if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having
431//     missing dependencies
432//   - otherwise, a ModuleError is thrown.
433func PathsForModuleSrcExcludes(ctx ModuleMissingDepsPathContext, paths, excludes []string) Paths {
434	return PathsRelativeToModuleSourceDir(SourceInput{
435		Context:      ctx,
436		Paths:        paths,
437		ExcludePaths: excludes,
438		IncludeDirs:  true,
439	})
440}
441
442func PathsRelativeToModuleSourceDir(input SourceInput) Paths {
443	ret, missingDeps := PathsAndMissingDepsRelativeToModuleSourceDir(input)
444	if input.Context.Config().AllowMissingDependencies() {
445		input.Context.AddMissingDependencies(missingDeps)
446	} else {
447		for _, m := range missingDeps {
448			input.Context.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m)
449		}
450	}
451	return ret
452}
453
454// OutputPaths is a slice of OutputPath objects, with helpers to operate on the collection.
455type OutputPaths []OutputPath
456
457// Paths returns the OutputPaths as a Paths
458func (p OutputPaths) Paths() Paths {
459	if p == nil {
460		return nil
461	}
462	ret := make(Paths, len(p))
463	for i, path := range p {
464		ret[i] = path
465	}
466	return ret
467}
468
469// Strings returns the string forms of the writable paths.
470func (p OutputPaths) Strings() []string {
471	if p == nil {
472		return nil
473	}
474	ret := make([]string, len(p))
475	for i, path := range p {
476		ret[i] = path.String()
477	}
478	return ret
479}
480
481// PathForGoBinary returns the path to the installed location of a bootstrap_go_binary module.
482func PathForGoBinary(ctx PathContext, goBinary bootstrap.GoBinaryTool) Path {
483	goBinaryInstallDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", false)
484	rel := Rel(ctx, goBinaryInstallDir.String(), goBinary.InstallPath())
485	return goBinaryInstallDir.Join(ctx, rel)
486}
487
488// Expands Paths to a SourceFileProducer or OutputFileProducer module dependency referenced via ":name" or ":name{.tag}" syntax.
489// If the dependency is not found, a missingErrorDependency is returned.
490// If the module dependency is not a SourceFileProducer or OutputFileProducer, appropriate errors will be returned.
491func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag string) (Paths, error) {
492	module := GetModuleFromPathDep(ctx, moduleName, tag)
493	if module == nil {
494		return nil, missingDependencyError{[]string{moduleName}}
495	}
496	if aModule, ok := module.(Module); ok && !aModule.Enabled() {
497		return nil, missingDependencyError{[]string{moduleName}}
498	}
499	if outProducer, ok := module.(OutputFileProducer); ok {
500		outputFiles, err := outProducer.OutputFiles(tag)
501		if err != nil {
502			return nil, fmt.Errorf("path dependency %q: %s", path, err)
503		}
504		return outputFiles, nil
505	} else if tag != "" {
506		return nil, fmt.Errorf("path dependency %q is not an output file producing module", path)
507	} else if goBinary, ok := module.(bootstrap.GoBinaryTool); ok {
508		goBinaryPath := PathForGoBinary(ctx, goBinary)
509		return Paths{goBinaryPath}, nil
510	} else if srcProducer, ok := module.(SourceFileProducer); ok {
511		return srcProducer.Srcs(), nil
512	} else {
513		return nil, fmt.Errorf("path dependency %q is not a source file producing module", path)
514	}
515}
516
517// GetModuleFromPathDep will return the module that was added as a dependency automatically for
518// properties tagged with `android:"path"` or manually using ExtractSourceDeps or
519// ExtractSourcesDeps.
520//
521// The moduleName and tag supplied to this should be the values returned from SrcIsModuleWithTag.
522// Or, if no tag is expected then the moduleName should be the value returned by  SrcIsModule and
523// the tag must be "".
524//
525// If tag is "" then the returned module will be the dependency that was added for ":moduleName".
526// Otherwise, it is the dependency that was added for ":moduleName{tag}".
527func GetModuleFromPathDep(ctx ModuleWithDepsPathContext, moduleName, tag string) blueprint.Module {
528	var found blueprint.Module
529	// The sourceOrOutputDepTag uniquely identifies the module dependency as it contains both the
530	// module name and the tag. Dependencies added automatically for properties tagged with
531	// `android:"path"` are deduped so are guaranteed to be unique. It is possible for duplicate
532	// dependencies to be added manually using ExtractSourcesDeps or ExtractSourceDeps but even then
533	// it will always be the case that the dependencies will be identical, i.e. the same tag and same
534	// moduleName referring to the same dependency module.
535	//
536	// It does not matter whether the moduleName is a fully qualified name or if the module
537	// dependency is a prebuilt module. All that matters is the same information is supplied to
538	// create the tag here as was supplied to create the tag when the dependency was added so that
539	// this finds the matching dependency module.
540	expectedTag := sourceOrOutputDepTag(moduleName, tag)
541	ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
542		depTag := ctx.OtherModuleDependencyTag(module)
543		if depTag == expectedTag {
544			found = module
545		}
546	})
547	return found
548}
549
550// PathsAndMissingDepsForModuleSrcExcludes returns a Paths{} containing the resolved references in
551// paths, minus those listed in excludes. Elements of paths and excludes are resolved as:
552//   - filepath, relative to local module directory, resolves as a filepath relative to the local
553//     source directory
554//   - glob, relative to the local module directory, resolves as filepath(s), relative to the local
555//     source directory. Not valid in excludes.
556//   - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer
557//     or OutputFileProducer. These resolve as a filepath to an output filepath or generated source
558//     filepath.
559//
560// and a list of the module names of missing module dependencies are returned as the second return.
561// Properties passed as the paths argument must have been annotated with struct tag
562// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
563// path_deps mutator.
564func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleMissingDepsPathContext, paths, excludes []string) (Paths, []string) {
565	return PathsAndMissingDepsRelativeToModuleSourceDir(SourceInput{
566		Context:      ctx,
567		Paths:        paths,
568		ExcludePaths: excludes,
569		IncludeDirs:  true,
570	})
571}
572
573func PathsAndMissingDepsRelativeToModuleSourceDir(input SourceInput) (Paths, []string) {
574	prefix := pathForModuleSrc(input.Context).String()
575
576	var expandedExcludes []string
577	if input.ExcludePaths != nil {
578		expandedExcludes = make([]string, 0, len(input.ExcludePaths))
579	}
580
581	var missingExcludeDeps []string
582	for _, e := range input.ExcludePaths {
583		if m, t := SrcIsModuleWithTag(e); m != "" {
584			modulePaths, err := getPathsFromModuleDep(input.Context, e, m, t)
585			if m, ok := err.(missingDependencyError); ok {
586				missingExcludeDeps = append(missingExcludeDeps, m.missingDeps...)
587			} else if err != nil {
588				reportPathError(input.Context, err)
589			} else {
590				expandedExcludes = append(expandedExcludes, modulePaths.Strings()...)
591			}
592		} else {
593			expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e))
594		}
595	}
596
597	if input.Paths == nil {
598		return nil, missingExcludeDeps
599	}
600
601	var missingDeps []string
602
603	expandedSrcFiles := make(Paths, 0, len(input.Paths))
604	for _, s := range input.Paths {
605		srcFiles, err := expandOneSrcPath(sourcePathInput{
606			context:          input.Context,
607			path:             s,
608			expandedExcludes: expandedExcludes,
609			includeDirs:      input.IncludeDirs,
610		})
611		if depErr, ok := err.(missingDependencyError); ok {
612			missingDeps = append(missingDeps, depErr.missingDeps...)
613		} else if err != nil {
614			reportPathError(input.Context, err)
615		}
616		expandedSrcFiles = append(expandedSrcFiles, srcFiles...)
617	}
618
619	return expandedSrcFiles, append(missingDeps, missingExcludeDeps...)
620}
621
622type missingDependencyError struct {
623	missingDeps []string
624}
625
626func (e missingDependencyError) Error() string {
627	return "missing dependencies: " + strings.Join(e.missingDeps, ", ")
628}
629
630type sourcePathInput struct {
631	context          ModuleWithDepsPathContext
632	path             string
633	expandedExcludes []string
634	includeDirs      bool
635}
636
637// Expands one path string to Paths rooted from the module's local source
638// directory, excluding those listed in the expandedExcludes.
639// Expands globs, references to SourceFileProducer or OutputFileProducer modules using the ":name" and ":name{.tag}" syntax.
640func expandOneSrcPath(input sourcePathInput) (Paths, error) {
641	excludePaths := func(paths Paths) Paths {
642		if len(input.expandedExcludes) == 0 {
643			return paths
644		}
645		remainder := make(Paths, 0, len(paths))
646		for _, p := range paths {
647			if !InList(p.String(), input.expandedExcludes) {
648				remainder = append(remainder, p)
649			}
650		}
651		return remainder
652	}
653	if m, t := SrcIsModuleWithTag(input.path); m != "" {
654		modulePaths, err := getPathsFromModuleDep(input.context, input.path, m, t)
655		if err != nil {
656			return nil, err
657		} else {
658			return excludePaths(modulePaths), nil
659		}
660	} else {
661		p := pathForModuleSrc(input.context, input.path)
662		if pathtools.IsGlob(input.path) {
663			paths := GlobFiles(input.context, p.String(), input.expandedExcludes)
664			return PathsWithModuleSrcSubDir(input.context, paths, ""), nil
665		} else {
666			if exists, _, err := input.context.Config().fs.Exists(p.String()); err != nil {
667				ReportPathErrorf(input.context, "%s: %s", p, err.Error())
668			} else if !exists && !input.context.Config().TestAllowNonExistentPaths {
669				ReportPathErrorf(input.context, "module source path %q does not exist", p)
670			} else if !input.includeDirs {
671				if isDir, err := input.context.Config().fs.IsDir(p.String()); exists && err != nil {
672					ReportPathErrorf(input.context, "%s: %s", p, err.Error())
673				} else if isDir {
674					ReportPathErrorf(input.context, "module source path %q is a directory", p)
675				}
676			}
677
678			if InList(p.String(), input.expandedExcludes) {
679				return nil, nil
680			}
681			return Paths{p}, nil
682		}
683	}
684}
685
686// pathsForModuleSrcFromFullPath returns Paths rooted from the module's local
687// source directory, but strip the local source directory from the beginning of
688// each string. If incDirs is false, strip paths with a trailing '/' from the list.
689// It intended for use in globs that only list files that exist, so it allows '$' in
690// filenames.
691func pathsForModuleSrcFromFullPath(ctx EarlyModulePathContext, paths []string, incDirs bool) Paths {
692	prefix := ctx.ModuleDir() + "/"
693	if prefix == "./" {
694		prefix = ""
695	}
696	ret := make(Paths, 0, len(paths))
697	for _, p := range paths {
698		if !incDirs && strings.HasSuffix(p, "/") {
699			continue
700		}
701		path := filepath.Clean(p)
702		if !strings.HasPrefix(path, prefix) {
703			ReportPathErrorf(ctx, "Path %q is not in module source directory %q", p, prefix)
704			continue
705		}
706
707		srcPath, err := safePathForSource(ctx, ctx.ModuleDir(), path[len(prefix):])
708		if err != nil {
709			reportPathError(ctx, err)
710			continue
711		}
712
713		srcPath.basePath.rel = srcPath.path
714
715		ret = append(ret, srcPath)
716	}
717	return ret
718}
719
720// PathsWithOptionalDefaultForModuleSrc returns Paths rooted from the module's local source
721// directory. If input is nil, use the default if it exists.  If input is empty, returns nil.
722func PathsWithOptionalDefaultForModuleSrc(ctx ModuleMissingDepsPathContext, input []string, def string) Paths {
723	if input != nil {
724		return PathsForModuleSrc(ctx, input)
725	}
726	// Use Glob so that if the default doesn't exist, a dependency is added so that when it
727	// is created, we're run again.
728	path := filepath.Join(ctx.ModuleDir(), def)
729	return Glob(ctx, path, nil)
730}
731
732// Strings returns the Paths in string form
733func (p Paths) Strings() []string {
734	if p == nil {
735		return nil
736	}
737	ret := make([]string, len(p))
738	for i, path := range p {
739		ret[i] = path.String()
740	}
741	return ret
742}
743
744func CopyOfPaths(paths Paths) Paths {
745	return append(Paths(nil), paths...)
746}
747
748// FirstUniquePaths returns all unique elements of a Paths, keeping the first copy of each.  It
749// modifies the Paths slice contents in place, and returns a subslice of the original slice.
750func FirstUniquePaths(list Paths) Paths {
751	// 128 was chosen based on BenchmarkFirstUniquePaths results.
752	if len(list) > 128 {
753		return firstUniquePathsMap(list)
754	}
755	return firstUniquePathsList(list)
756}
757
758// SortedUniquePaths returns all unique elements of a Paths in sorted order.  It modifies the
759// Paths slice contents in place, and returns a subslice of the original slice.
760func SortedUniquePaths(list Paths) Paths {
761	unique := FirstUniquePaths(list)
762	sort.Slice(unique, func(i, j int) bool {
763		return unique[i].String() < unique[j].String()
764	})
765	return unique
766}
767
768func firstUniquePathsList(list Paths) Paths {
769	k := 0
770outer:
771	for i := 0; i < len(list); i++ {
772		for j := 0; j < k; j++ {
773			if list[i] == list[j] {
774				continue outer
775			}
776		}
777		list[k] = list[i]
778		k++
779	}
780	return list[:k]
781}
782
783func firstUniquePathsMap(list Paths) Paths {
784	k := 0
785	seen := make(map[Path]bool, len(list))
786	for i := 0; i < len(list); i++ {
787		if seen[list[i]] {
788			continue
789		}
790		seen[list[i]] = true
791		list[k] = list[i]
792		k++
793	}
794	return list[:k]
795}
796
797// FirstUniqueInstallPaths returns all unique elements of an InstallPaths, keeping the first copy of each.  It
798// modifies the InstallPaths slice contents in place, and returns a subslice of the original slice.
799func FirstUniqueInstallPaths(list InstallPaths) InstallPaths {
800	// 128 was chosen based on BenchmarkFirstUniquePaths results.
801	if len(list) > 128 {
802		return firstUniqueInstallPathsMap(list)
803	}
804	return firstUniqueInstallPathsList(list)
805}
806
807func firstUniqueInstallPathsList(list InstallPaths) InstallPaths {
808	k := 0
809outer:
810	for i := 0; i < len(list); i++ {
811		for j := 0; j < k; j++ {
812			if list[i] == list[j] {
813				continue outer
814			}
815		}
816		list[k] = list[i]
817		k++
818	}
819	return list[:k]
820}
821
822func firstUniqueInstallPathsMap(list InstallPaths) InstallPaths {
823	k := 0
824	seen := make(map[InstallPath]bool, len(list))
825	for i := 0; i < len(list); i++ {
826		if seen[list[i]] {
827			continue
828		}
829		seen[list[i]] = true
830		list[k] = list[i]
831		k++
832	}
833	return list[:k]
834}
835
836// LastUniquePaths returns all unique elements of a Paths, keeping the last copy of each.  It
837// modifies the Paths slice contents in place, and returns a subslice of the original slice.
838func LastUniquePaths(list Paths) Paths {
839	totalSkip := 0
840	for i := len(list) - 1; i >= totalSkip; i-- {
841		skip := 0
842		for j := i - 1; j >= totalSkip; j-- {
843			if list[i] == list[j] {
844				skip++
845			} else {
846				list[j+skip] = list[j]
847			}
848		}
849		totalSkip += skip
850	}
851	return list[totalSkip:]
852}
853
854// ReversePaths returns a copy of a Paths in reverse order.
855func ReversePaths(list Paths) Paths {
856	if list == nil {
857		return nil
858	}
859	ret := make(Paths, len(list))
860	for i := range list {
861		ret[i] = list[len(list)-1-i]
862	}
863	return ret
864}
865
866func indexPathList(s Path, list []Path) int {
867	for i, l := range list {
868		if l == s {
869			return i
870		}
871	}
872
873	return -1
874}
875
876func inPathList(p Path, list []Path) bool {
877	return indexPathList(p, list) != -1
878}
879
880func FilterPathList(list []Path, filter []Path) (remainder []Path, filtered []Path) {
881	return FilterPathListPredicate(list, func(p Path) bool { return inPathList(p, filter) })
882}
883
884func FilterPathListPredicate(list []Path, predicate func(Path) bool) (remainder []Path, filtered []Path) {
885	for _, l := range list {
886		if predicate(l) {
887			filtered = append(filtered, l)
888		} else {
889			remainder = append(remainder, l)
890		}
891	}
892
893	return
894}
895
896// HasExt returns true of any of the paths have extension ext, otherwise false
897func (p Paths) HasExt(ext string) bool {
898	for _, path := range p {
899		if path.Ext() == ext {
900			return true
901		}
902	}
903
904	return false
905}
906
907// FilterByExt returns the subset of the paths that have extension ext
908func (p Paths) FilterByExt(ext string) Paths {
909	ret := make(Paths, 0, len(p))
910	for _, path := range p {
911		if path.Ext() == ext {
912			ret = append(ret, path)
913		}
914	}
915	return ret
916}
917
918// FilterOutByExt returns the subset of the paths that do not have extension ext
919func (p Paths) FilterOutByExt(ext string) Paths {
920	ret := make(Paths, 0, len(p))
921	for _, path := range p {
922		if path.Ext() != ext {
923			ret = append(ret, path)
924		}
925	}
926	return ret
927}
928
929// DirectorySortedPaths is a slice of paths that are sorted such that all files in a directory
930// (including subdirectories) are in a contiguous subslice of the list, and can be found in
931// O(log(N)) time using a binary search on the directory prefix.
932type DirectorySortedPaths Paths
933
934func PathsToDirectorySortedPaths(paths Paths) DirectorySortedPaths {
935	ret := append(DirectorySortedPaths(nil), paths...)
936	sort.Slice(ret, func(i, j int) bool {
937		return ret[i].String() < ret[j].String()
938	})
939	return ret
940}
941
942// PathsInDirectory returns a subslice of the DirectorySortedPaths as a Paths that contains all entries
943// that are in the specified directory and its subdirectories.
944func (p DirectorySortedPaths) PathsInDirectory(dir string) Paths {
945	prefix := filepath.Clean(dir) + "/"
946	start := sort.Search(len(p), func(i int) bool {
947		return prefix < p[i].String()
948	})
949
950	ret := p[start:]
951
952	end := sort.Search(len(ret), func(i int) bool {
953		return !strings.HasPrefix(ret[i].String(), prefix)
954	})
955
956	ret = ret[:end]
957
958	return Paths(ret)
959}
960
961// WritablePaths is a slice of WritablePath, used for multiple outputs.
962type WritablePaths []WritablePath
963
964// RelativeToTop creates a new WritablePaths containing the result of calling Path.RelativeToTop on
965// each item in this slice.
966func (p WritablePaths) RelativeToTop() WritablePaths {
967	ensureTestOnly()
968	if p == nil {
969		return p
970	}
971	ret := make(WritablePaths, len(p))
972	for i, path := range p {
973		ret[i] = path.RelativeToTop().(WritablePath)
974	}
975	return ret
976}
977
978// Strings returns the string forms of the writable paths.
979func (p WritablePaths) Strings() []string {
980	if p == nil {
981		return nil
982	}
983	ret := make([]string, len(p))
984	for i, path := range p {
985		ret[i] = path.String()
986	}
987	return ret
988}
989
990// Paths returns the WritablePaths as a Paths
991func (p WritablePaths) Paths() Paths {
992	if p == nil {
993		return nil
994	}
995	ret := make(Paths, len(p))
996	for i, path := range p {
997		ret[i] = path
998	}
999	return ret
1000}
1001
1002type basePath struct {
1003	path string
1004	rel  string
1005}
1006
1007func (p basePath) Ext() string {
1008	return filepath.Ext(p.path)
1009}
1010
1011func (p basePath) Base() string {
1012	return filepath.Base(p.path)
1013}
1014
1015func (p basePath) Rel() string {
1016	if p.rel != "" {
1017		return p.rel
1018	}
1019	return p.path
1020}
1021
1022func (p basePath) String() string {
1023	return p.path
1024}
1025
1026func (p basePath) withRel(rel string) basePath {
1027	p.path = filepath.Join(p.path, rel)
1028	p.rel = rel
1029	return p
1030}
1031
1032// SourcePath is a Path representing a file path rooted from SrcDir
1033type SourcePath struct {
1034	basePath
1035}
1036
1037func (p SourcePath) RelativeToTop() Path {
1038	ensureTestOnly()
1039	return p
1040}
1041
1042var _ Path = SourcePath{}
1043
1044func (p SourcePath) withRel(rel string) SourcePath {
1045	p.basePath = p.basePath.withRel(rel)
1046	return p
1047}
1048
1049// safePathForSource is for paths that we expect are safe -- only for use by go
1050// code that is embedding ninja variables in paths
1051func safePathForSource(ctx PathContext, pathComponents ...string) (SourcePath, error) {
1052	p, err := validateSafePath(pathComponents...)
1053	ret := SourcePath{basePath{p, ""}}
1054	if err != nil {
1055		return ret, err
1056	}
1057
1058	// absolute path already checked by validateSafePath
1059	// special-case api surface gen files for now
1060	if strings.HasPrefix(ret.String(), ctx.Config().soongOutDir) && !strings.Contains(ret.String(), ctx.Config().soongOutDir+"/.export") {
1061		return ret, fmt.Errorf("source path %q is in output", ret.String())
1062	}
1063
1064	return ret, err
1065}
1066
1067// pathForSource creates a SourcePath from pathComponents, but does not check that it exists.
1068func pathForSource(ctx PathContext, pathComponents ...string) (SourcePath, error) {
1069	p, err := validatePath(pathComponents...)
1070	ret := SourcePath{basePath{p, ""}}
1071	if err != nil {
1072		return ret, err
1073	}
1074
1075	// absolute path already checked by validatePath
1076	// special-case for now
1077	if strings.HasPrefix(ret.String(), ctx.Config().soongOutDir) && !strings.Contains(ret.String(), ctx.Config().soongOutDir+"/.export") {
1078		return ret, fmt.Errorf("source path %q is in output", ret.String())
1079	}
1080
1081	return ret, nil
1082}
1083
1084// existsWithDependencies returns true if the path exists, and adds appropriate dependencies to rerun if the
1085// path does not exist.
1086func existsWithDependencies(ctx PathGlobContext, path SourcePath) (exists bool, err error) {
1087	var files []string
1088
1089	// Use glob to produce proper dependencies, even though we only want
1090	// a single file.
1091	files, err = ctx.GlobWithDeps(path.String(), nil)
1092
1093	if err != nil {
1094		return false, fmt.Errorf("glob: %s", err.Error())
1095	}
1096
1097	return len(files) > 0, nil
1098}
1099
1100// PathForSource joins the provided path components and validates that the result
1101// neither escapes the source dir nor is in the out dir.
1102// On error, it will return a usable, but invalid SourcePath, and report a ModuleError.
1103func PathForSource(ctx PathContext, pathComponents ...string) SourcePath {
1104	path, err := pathForSource(ctx, pathComponents...)
1105	if err != nil {
1106		reportPathError(ctx, err)
1107	}
1108
1109	if pathtools.IsGlob(path.String()) {
1110		ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
1111	}
1112
1113	if modCtx, ok := ctx.(ModuleMissingDepsPathContext); ok && ctx.Config().AllowMissingDependencies() {
1114		exists, err := existsWithDependencies(modCtx, path)
1115		if err != nil {
1116			reportPathError(ctx, err)
1117		}
1118		if !exists {
1119			modCtx.AddMissingDependencies([]string{path.String()})
1120		}
1121	} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
1122		ReportPathErrorf(ctx, "%s: %s", path, err.Error())
1123	} else if !exists && !ctx.Config().TestAllowNonExistentPaths {
1124		ReportPathErrorf(ctx, "source path %q does not exist", path)
1125	}
1126	return path
1127}
1128
1129// MaybeExistentPathForSource joins the provided path components and validates that the result
1130// neither escapes the source dir nor is in the out dir.
1131// It does not validate whether the path exists.
1132func MaybeExistentPathForSource(ctx PathContext, pathComponents ...string) SourcePath {
1133	path, err := pathForSource(ctx, pathComponents...)
1134	if err != nil {
1135		reportPathError(ctx, err)
1136	}
1137
1138	if pathtools.IsGlob(path.String()) {
1139		ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
1140	}
1141	return path
1142}
1143
1144// ExistentPathForSource returns an OptionalPath with the SourcePath, rooted from SrcDir, *not*
1145// rooted from the module's local source directory, if the path exists, or an empty OptionalPath if
1146// it doesn't exist. Dependencies are added so that the ninja file will be regenerated if the state
1147// of the path changes.
1148func ExistentPathForSource(ctx PathGlobContext, pathComponents ...string) OptionalPath {
1149	path, err := pathForSource(ctx, pathComponents...)
1150	if err != nil {
1151		reportPathError(ctx, err)
1152		// No need to put the error message into the returned path since it has been reported already.
1153		return OptionalPath{}
1154	}
1155
1156	if pathtools.IsGlob(path.String()) {
1157		ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
1158		return OptionalPath{}
1159	}
1160
1161	exists, err := existsWithDependencies(ctx, path)
1162	if err != nil {
1163		reportPathError(ctx, err)
1164		return OptionalPath{}
1165	}
1166	if !exists {
1167		return InvalidOptionalPath(path.String() + " does not exist")
1168	}
1169	return OptionalPathForPath(path)
1170}
1171
1172func (p SourcePath) String() string {
1173	if p.path == "" {
1174		return "."
1175	}
1176	return p.path
1177}
1178
1179// Join creates a new SourcePath with paths... joined with the current path. The
1180// provided paths... may not use '..' to escape from the current path.
1181func (p SourcePath) Join(ctx PathContext, paths ...string) SourcePath {
1182	path, err := validatePath(paths...)
1183	if err != nil {
1184		reportPathError(ctx, err)
1185	}
1186	return p.withRel(path)
1187}
1188
1189// join is like Join but does less path validation.
1190func (p SourcePath) join(ctx PathContext, paths ...string) SourcePath {
1191	path, err := validateSafePath(paths...)
1192	if err != nil {
1193		reportPathError(ctx, err)
1194	}
1195	return p.withRel(path)
1196}
1197
1198// OverlayPath returns the overlay for `path' if it exists. This assumes that the
1199// SourcePath is the path to a resource overlay directory.
1200func (p SourcePath) OverlayPath(ctx ModuleMissingDepsPathContext, path Path) OptionalPath {
1201	var relDir string
1202	if srcPath, ok := path.(SourcePath); ok {
1203		relDir = srcPath.path
1204	} else {
1205		ReportPathErrorf(ctx, "Cannot find relative path for %s(%s)", reflect.TypeOf(path).Name(), path)
1206		// No need to put the error message into the returned path since it has been reported already.
1207		return OptionalPath{}
1208	}
1209	dir := filepath.Join(p.path, relDir)
1210	// Use Glob so that we are run again if the directory is added.
1211	if pathtools.IsGlob(dir) {
1212		ReportPathErrorf(ctx, "Path may not contain a glob: %s", dir)
1213	}
1214	paths, err := ctx.GlobWithDeps(dir, nil)
1215	if err != nil {
1216		ReportPathErrorf(ctx, "glob: %s", err.Error())
1217		return OptionalPath{}
1218	}
1219	if len(paths) == 0 {
1220		return InvalidOptionalPath(dir + " does not exist")
1221	}
1222	return OptionalPathForPath(PathForSource(ctx, paths[0]))
1223}
1224
1225// OutputPath is a Path representing an intermediates file path rooted from the build directory
1226type OutputPath struct {
1227	basePath
1228
1229	// The soong build directory, i.e. Config.SoongOutDir()
1230	soongOutDir string
1231
1232	fullPath string
1233}
1234
1235func (p OutputPath) withRel(rel string) OutputPath {
1236	p.basePath = p.basePath.withRel(rel)
1237	p.fullPath = filepath.Join(p.fullPath, rel)
1238	return p
1239}
1240
1241func (p OutputPath) WithoutRel() OutputPath {
1242	p.basePath.rel = filepath.Base(p.basePath.path)
1243	return p
1244}
1245
1246func (p OutputPath) getSoongOutDir() string {
1247	return p.soongOutDir
1248}
1249
1250func (p OutputPath) RelativeToTop() Path {
1251	return p.outputPathRelativeToTop()
1252}
1253
1254func (p OutputPath) outputPathRelativeToTop() OutputPath {
1255	p.fullPath = StringPathRelativeToTop(p.soongOutDir, p.fullPath)
1256	p.soongOutDir = OutSoongDir
1257	return p
1258}
1259
1260func (p OutputPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
1261	return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
1262}
1263
1264var _ Path = OutputPath{}
1265var _ WritablePath = OutputPath{}
1266var _ objPathProvider = OutputPath{}
1267
1268// toolDepPath is a Path representing a dependency of the build tool.
1269type toolDepPath struct {
1270	basePath
1271}
1272
1273func (t toolDepPath) RelativeToTop() Path {
1274	ensureTestOnly()
1275	return t
1276}
1277
1278var _ Path = toolDepPath{}
1279
1280// pathForBuildToolDep returns a toolDepPath representing the given path string.
1281// There is no validation for the path, as it is "trusted": It may fail
1282// normal validation checks. For example, it may be an absolute path.
1283// Only use this function to construct paths for dependencies of the build
1284// tool invocation.
1285func pathForBuildToolDep(ctx PathContext, path string) toolDepPath {
1286	return toolDepPath{basePath{path, ""}}
1287}
1288
1289// PathForOutput joins the provided paths and returns an OutputPath that is
1290// validated to not escape the build dir.
1291// On error, it will return a usable, but invalid OutputPath, and report a ModuleError.
1292func PathForOutput(ctx PathContext, pathComponents ...string) OutputPath {
1293	path, err := validatePath(pathComponents...)
1294	if err != nil {
1295		reportPathError(ctx, err)
1296	}
1297	fullPath := filepath.Join(ctx.Config().soongOutDir, path)
1298	path = fullPath[len(fullPath)-len(path):]
1299	return OutputPath{basePath{path, ""}, ctx.Config().soongOutDir, fullPath}
1300}
1301
1302// PathsForOutput returns Paths rooted from soongOutDir
1303func PathsForOutput(ctx PathContext, paths []string) WritablePaths {
1304	ret := make(WritablePaths, len(paths))
1305	for i, path := range paths {
1306		ret[i] = PathForOutput(ctx, path)
1307	}
1308	return ret
1309}
1310
1311func (p OutputPath) writablePath() {}
1312
1313func (p OutputPath) String() string {
1314	return p.fullPath
1315}
1316
1317// Join creates a new OutputPath with paths... joined with the current path. The
1318// provided paths... may not use '..' to escape from the current path.
1319func (p OutputPath) Join(ctx PathContext, paths ...string) OutputPath {
1320	path, err := validatePath(paths...)
1321	if err != nil {
1322		reportPathError(ctx, err)
1323	}
1324	return p.withRel(path)
1325}
1326
1327// ReplaceExtension creates a new OutputPath with the extension replaced with ext.
1328func (p OutputPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
1329	if strings.Contains(ext, "/") {
1330		ReportPathErrorf(ctx, "extension %q cannot contain /", ext)
1331	}
1332	ret := PathForOutput(ctx, pathtools.ReplaceExtension(p.path, ext))
1333	ret.rel = pathtools.ReplaceExtension(p.rel, ext)
1334	return ret
1335}
1336
1337// InSameDir creates a new OutputPath from the directory of the current OutputPath joined with the elements in paths.
1338func (p OutputPath) InSameDir(ctx PathContext, paths ...string) OutputPath {
1339	path, err := validatePath(paths...)
1340	if err != nil {
1341		reportPathError(ctx, err)
1342	}
1343
1344	ret := PathForOutput(ctx, filepath.Dir(p.path), path)
1345	ret.rel = filepath.Join(filepath.Dir(p.rel), path)
1346	return ret
1347}
1348
1349// PathForIntermediates returns an OutputPath representing the top-level
1350// intermediates directory.
1351func PathForIntermediates(ctx PathContext, paths ...string) OutputPath {
1352	path, err := validatePath(paths...)
1353	if err != nil {
1354		reportPathError(ctx, err)
1355	}
1356	return PathForOutput(ctx, ".intermediates", path)
1357}
1358
1359var _ genPathProvider = SourcePath{}
1360var _ objPathProvider = SourcePath{}
1361var _ resPathProvider = SourcePath{}
1362
1363// PathForModuleSrc returns a Path representing the paths... under the
1364// module's local source directory.
1365func PathForModuleSrc(ctx ModuleMissingDepsPathContext, pathComponents ...string) Path {
1366	// Just join the components textually just to make sure that it does not corrupt a fully qualified
1367	// module reference, e.g. if the pathComponents is "://other:foo" then using filepath.Join() or
1368	// validatePath() will corrupt it, e.g. replace "//" with "/". If the path is not a module
1369	// reference then it will be validated by expandOneSrcPath anyway when it calls expandOneSrcPath.
1370	p := strings.Join(pathComponents, string(filepath.Separator))
1371	paths, err := expandOneSrcPath(sourcePathInput{context: ctx, path: p, includeDirs: true})
1372	if err != nil {
1373		if depErr, ok := err.(missingDependencyError); ok {
1374			if ctx.Config().AllowMissingDependencies() {
1375				ctx.AddMissingDependencies(depErr.missingDeps)
1376			} else {
1377				ctx.ModuleErrorf(`%s, is the property annotated with android:"path"?`, depErr.Error())
1378			}
1379		} else {
1380			reportPathError(ctx, err)
1381		}
1382		return nil
1383	} else if len(paths) == 0 {
1384		ReportPathErrorf(ctx, "%q produced no files, expected exactly one", p)
1385		return nil
1386	} else if len(paths) > 1 {
1387		ReportPathErrorf(ctx, "%q produced %d files, expected exactly one", p, len(paths))
1388	}
1389	return paths[0]
1390}
1391
1392func pathForModuleSrc(ctx EarlyModulePathContext, paths ...string) SourcePath {
1393	p, err := validatePath(paths...)
1394	if err != nil {
1395		reportPathError(ctx, err)
1396	}
1397
1398	path, err := pathForSource(ctx, ctx.ModuleDir(), p)
1399	if err != nil {
1400		reportPathError(ctx, err)
1401	}
1402
1403	path.basePath.rel = p
1404
1405	return path
1406}
1407
1408// PathsWithModuleSrcSubDir takes a list of Paths and returns a new list of Paths where Rel() on each path
1409// will return the path relative to subDir in the module's source directory.  If any input paths are not located
1410// inside subDir then a path error will be reported.
1411func PathsWithModuleSrcSubDir(ctx EarlyModulePathContext, paths Paths, subDir string) Paths {
1412	paths = append(Paths(nil), paths...)
1413	subDirFullPath := pathForModuleSrc(ctx, subDir)
1414	for i, path := range paths {
1415		rel := Rel(ctx, subDirFullPath.String(), path.String())
1416		paths[i] = subDirFullPath.join(ctx, rel)
1417	}
1418	return paths
1419}
1420
1421// PathWithModuleSrcSubDir takes a Path and returns a Path where Rel() will return the path relative to subDir in the
1422// module's source directory.  If the input path is not located inside subDir then a path error will be reported.
1423func PathWithModuleSrcSubDir(ctx EarlyModulePathContext, path Path, subDir string) Path {
1424	subDirFullPath := pathForModuleSrc(ctx, subDir)
1425	rel := Rel(ctx, subDirFullPath.String(), path.String())
1426	return subDirFullPath.Join(ctx, rel)
1427}
1428
1429// OptionalPathForModuleSrc returns an OptionalPath. The OptionalPath contains a
1430// valid path if p is non-nil.
1431func OptionalPathForModuleSrc(ctx ModuleMissingDepsPathContext, p *string) OptionalPath {
1432	if p == nil {
1433		return OptionalPath{}
1434	}
1435	return OptionalPathForPath(PathForModuleSrc(ctx, *p))
1436}
1437
1438func (p SourcePath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath {
1439	return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
1440}
1441
1442func (p SourcePath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
1443	return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
1444}
1445
1446func (p SourcePath) resPathWithName(ctx ModuleOutPathContext, name string) ModuleResPath {
1447	// TODO: Use full directory if the new ctx is not the current ctx?
1448	return PathForModuleRes(ctx, p.path, name)
1449}
1450
1451// ModuleOutPath is a Path representing a module's output directory.
1452type ModuleOutPath struct {
1453	OutputPath
1454}
1455
1456func (p ModuleOutPath) RelativeToTop() Path {
1457	p.OutputPath = p.outputPathRelativeToTop()
1458	return p
1459}
1460
1461var _ Path = ModuleOutPath{}
1462var _ WritablePath = ModuleOutPath{}
1463
1464func (p ModuleOutPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
1465	return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
1466}
1467
1468// ModuleOutPathContext Subset of ModuleContext functions necessary for output path methods.
1469type ModuleOutPathContext interface {
1470	PathContext
1471
1472	ModuleName() string
1473	ModuleDir() string
1474	ModuleSubDir() string
1475}
1476
1477func pathForModuleOut(ctx ModuleOutPathContext) OutputPath {
1478	return PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir())
1479}
1480
1481// PathForModuleOut returns a Path representing the paths... under the module's
1482// output directory.
1483func PathForModuleOut(ctx ModuleOutPathContext, paths ...string) ModuleOutPath {
1484	p, err := validatePath(paths...)
1485	if err != nil {
1486		reportPathError(ctx, err)
1487	}
1488	return ModuleOutPath{
1489		OutputPath: pathForModuleOut(ctx).withRel(p),
1490	}
1491}
1492
1493// ModuleGenPath is a Path representing the 'gen' directory in a module's output
1494// directory. Mainly used for generated sources.
1495type ModuleGenPath struct {
1496	ModuleOutPath
1497}
1498
1499func (p ModuleGenPath) RelativeToTop() Path {
1500	p.OutputPath = p.outputPathRelativeToTop()
1501	return p
1502}
1503
1504var _ Path = ModuleGenPath{}
1505var _ WritablePath = ModuleGenPath{}
1506var _ genPathProvider = ModuleGenPath{}
1507var _ objPathProvider = ModuleGenPath{}
1508
1509// PathForModuleGen returns a Path representing the paths... under the module's
1510// `gen' directory.
1511func PathForModuleGen(ctx ModuleOutPathContext, paths ...string) ModuleGenPath {
1512	p, err := validatePath(paths...)
1513	if err != nil {
1514		reportPathError(ctx, err)
1515	}
1516	return ModuleGenPath{
1517		ModuleOutPath: ModuleOutPath{
1518			OutputPath: pathForModuleOut(ctx).withRel("gen").withRel(p),
1519		},
1520	}
1521}
1522
1523func (p ModuleGenPath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath {
1524	// TODO: make a different path for local vs remote generated files?
1525	return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
1526}
1527
1528func (p ModuleGenPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
1529	return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
1530}
1531
1532// ModuleObjPath is a Path representing the 'obj' directory in a module's output
1533// directory. Used for compiled objects.
1534type ModuleObjPath struct {
1535	ModuleOutPath
1536}
1537
1538func (p ModuleObjPath) RelativeToTop() Path {
1539	p.OutputPath = p.outputPathRelativeToTop()
1540	return p
1541}
1542
1543var _ Path = ModuleObjPath{}
1544var _ WritablePath = ModuleObjPath{}
1545
1546// PathForModuleObj returns a Path representing the paths... under the module's
1547// 'obj' directory.
1548func PathForModuleObj(ctx ModuleOutPathContext, pathComponents ...string) ModuleObjPath {
1549	p, err := validatePath(pathComponents...)
1550	if err != nil {
1551		reportPathError(ctx, err)
1552	}
1553	return ModuleObjPath{PathForModuleOut(ctx, "obj", p)}
1554}
1555
1556// ModuleResPath is a a Path representing the 'res' directory in a module's
1557// output directory.
1558type ModuleResPath struct {
1559	ModuleOutPath
1560}
1561
1562func (p ModuleResPath) RelativeToTop() Path {
1563	p.OutputPath = p.outputPathRelativeToTop()
1564	return p
1565}
1566
1567var _ Path = ModuleResPath{}
1568var _ WritablePath = ModuleResPath{}
1569
1570// PathForModuleRes returns a Path representing the paths... under the module's
1571// 'res' directory.
1572func PathForModuleRes(ctx ModuleOutPathContext, pathComponents ...string) ModuleResPath {
1573	p, err := validatePath(pathComponents...)
1574	if err != nil {
1575		reportPathError(ctx, err)
1576	}
1577
1578	return ModuleResPath{PathForModuleOut(ctx, "res", p)}
1579}
1580
1581// InstallPath is a Path representing a installed file path rooted from the build directory
1582type InstallPath struct {
1583	basePath
1584
1585	// The soong build directory, i.e. Config.SoongOutDir()
1586	soongOutDir string
1587
1588	// partitionDir is the part of the InstallPath that is automatically determined according to the context.
1589	// For example, it is host/<os>-<arch> for host modules, and target/product/<device>/<partition> for device modules.
1590	partitionDir string
1591
1592	partition string
1593
1594	// makePath indicates whether this path is for Soong (false) or Make (true).
1595	makePath bool
1596}
1597
1598// Will panic if called from outside a test environment.
1599func ensureTestOnly() {
1600	if PrefixInList(os.Args, "-test.") {
1601		return
1602	}
1603	panic(fmt.Errorf("Not in test. Command line:\n  %s", strings.Join(os.Args, "\n  ")))
1604}
1605
1606func (p InstallPath) RelativeToTop() Path {
1607	ensureTestOnly()
1608	p.soongOutDir = OutSoongDir
1609	return p
1610}
1611
1612func (p InstallPath) getSoongOutDir() string {
1613	return p.soongOutDir
1614}
1615
1616func (p InstallPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
1617	panic("Not implemented")
1618}
1619
1620var _ Path = InstallPath{}
1621var _ WritablePath = InstallPath{}
1622
1623func (p InstallPath) writablePath() {}
1624
1625func (p InstallPath) String() string {
1626	if p.makePath {
1627		// Make path starts with out/ instead of out/soong.
1628		return filepath.Join(p.soongOutDir, "../", p.path)
1629	} else {
1630		return filepath.Join(p.soongOutDir, p.path)
1631	}
1632}
1633
1634// PartitionDir returns the path to the partition where the install path is rooted at. It is
1635// out/soong/target/product/<device>/<partition> for device modules, and out/soong/host/<os>-<arch> for host modules.
1636// The ./soong is dropped if the install path is for Make.
1637func (p InstallPath) PartitionDir() string {
1638	if p.makePath {
1639		return filepath.Join(p.soongOutDir, "../", p.partitionDir)
1640	} else {
1641		return filepath.Join(p.soongOutDir, p.partitionDir)
1642	}
1643}
1644
1645func (p InstallPath) Partition() string {
1646	return p.partition
1647}
1648
1649// Join creates a new InstallPath with paths... joined with the current path. The
1650// provided paths... may not use '..' to escape from the current path.
1651func (p InstallPath) Join(ctx PathContext, paths ...string) InstallPath {
1652	path, err := validatePath(paths...)
1653	if err != nil {
1654		reportPathError(ctx, err)
1655	}
1656	return p.withRel(path)
1657}
1658
1659func (p InstallPath) withRel(rel string) InstallPath {
1660	p.basePath = p.basePath.withRel(rel)
1661	return p
1662}
1663
1664// Deprecated: ToMakePath is a noop, PathForModuleInstall always returns Make paths when building
1665// embedded in Make.
1666func (p InstallPath) ToMakePath() InstallPath {
1667	p.makePath = true
1668	return p
1669}
1670
1671// PathForModuleInstall returns a Path representing the install path for the
1672// module appended with paths...
1673func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
1674	os, arch := osAndArch(ctx)
1675	partition := modulePartition(ctx, os)
1676	return makePathForInstall(ctx, os, arch, partition, ctx.Debug(), pathComponents...)
1677}
1678
1679// PathForHostDexInstall returns an InstallPath representing the install path for the
1680// module appended with paths...
1681func PathForHostDexInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
1682	return makePathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "", ctx.Debug(), pathComponents...)
1683}
1684
1685// PathForModuleInPartitionInstall is similar to PathForModuleInstall but partition is provided by the caller
1686func PathForModuleInPartitionInstall(ctx ModuleInstallPathContext, partition string, pathComponents ...string) InstallPath {
1687	os, arch := osAndArch(ctx)
1688	return makePathForInstall(ctx, os, arch, partition, ctx.Debug(), pathComponents...)
1689}
1690
1691func osAndArch(ctx ModuleInstallPathContext) (OsType, ArchType) {
1692	os := ctx.Os()
1693	arch := ctx.Arch().ArchType
1694	forceOS, forceArch := ctx.InstallForceOS()
1695	if forceOS != nil {
1696		os = *forceOS
1697	}
1698	if forceArch != nil {
1699		arch = *forceArch
1700	}
1701	return os, arch
1702}
1703
1704func makePathForInstall(ctx ModuleInstallPathContext, os OsType, arch ArchType, partition string, debug bool, pathComponents ...string) InstallPath {
1705	ret := pathForInstall(ctx, os, arch, partition, debug, pathComponents...)
1706	return ret
1707}
1708
1709func pathForInstall(ctx PathContext, os OsType, arch ArchType, partition string, debug bool,
1710	pathComponents ...string) InstallPath {
1711
1712	var partitionPaths []string
1713
1714	if os.Class == Device {
1715		partitionPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
1716	} else {
1717		osName := os.String()
1718		if os == Linux {
1719			// instead of linux_glibc
1720			osName = "linux"
1721		}
1722		if os == LinuxMusl && ctx.Config().UseHostMusl() {
1723			// When using musl instead of glibc, use "linux" instead of "linux_musl".  When cross
1724			// compiling we will still use "linux_musl".
1725			osName = "linux"
1726		}
1727
1728		// SOONG_HOST_OUT is set to out/host/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
1729		// and HOST_PREBUILT_ARCH is forcibly set to x86 even on x86_64 hosts. We don't seem
1730		// to have a plan to fix it (see the comment in build/make/core/envsetup.mk).
1731		// Let's keep using x86 for the existing cases until we have a need to support
1732		// other architectures.
1733		archName := arch.String()
1734		if os.Class == Host && (arch == X86_64 || arch == Common) {
1735			archName = "x86"
1736		}
1737		partitionPaths = []string{"host", osName + "-" + archName, partition}
1738	}
1739	if debug {
1740		partitionPaths = append([]string{"debug"}, partitionPaths...)
1741	}
1742
1743	partitionPath, err := validatePath(partitionPaths...)
1744	if err != nil {
1745		reportPathError(ctx, err)
1746	}
1747
1748	base := InstallPath{
1749		basePath:     basePath{partitionPath, ""},
1750		soongOutDir:  ctx.Config().soongOutDir,
1751		partitionDir: partitionPath,
1752		partition:    partition,
1753	}
1754
1755	if ctx.Config().KatiEnabled() {
1756		base.makePath = true
1757	}
1758
1759	return base.Join(ctx, pathComponents...)
1760}
1761
1762func pathForNdkOrSdkInstall(ctx PathContext, prefix string, paths []string) InstallPath {
1763	base := InstallPath{
1764		basePath:     basePath{prefix, ""},
1765		soongOutDir:  ctx.Config().soongOutDir,
1766		partitionDir: prefix,
1767		makePath:     false,
1768	}
1769	return base.Join(ctx, paths...)
1770}
1771
1772func PathForNdkInstall(ctx PathContext, paths ...string) InstallPath {
1773	return pathForNdkOrSdkInstall(ctx, "ndk", paths)
1774}
1775
1776func PathForMainlineSdksInstall(ctx PathContext, paths ...string) InstallPath {
1777	return pathForNdkOrSdkInstall(ctx, "mainline-sdks", paths)
1778}
1779
1780func InstallPathToOnDevicePath(ctx PathContext, path InstallPath) string {
1781	rel := Rel(ctx, strings.TrimSuffix(path.PartitionDir(), path.partition), path.String())
1782	return "/" + rel
1783}
1784
1785func modulePartition(ctx ModuleInstallPathContext, os OsType) string {
1786	var partition string
1787	if ctx.InstallInTestcases() {
1788		// "testcases" install directory can be used for host or device modules.
1789		partition = "testcases"
1790	} else if os.Class == Device {
1791		if ctx.InstallInData() {
1792			partition = "data"
1793		} else if ctx.InstallInRamdisk() {
1794			if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() {
1795				partition = "recovery/root/first_stage_ramdisk"
1796			} else {
1797				partition = "ramdisk"
1798			}
1799			if !ctx.InstallInRoot() {
1800				partition += "/system"
1801			}
1802		} else if ctx.InstallInVendorRamdisk() {
1803			// The module is only available after switching root into
1804			// /first_stage_ramdisk. To expose the module before switching root
1805			// on a device without a dedicated recovery partition, install the
1806			// recovery variant.
1807			if ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
1808				partition = "vendor_ramdisk/first_stage_ramdisk"
1809			} else {
1810				partition = "vendor_ramdisk"
1811			}
1812			if !ctx.InstallInRoot() {
1813				partition += "/system"
1814			}
1815		} else if ctx.InstallInDebugRamdisk() {
1816			partition = "debug_ramdisk"
1817		} else if ctx.InstallInRecovery() {
1818			if ctx.InstallInRoot() {
1819				partition = "recovery/root"
1820			} else {
1821				// the layout of recovery partion is the same as that of system partition
1822				partition = "recovery/root/system"
1823			}
1824		} else if ctx.SocSpecific() {
1825			partition = ctx.DeviceConfig().VendorPath()
1826		} else if ctx.DeviceSpecific() {
1827			partition = ctx.DeviceConfig().OdmPath()
1828		} else if ctx.ProductSpecific() {
1829			partition = ctx.DeviceConfig().ProductPath()
1830		} else if ctx.SystemExtSpecific() {
1831			partition = ctx.DeviceConfig().SystemExtPath()
1832		} else if ctx.InstallInRoot() {
1833			partition = "root"
1834		} else {
1835			partition = "system"
1836		}
1837		if ctx.InstallInSanitizerDir() {
1838			partition = "data/asan/" + partition
1839		}
1840	}
1841	return partition
1842}
1843
1844type InstallPaths []InstallPath
1845
1846// Paths returns the InstallPaths as a Paths
1847func (p InstallPaths) Paths() Paths {
1848	if p == nil {
1849		return nil
1850	}
1851	ret := make(Paths, len(p))
1852	for i, path := range p {
1853		ret[i] = path
1854	}
1855	return ret
1856}
1857
1858// Strings returns the string forms of the install paths.
1859func (p InstallPaths) Strings() []string {
1860	if p == nil {
1861		return nil
1862	}
1863	ret := make([]string, len(p))
1864	for i, path := range p {
1865		ret[i] = path.String()
1866	}
1867	return ret
1868}
1869
1870// validatePathInternal ensures that a path does not leave its component, and
1871// optionally doesn't contain Ninja variables.
1872func validatePathInternal(allowNinjaVariables bool, pathComponents ...string) (string, error) {
1873	for _, path := range pathComponents {
1874		if !allowNinjaVariables && strings.Contains(path, "$") {
1875			return "", fmt.Errorf("Path contains invalid character($): %s", path)
1876		}
1877
1878		path := filepath.Clean(path)
1879		if path == ".." || strings.HasPrefix(path, "../") || strings.HasPrefix(path, "/") {
1880			return "", fmt.Errorf("Path is outside directory: %s", path)
1881		}
1882	}
1883	// TODO: filepath.Join isn't necessarily correct with embedded ninja
1884	// variables. '..' may remove the entire ninja variable, even if it
1885	// will be expanded to multiple nested directories.
1886	return filepath.Join(pathComponents...), nil
1887}
1888
1889// validateSafePath validates a path that we trust (may contain ninja
1890// variables).  Ensures that each path component does not attempt to leave its
1891// component. Returns a joined version of each path component.
1892func validateSafePath(pathComponents ...string) (string, error) {
1893	return validatePathInternal(true, pathComponents...)
1894}
1895
1896// validatePath validates that a path does not include ninja variables, and that
1897// each path component does not attempt to leave its component. Returns a joined
1898// version of each path component.
1899func validatePath(pathComponents ...string) (string, error) {
1900	return validatePathInternal(false, pathComponents...)
1901}
1902
1903func PathForPhony(ctx PathContext, phony string) WritablePath {
1904	if strings.ContainsAny(phony, "$/") {
1905		ReportPathErrorf(ctx, "Phony target contains invalid character ($ or /): %s", phony)
1906	}
1907	return PhonyPath{basePath{phony, ""}}
1908}
1909
1910type PhonyPath struct {
1911	basePath
1912}
1913
1914func (p PhonyPath) writablePath() {}
1915
1916func (p PhonyPath) getSoongOutDir() string {
1917	// A phone path cannot contain any / so cannot be relative to the build directory.
1918	return ""
1919}
1920
1921func (p PhonyPath) RelativeToTop() Path {
1922	ensureTestOnly()
1923	// A phony path cannot contain any / so does not have a build directory so switching to a new
1924	// build directory has no effect so just return this path.
1925	return p
1926}
1927
1928func (p PhonyPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
1929	panic("Not implemented")
1930}
1931
1932var _ Path = PhonyPath{}
1933var _ WritablePath = PhonyPath{}
1934
1935type testPath struct {
1936	basePath
1937}
1938
1939func (p testPath) RelativeToTop() Path {
1940	ensureTestOnly()
1941	return p
1942}
1943
1944func (p testPath) String() string {
1945	return p.path
1946}
1947
1948var _ Path = testPath{}
1949
1950// PathForTesting returns a Path constructed from joining the elements of paths with '/'.  It should only be used from
1951// within tests.
1952func PathForTesting(paths ...string) Path {
1953	p, err := validateSafePath(paths...)
1954	if err != nil {
1955		panic(err)
1956	}
1957	return testPath{basePath{path: p, rel: p}}
1958}
1959
1960func PathForTestingWithRel(path, rel string) Path {
1961	p, err := validateSafePath(path, rel)
1962	if err != nil {
1963		panic(err)
1964	}
1965	r, err := validatePath(rel)
1966	if err != nil {
1967		panic(err)
1968	}
1969	return testPath{basePath{path: p, rel: r}}
1970}
1971
1972// PathsForTesting returns a Path constructed from each element in strs. It should only be used from within tests.
1973func PathsForTesting(strs ...string) Paths {
1974	p := make(Paths, len(strs))
1975	for i, s := range strs {
1976		p[i] = PathForTesting(s)
1977	}
1978
1979	return p
1980}
1981
1982type testPathContext struct {
1983	config Config
1984}
1985
1986func (x *testPathContext) Config() Config             { return x.config }
1987func (x *testPathContext) AddNinjaFileDeps(...string) {}
1988
1989// PathContextForTesting returns a PathContext that can be used in tests, for example to create an OutputPath with
1990// PathForOutput.
1991func PathContextForTesting(config Config) PathContext {
1992	return &testPathContext{
1993		config: config,
1994	}
1995}
1996
1997type testModuleInstallPathContext struct {
1998	baseModuleContext
1999
2000	inData          bool
2001	inTestcases     bool
2002	inSanitizerDir  bool
2003	inRamdisk       bool
2004	inVendorRamdisk bool
2005	inDebugRamdisk  bool
2006	inRecovery      bool
2007	inRoot          bool
2008	forceOS         *OsType
2009	forceArch       *ArchType
2010}
2011
2012func (m testModuleInstallPathContext) Config() Config {
2013	return m.baseModuleContext.config
2014}
2015
2016func (testModuleInstallPathContext) AddNinjaFileDeps(deps ...string) {}
2017
2018func (m testModuleInstallPathContext) InstallInData() bool {
2019	return m.inData
2020}
2021
2022func (m testModuleInstallPathContext) InstallInTestcases() bool {
2023	return m.inTestcases
2024}
2025
2026func (m testModuleInstallPathContext) InstallInSanitizerDir() bool {
2027	return m.inSanitizerDir
2028}
2029
2030func (m testModuleInstallPathContext) InstallInRamdisk() bool {
2031	return m.inRamdisk
2032}
2033
2034func (m testModuleInstallPathContext) InstallInVendorRamdisk() bool {
2035	return m.inVendorRamdisk
2036}
2037
2038func (m testModuleInstallPathContext) InstallInDebugRamdisk() bool {
2039	return m.inDebugRamdisk
2040}
2041
2042func (m testModuleInstallPathContext) InstallInRecovery() bool {
2043	return m.inRecovery
2044}
2045
2046func (m testModuleInstallPathContext) InstallInRoot() bool {
2047	return m.inRoot
2048}
2049
2050func (m testModuleInstallPathContext) InstallForceOS() (*OsType, *ArchType) {
2051	return m.forceOS, m.forceArch
2052}
2053
2054// Construct a minimal ModuleInstallPathContext for testing. Note that baseModuleContext is
2055// default-initialized, which leaves blueprint.baseModuleContext set to nil, so methods that are
2056// delegated to it will panic.
2057func ModuleInstallPathContextForTesting(config Config) ModuleInstallPathContext {
2058	ctx := &testModuleInstallPathContext{}
2059	ctx.config = config
2060	ctx.os = Android
2061	return ctx
2062}
2063
2064// Rel performs the same function as filepath.Rel, but reports errors to a PathContext, and reports an error if
2065// targetPath is not inside basePath.
2066func Rel(ctx PathContext, basePath string, targetPath string) string {
2067	rel, isRel := MaybeRel(ctx, basePath, targetPath)
2068	if !isRel {
2069		ReportPathErrorf(ctx, "path %q is not under path %q", targetPath, basePath)
2070		return ""
2071	}
2072	return rel
2073}
2074
2075// MaybeRel performs the same function as filepath.Rel, but reports errors to a PathContext, and returns false if
2076// targetPath is not inside basePath.
2077func MaybeRel(ctx PathContext, basePath string, targetPath string) (string, bool) {
2078	rel, isRel, err := maybeRelErr(basePath, targetPath)
2079	if err != nil {
2080		reportPathError(ctx, err)
2081	}
2082	return rel, isRel
2083}
2084
2085func maybeRelErr(basePath string, targetPath string) (string, bool, error) {
2086	// filepath.Rel returns an error if one path is absolute and the other is not, handle that case first.
2087	if filepath.IsAbs(basePath) != filepath.IsAbs(targetPath) {
2088		return "", false, nil
2089	}
2090	rel, err := filepath.Rel(basePath, targetPath)
2091	if err != nil {
2092		return "", false, err
2093	} else if rel == ".." || strings.HasPrefix(rel, "../") || strings.HasPrefix(rel, "/") {
2094		return "", false, nil
2095	}
2096	return rel, true, nil
2097}
2098
2099// Writes a file to the output directory.  Attempting to write directly to the output directory
2100// will fail due to the sandbox of the soong_build process.
2101// Only writes the file if the file doesn't exist or if it has different contents, to prevent
2102// updating the timestamp if no changes would be made. (This is better for incremental
2103// performance.)
2104func WriteFileToOutputDir(path WritablePath, data []byte, perm os.FileMode) error {
2105	absPath := absolutePath(path.String())
2106	err := os.MkdirAll(filepath.Dir(absPath), 0777)
2107	if err != nil {
2108		return err
2109	}
2110	return pathtools.WriteFileIfChanged(absPath, data, perm)
2111}
2112
2113func RemoveAllOutputDir(path WritablePath) error {
2114	return os.RemoveAll(absolutePath(path.String()))
2115}
2116
2117func CreateOutputDirIfNonexistent(path WritablePath, perm os.FileMode) error {
2118	dir := absolutePath(path.String())
2119	return createDirIfNonexistent(dir, perm)
2120}
2121
2122func createDirIfNonexistent(dir string, perm os.FileMode) error {
2123	if _, err := os.Stat(dir); os.IsNotExist(err) {
2124		return os.MkdirAll(dir, os.ModePerm)
2125	} else {
2126		return err
2127	}
2128}
2129
2130// absolutePath is deliberately private so that Soong's Go plugins can't use it to find and
2131// read arbitrary files without going through the methods in the current package that track
2132// dependencies.
2133func absolutePath(path string) string {
2134	if filepath.IsAbs(path) {
2135		return path
2136	}
2137	return filepath.Join(absSrcDir, path)
2138}
2139
2140// A DataPath represents the path of a file to be used as data, for example
2141// a test library to be installed alongside a test.
2142// The data file should be installed (copied from `<SrcPath>`) to
2143// `<install_root>/<RelativeInstallPath>/<filename>`, or
2144// `<install_root>/<filename>` if RelativeInstallPath is empty.
2145type DataPath struct {
2146	// The path of the data file that should be copied into the data directory
2147	SrcPath Path
2148	// The install path of the data file, relative to the install root.
2149	RelativeInstallPath string
2150}
2151
2152// PathsIfNonNil returns a Paths containing only the non-nil input arguments.
2153func PathsIfNonNil(paths ...Path) Paths {
2154	if len(paths) == 0 {
2155		// Fast path for empty argument list
2156		return nil
2157	} else if len(paths) == 1 {
2158		// Fast path for a single argument
2159		if paths[0] != nil {
2160			return paths
2161		} else {
2162			return nil
2163		}
2164	}
2165	ret := make(Paths, 0, len(paths))
2166	for _, path := range paths {
2167		if path != nil {
2168			ret = append(ret, path)
2169		}
2170	}
2171	if len(ret) == 0 {
2172		return nil
2173	}
2174	return ret
2175}
2176
2177var thirdPartyDirPrefixExceptions = []*regexp.Regexp{
2178	regexp.MustCompile("^vendor/[^/]*google[^/]*/"),
2179	regexp.MustCompile("^hardware/google/"),
2180	regexp.MustCompile("^hardware/interfaces/"),
2181	regexp.MustCompile("^hardware/libhardware[^/]*/"),
2182	regexp.MustCompile("^hardware/ril/"),
2183}
2184
2185func IsThirdPartyPath(path string) bool {
2186	thirdPartyDirPrefixes := []string{"external/", "vendor/", "hardware/"}
2187
2188	if HasAnyPrefix(path, thirdPartyDirPrefixes) {
2189		for _, prefix := range thirdPartyDirPrefixExceptions {
2190			if prefix.MatchString(path) {
2191				return false
2192			}
2193		}
2194		return true
2195	}
2196	return false
2197}
2198
2199// PathsDepSet is a thin type-safe wrapper around the generic depSet.  It always uses
2200// topological order.
2201type PathsDepSet struct {
2202	depSet
2203}
2204
2205// newPathsDepSet returns an immutable PathsDepSet with the given direct and
2206// transitive contents.
2207func newPathsDepSet(direct Paths, transitive []*PathsDepSet) *PathsDepSet {
2208	return &PathsDepSet{*newDepSet(TOPOLOGICAL, direct, transitive)}
2209}
2210
2211// ToList returns the PathsDepSet flattened to a list in topological order.
2212func (d *PathsDepSet) ToList() Paths {
2213	if d == nil {
2214		return nil
2215	}
2216	return d.depSet.ToList().(Paths)
2217}
2218