pom2bp.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. // Copyright 2017 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 main
  15. import (
  16. "archive/zip"
  17. "bufio"
  18. "bytes"
  19. "encoding/xml"
  20. "flag"
  21. "fmt"
  22. "io/ioutil"
  23. "os"
  24. "os/exec"
  25. "path/filepath"
  26. "regexp"
  27. "sort"
  28. "strings"
  29. "text/template"
  30. "github.com/google/blueprint/proptools"
  31. "android/soong/bpfix/bpfix"
  32. )
  33. type RewriteNames []RewriteName
  34. type RewriteName struct {
  35. regexp *regexp.Regexp
  36. repl string
  37. }
  38. func (r *RewriteNames) String() string {
  39. return ""
  40. }
  41. func (r *RewriteNames) Set(v string) error {
  42. split := strings.SplitN(v, "=", 2)
  43. if len(split) != 2 {
  44. return fmt.Errorf("Must be in the form of <regex>=<replace>")
  45. }
  46. regex, err := regexp.Compile(split[0])
  47. if err != nil {
  48. return nil
  49. }
  50. *r = append(*r, RewriteName{
  51. regexp: regex,
  52. repl: split[1],
  53. })
  54. return nil
  55. }
  56. func (r *RewriteNames) MavenToBp(groupId string, artifactId string) string {
  57. for _, r := range *r {
  58. if r.regexp.MatchString(groupId + ":" + artifactId) {
  59. return r.regexp.ReplaceAllString(groupId+":"+artifactId, r.repl)
  60. } else if r.regexp.MatchString(artifactId) {
  61. return r.regexp.ReplaceAllString(artifactId, r.repl)
  62. }
  63. }
  64. return artifactId
  65. }
  66. var rewriteNames = RewriteNames{}
  67. type ExtraDeps map[string][]string
  68. func (d ExtraDeps) String() string {
  69. return ""
  70. }
  71. func (d ExtraDeps) Set(v string) error {
  72. split := strings.SplitN(v, "=", 2)
  73. if len(split) != 2 {
  74. return fmt.Errorf("Must be in the form of <module>=<module>[,<module>]")
  75. }
  76. d[split[0]] = strings.Split(split[1], ",")
  77. return nil
  78. }
  79. var extraStaticLibs = make(ExtraDeps)
  80. var extraLibs = make(ExtraDeps)
  81. type Exclude map[string]bool
  82. func (e Exclude) String() string {
  83. return ""
  84. }
  85. func (e Exclude) Set(v string) error {
  86. e[v] = true
  87. return nil
  88. }
  89. var excludes = make(Exclude)
  90. type HostModuleNames map[string]bool
  91. func (n HostModuleNames) IsHostModule(groupId string, artifactId string) bool {
  92. _, found := n[groupId+":"+artifactId]
  93. return found
  94. }
  95. func (n HostModuleNames) String() string {
  96. return ""
  97. }
  98. func (n HostModuleNames) Set(v string) error {
  99. n[v] = true
  100. return nil
  101. }
  102. var hostModuleNames = HostModuleNames{}
  103. type HostAndDeviceModuleNames map[string]bool
  104. func (n HostAndDeviceModuleNames) IsHostAndDeviceModule(groupId string, artifactId string) bool {
  105. _, found := n[groupId+":"+artifactId]
  106. return found
  107. }
  108. func (n HostAndDeviceModuleNames) String() string {
  109. return ""
  110. }
  111. func (n HostAndDeviceModuleNames) Set(v string) error {
  112. n[v] = true
  113. return nil
  114. }
  115. var hostAndDeviceModuleNames = HostAndDeviceModuleNames{}
  116. var sdkVersion string
  117. var useVersion string
  118. var staticDeps bool
  119. var jetifier bool
  120. func InList(s string, list []string) bool {
  121. for _, l := range list {
  122. if l == s {
  123. return true
  124. }
  125. }
  126. return false
  127. }
  128. type Dependency struct {
  129. XMLName xml.Name `xml:"dependency"`
  130. BpTarget string `xml:"-"`
  131. GroupId string `xml:"groupId"`
  132. ArtifactId string `xml:"artifactId"`
  133. Version string `xml:"version"`
  134. Type string `xml:"type"`
  135. Scope string `xml:"scope"`
  136. }
  137. func (d Dependency) BpName() string {
  138. if d.BpTarget == "" {
  139. d.BpTarget = rewriteNames.MavenToBp(d.GroupId, d.ArtifactId)
  140. }
  141. return d.BpTarget
  142. }
  143. type Pom struct {
  144. XMLName xml.Name `xml:"http://maven.apache.org/POM/4.0.0 project"`
  145. PomFile string `xml:"-"`
  146. ArtifactFile string `xml:"-"`
  147. BpTarget string `xml:"-"`
  148. MinSdkVersion string `xml:"-"`
  149. GroupId string `xml:"groupId"`
  150. ArtifactId string `xml:"artifactId"`
  151. Version string `xml:"version"`
  152. Packaging string `xml:"packaging"`
  153. Dependencies []*Dependency `xml:"dependencies>dependency"`
  154. }
  155. func (p Pom) IsAar() bool {
  156. return p.Packaging == "aar"
  157. }
  158. func (p Pom) IsJar() bool {
  159. return p.Packaging == "jar"
  160. }
  161. func (p Pom) IsHostModule() bool {
  162. return hostModuleNames.IsHostModule(p.GroupId, p.ArtifactId)
  163. }
  164. func (p Pom) IsDeviceModule() bool {
  165. return !p.IsHostModule()
  166. }
  167. func (p Pom) IsHostAndDeviceModule() bool {
  168. return hostAndDeviceModuleNames.IsHostAndDeviceModule(p.GroupId, p.ArtifactId)
  169. }
  170. func (p Pom) ModuleType() string {
  171. if p.IsAar() {
  172. return "android_library"
  173. } else if p.IsHostModule() && !p.IsHostAndDeviceModule() {
  174. return "java_library_host"
  175. } else {
  176. return "java_library_static"
  177. }
  178. }
  179. func (p Pom) ImportModuleType() string {
  180. if p.IsAar() {
  181. return "android_library_import"
  182. } else if p.IsHostModule() && !p.IsHostAndDeviceModule() {
  183. return "java_import_host"
  184. } else {
  185. return "java_import"
  186. }
  187. }
  188. func (p Pom) ImportProperty() string {
  189. if p.IsAar() {
  190. return "aars"
  191. } else {
  192. return "jars"
  193. }
  194. }
  195. func (p Pom) BpName() string {
  196. if p.BpTarget == "" {
  197. p.BpTarget = rewriteNames.MavenToBp(p.GroupId, p.ArtifactId)
  198. }
  199. return p.BpTarget
  200. }
  201. func (p Pom) BpJarDeps() []string {
  202. return p.BpDeps("jar", []string{"compile", "runtime"})
  203. }
  204. func (p Pom) BpAarDeps() []string {
  205. return p.BpDeps("aar", []string{"compile", "runtime"})
  206. }
  207. func (p Pom) BpExtraStaticLibs() []string {
  208. return extraStaticLibs[p.BpName()]
  209. }
  210. func (p Pom) BpExtraLibs() []string {
  211. return extraLibs[p.BpName()]
  212. }
  213. // BpDeps obtains dependencies filtered by type and scope. The results of this
  214. // method are formatted as Android.bp targets, e.g. run through MavenToBp rules.
  215. func (p Pom) BpDeps(typeExt string, scopes []string) []string {
  216. var ret []string
  217. for _, d := range p.Dependencies {
  218. if d.Type != typeExt || !InList(d.Scope, scopes) {
  219. continue
  220. }
  221. name := rewriteNames.MavenToBp(d.GroupId, d.ArtifactId)
  222. ret = append(ret, name)
  223. }
  224. return ret
  225. }
  226. func (p Pom) SdkVersion() string {
  227. return sdkVersion
  228. }
  229. func (p Pom) Jetifier() bool {
  230. return jetifier
  231. }
  232. func (p *Pom) FixDeps(modules map[string]*Pom) {
  233. for _, d := range p.Dependencies {
  234. if d.Type == "" {
  235. if depPom, ok := modules[d.BpName()]; ok {
  236. // We've seen the POM for this dependency, use its packaging
  237. // as the dependency type rather than Maven spec default.
  238. d.Type = depPom.Packaging
  239. } else {
  240. // Dependency type was not specified and we don't have the POM
  241. // for this artifact, use the default from Maven spec.
  242. d.Type = "jar"
  243. }
  244. }
  245. if d.Scope == "" {
  246. // Scope was not specified, use the default from Maven spec.
  247. d.Scope = "compile"
  248. }
  249. }
  250. }
  251. // ExtractMinSdkVersion extracts the minSdkVersion from the AndroidManifest.xml file inside an aar file, or sets it
  252. // to "current" if it is not present.
  253. func (p *Pom) ExtractMinSdkVersion() error {
  254. aar, err := zip.OpenReader(p.ArtifactFile)
  255. if err != nil {
  256. return err
  257. }
  258. defer aar.Close()
  259. var manifest *zip.File
  260. for _, f := range aar.File {
  261. if f.Name == "AndroidManifest.xml" {
  262. manifest = f
  263. break
  264. }
  265. }
  266. if manifest == nil {
  267. return fmt.Errorf("failed to find AndroidManifest.xml in %s", p.ArtifactFile)
  268. }
  269. r, err := manifest.Open()
  270. if err != nil {
  271. return err
  272. }
  273. defer r.Close()
  274. decoder := xml.NewDecoder(r)
  275. manifestData := struct {
  276. XMLName xml.Name `xml:"manifest"`
  277. Uses_sdk struct {
  278. MinSdkVersion string `xml:"http://schemas.android.com/apk/res/android minSdkVersion,attr"`
  279. } `xml:"uses-sdk"`
  280. }{}
  281. err = decoder.Decode(&manifestData)
  282. if err != nil {
  283. return err
  284. }
  285. p.MinSdkVersion = manifestData.Uses_sdk.MinSdkVersion
  286. if p.MinSdkVersion == "" {
  287. p.MinSdkVersion = "current"
  288. }
  289. return nil
  290. }
  291. var bpTemplate = template.Must(template.New("bp").Parse(`
  292. {{.ImportModuleType}} {
  293. name: "{{.BpName}}",
  294. {{.ImportProperty}}: ["{{.ArtifactFile}}"],
  295. sdk_version: "{{.SdkVersion}}",
  296. {{- if .Jetifier}}
  297. jetifier: true,
  298. {{- end}}
  299. {{- if .IsHostAndDeviceModule}}
  300. host_supported: true,
  301. {{- end}}
  302. {{- if .IsAar}}
  303. min_sdk_version: "{{.MinSdkVersion}}",
  304. static_libs: [
  305. {{- range .BpJarDeps}}
  306. "{{.}}",
  307. {{- end}}
  308. {{- range .BpAarDeps}}
  309. "{{.}}",
  310. {{- end}}
  311. {{- range .BpExtraStaticLibs}}
  312. "{{.}}",
  313. {{- end}}
  314. ],
  315. {{- if .BpExtraLibs}}
  316. libs: [
  317. {{- range .BpExtraLibs}}
  318. "{{.}}",
  319. {{- end}}
  320. ],
  321. {{- end}}
  322. {{- end}}
  323. }
  324. `))
  325. var bpDepsTemplate = template.Must(template.New("bp").Parse(`
  326. {{.ImportModuleType}} {
  327. name: "{{.BpName}}-nodeps",
  328. {{.ImportProperty}}: ["{{.ArtifactFile}}"],
  329. sdk_version: "{{.SdkVersion}}",
  330. {{- if .Jetifier}}
  331. jetifier: true,
  332. {{- end}}
  333. {{- if .IsHostAndDeviceModule}}
  334. host_supported: true,
  335. {{- end}}
  336. {{- if .IsAar}}
  337. min_sdk_version: "{{.MinSdkVersion}}",
  338. static_libs: [
  339. {{- range .BpJarDeps}}
  340. "{{.}}",
  341. {{- end}}
  342. {{- range .BpAarDeps}}
  343. "{{.}}",
  344. {{- end}}
  345. {{- range .BpExtraStaticLibs}}
  346. "{{.}}",
  347. {{- end}}
  348. ],
  349. {{- if .BpExtraLibs}}
  350. libs: [
  351. {{- range .BpExtraLibs}}
  352. "{{.}}",
  353. {{- end}}
  354. ],
  355. {{- end}}
  356. {{- end}}
  357. }
  358. {{.ModuleType}} {
  359. name: "{{.BpName}}",
  360. {{- if .IsDeviceModule}}
  361. sdk_version: "{{.SdkVersion}}",
  362. {{- if .IsHostAndDeviceModule}}
  363. host_supported: true,
  364. {{- end}}
  365. {{- if .IsAar}}
  366. min_sdk_version: "{{.MinSdkVersion}}",
  367. manifest: "manifests/{{.BpName}}/AndroidManifest.xml",
  368. {{- end}}
  369. {{- end}}
  370. static_libs: [
  371. "{{.BpName}}-nodeps",
  372. {{- range .BpJarDeps}}
  373. "{{.}}",
  374. {{- end}}
  375. {{- range .BpAarDeps}}
  376. "{{.}}",
  377. {{- end}}
  378. {{- range .BpExtraStaticLibs}}
  379. "{{.}}",
  380. {{- end}}
  381. ],
  382. {{- if .BpExtraLibs}}
  383. libs: [
  384. {{- range .BpExtraLibs}}
  385. "{{.}}",
  386. {{- end}}
  387. ],
  388. {{- end}}
  389. java_version: "1.7",
  390. }
  391. `))
  392. func parse(filename string) (*Pom, error) {
  393. data, err := ioutil.ReadFile(filename)
  394. if err != nil {
  395. return nil, err
  396. }
  397. var pom Pom
  398. err = xml.Unmarshal(data, &pom)
  399. if err != nil {
  400. return nil, err
  401. }
  402. if useVersion != "" && pom.Version != useVersion {
  403. return nil, nil
  404. }
  405. if pom.Packaging == "" {
  406. pom.Packaging = "jar"
  407. }
  408. pom.PomFile = filename
  409. pom.ArtifactFile = strings.TrimSuffix(filename, ".pom") + "." + pom.Packaging
  410. return &pom, nil
  411. }
  412. func rerunForRegen(filename string) error {
  413. buf, err := ioutil.ReadFile(filename)
  414. if err != nil {
  415. return err
  416. }
  417. scanner := bufio.NewScanner(bytes.NewBuffer(buf))
  418. // Skip the first line in the file
  419. for i := 0; i < 2; i++ {
  420. if !scanner.Scan() {
  421. if scanner.Err() != nil {
  422. return scanner.Err()
  423. } else {
  424. return fmt.Errorf("unexpected EOF")
  425. }
  426. }
  427. }
  428. // Extract the old args from the file
  429. line := scanner.Text()
  430. if strings.HasPrefix(line, "// pom2bp ") {
  431. line = strings.TrimPrefix(line, "// pom2bp ")
  432. } else if strings.HasPrefix(line, "// pom2mk ") {
  433. line = strings.TrimPrefix(line, "// pom2mk ")
  434. } else if strings.HasPrefix(line, "# pom2mk ") {
  435. line = strings.TrimPrefix(line, "# pom2mk ")
  436. } else {
  437. return fmt.Errorf("unexpected second line: %q", line)
  438. }
  439. args := strings.Split(line, " ")
  440. lastArg := args[len(args)-1]
  441. args = args[:len(args)-1]
  442. // Append all current command line args except -regen <file> to the ones from the file
  443. for i := 1; i < len(os.Args); i++ {
  444. if os.Args[i] == "-regen" || os.Args[i] == "--regen" {
  445. i++
  446. } else {
  447. args = append(args, os.Args[i])
  448. }
  449. }
  450. args = append(args, lastArg)
  451. cmd := os.Args[0] + " " + strings.Join(args, " ")
  452. // Re-exec pom2bp with the new arguments
  453. output, err := exec.Command("/bin/sh", "-c", cmd).Output()
  454. if exitErr, _ := err.(*exec.ExitError); exitErr != nil {
  455. return fmt.Errorf("failed to run %s\n%s", cmd, string(exitErr.Stderr))
  456. } else if err != nil {
  457. return err
  458. }
  459. // If the old file was a .mk file, replace it with a .bp file
  460. if filepath.Ext(filename) == ".mk" {
  461. os.Remove(filename)
  462. filename = strings.TrimSuffix(filename, ".mk") + ".bp"
  463. }
  464. return ioutil.WriteFile(filename, output, 0666)
  465. }
  466. func main() {
  467. flag.Usage = func() {
  468. fmt.Fprintf(os.Stderr, `pom2bp, a tool to create Android.bp files from maven repos
  469. The tool will extract the necessary information from *.pom files to create an Android.bp whose
  470. aar libraries can be linked against when using AAPT2.
  471. Usage: %s [--rewrite <regex>=<replace>] [-exclude <module>] [--extra-static-libs <module>=<module>[,<module>]] [--extra-libs <module>=<module>[,<module>]] [<dir>] [-regen <file>]
  472. -rewrite <regex>=<replace>
  473. rewrite can be used to specify mappings between Maven projects and Android.bp modules. The -rewrite
  474. option can be specified multiple times. When determining the Android.bp module for a given Maven
  475. project, mappings are searched in the order they were specified. The first <regex> matching
  476. either the Maven project's <groupId>:<artifactId> or <artifactId> will be used to generate
  477. the Android.bp module name using <replace>. If no matches are found, <artifactId> is used.
  478. -exclude <module>
  479. Don't put the specified module in the Android.bp file.
  480. -extra-static-libs <module>=<module>[,<module>]
  481. Some Android.bp modules have transitive static dependencies that must be specified when they
  482. are depended upon (like android-support-v7-mediarouter requires android-support-v7-appcompat).
  483. This may be specified multiple times to declare these dependencies.
  484. -extra-libs <module>=<module>[,<module>]
  485. Some Android.bp modules have transitive runtime dependencies that must be specified when they
  486. are depended upon (like androidx.test.rules requires android.test.base).
  487. This may be specified multiple times to declare these dependencies.
  488. -sdk-version <version>
  489. Sets sdk_version: "<version>" for all modules.
  490. -use-version <version>
  491. If the maven directory contains multiple versions of artifacts and their pom files,
  492. -use-version can be used to only write Android.bp files for a specific version of those artifacts.
  493. -jetifier
  494. Sets jetifier: true for all modules.
  495. <dir>
  496. The directory to search for *.pom files under.
  497. The contents are written to stdout, to be put in the current directory (often as Android.bp)
  498. -regen <file>
  499. Read arguments from <file> and overwrite it (if it ends with .bp) or move it to .bp (if it
  500. ends with .mk).
  501. `, os.Args[0])
  502. }
  503. var regen string
  504. flag.Var(&excludes, "exclude", "Exclude module")
  505. flag.Var(&extraStaticLibs, "extra-static-libs", "Extra static dependencies needed when depending on a module")
  506. flag.Var(&extraLibs, "extra-libs", "Extra runtime dependencies needed when depending on a module")
  507. flag.Var(&rewriteNames, "rewrite", "Regex(es) to rewrite artifact names")
  508. flag.Var(&hostModuleNames, "host", "Specifies that the corresponding module (specified in the form 'module.group:module.artifact') is a host module")
  509. flag.Var(&hostAndDeviceModuleNames, "host-and-device", "Specifies that the corresponding module (specified in the form 'module.group:module.artifact') is both a host and device module.")
  510. flag.StringVar(&sdkVersion, "sdk-version", "", "What to write to sdk_version")
  511. flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version")
  512. flag.BoolVar(&staticDeps, "static-deps", false, "Statically include direct dependencies")
  513. flag.BoolVar(&jetifier, "jetifier", false, "Sets jetifier: true on all modules")
  514. flag.StringVar(&regen, "regen", "", "Rewrite specified file")
  515. flag.Parse()
  516. if regen != "" {
  517. err := rerunForRegen(regen)
  518. if err != nil {
  519. fmt.Fprintln(os.Stderr, err)
  520. os.Exit(1)
  521. }
  522. os.Exit(0)
  523. }
  524. if flag.NArg() == 0 {
  525. fmt.Fprintln(os.Stderr, "Directory argument is required")
  526. os.Exit(1)
  527. } else if flag.NArg() > 1 {
  528. fmt.Fprintln(os.Stderr, "Multiple directories provided:", strings.Join(flag.Args(), " "))
  529. os.Exit(1)
  530. }
  531. dir := flag.Arg(0)
  532. absDir, err := filepath.Abs(dir)
  533. if err != nil {
  534. fmt.Fprintln(os.Stderr, "Failed to get absolute directory:", err)
  535. os.Exit(1)
  536. }
  537. var filenames []string
  538. err = filepath.Walk(absDir, func(path string, info os.FileInfo, err error) error {
  539. if err != nil {
  540. return err
  541. }
  542. name := info.Name()
  543. if info.IsDir() {
  544. if strings.HasPrefix(name, ".") {
  545. return filepath.SkipDir
  546. }
  547. return nil
  548. }
  549. if strings.HasPrefix(name, ".") {
  550. return nil
  551. }
  552. if strings.HasSuffix(name, ".pom") {
  553. path, err = filepath.Rel(absDir, path)
  554. if err != nil {
  555. return err
  556. }
  557. filenames = append(filenames, filepath.Join(dir, path))
  558. }
  559. return nil
  560. })
  561. if err != nil {
  562. fmt.Fprintln(os.Stderr, "Error walking files:", err)
  563. os.Exit(1)
  564. }
  565. if len(filenames) == 0 {
  566. fmt.Fprintln(os.Stderr, "Error: no *.pom files found under", dir)
  567. os.Exit(1)
  568. }
  569. sort.Strings(filenames)
  570. poms := []*Pom{}
  571. modules := make(map[string]*Pom)
  572. duplicate := false
  573. for _, filename := range filenames {
  574. pom, err := parse(filename)
  575. if err != nil {
  576. fmt.Fprintln(os.Stderr, "Error converting", filename, err)
  577. os.Exit(1)
  578. }
  579. if pom != nil {
  580. key := pom.BpName()
  581. if excludes[key] {
  582. continue
  583. }
  584. if old, ok := modules[key]; ok {
  585. fmt.Fprintln(os.Stderr, "Module", key, "defined twice:", old.PomFile, pom.PomFile)
  586. duplicate = true
  587. }
  588. poms = append(poms, pom)
  589. modules[key] = pom
  590. }
  591. }
  592. if duplicate {
  593. os.Exit(1)
  594. }
  595. for _, pom := range poms {
  596. if pom.IsAar() {
  597. err := pom.ExtractMinSdkVersion()
  598. if err != nil {
  599. fmt.Fprintf(os.Stderr, "Error reading manifest for %s: %s", pom.ArtifactFile, err)
  600. os.Exit(1)
  601. }
  602. }
  603. pom.FixDeps(modules)
  604. }
  605. buf := &bytes.Buffer{}
  606. fmt.Fprintln(buf, "// Automatically generated with:")
  607. fmt.Fprintln(buf, "// pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
  608. for _, pom := range poms {
  609. var err error
  610. if staticDeps {
  611. err = bpDepsTemplate.Execute(buf, pom)
  612. } else {
  613. err = bpTemplate.Execute(buf, pom)
  614. }
  615. if err != nil {
  616. fmt.Fprintln(os.Stderr, "Error writing", pom.PomFile, pom.BpName(), err)
  617. os.Exit(1)
  618. }
  619. }
  620. out, err := bpfix.Reformat(buf.String())
  621. if err != nil {
  622. fmt.Fprintln(os.Stderr, "Error formatting output", err)
  623. os.Exit(1)
  624. }
  625. os.Stdout.WriteString(out)
  626. }