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