paths.go 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221
  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. }
  1910. // PathsDepSet is a thin type-safe wrapper around the generic depSet. It always uses
  1911. // topological order.
  1912. type PathsDepSet struct {
  1913. depSet
  1914. }
  1915. // newPathsDepSet returns an immutable PathsDepSet with the given direct and
  1916. // transitive contents.
  1917. func newPathsDepSet(direct Paths, transitive []*PathsDepSet) *PathsDepSet {
  1918. return &PathsDepSet{*newDepSet(TOPOLOGICAL, direct, transitive)}
  1919. }
  1920. // ToList returns the PathsDepSet flattened to a list in topological order.
  1921. func (d *PathsDepSet) ToList() Paths {
  1922. if d == nil {
  1923. return nil
  1924. }
  1925. return d.depSet.ToList().(Paths)
  1926. }