paths.go 68 KB

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