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