paths.go 68 KB

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