1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage main 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "bufio" 19*333d2b36SAndroid Build Coastguard Worker "bytes" 20*333d2b36SAndroid Build Coastguard Worker "encoding/xml" 21*333d2b36SAndroid Build Coastguard Worker "flag" 22*333d2b36SAndroid Build Coastguard Worker "fmt" 23*333d2b36SAndroid Build Coastguard Worker "io/ioutil" 24*333d2b36SAndroid Build Coastguard Worker "os" 25*333d2b36SAndroid Build Coastguard Worker "os/exec" 26*333d2b36SAndroid Build Coastguard Worker "path/filepath" 27*333d2b36SAndroid Build Coastguard Worker "regexp" 28*333d2b36SAndroid Build Coastguard Worker "sort" 29*333d2b36SAndroid Build Coastguard Worker "strings" 30*333d2b36SAndroid Build Coastguard Worker "text/template" 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 33*333d2b36SAndroid Build Coastguard Worker) 34*333d2b36SAndroid Build Coastguard Worker 35*333d2b36SAndroid Build Coastguard Workertype RewriteNames []RewriteName 36*333d2b36SAndroid Build Coastguard Workertype RewriteName struct { 37*333d2b36SAndroid Build Coastguard Worker regexp *regexp.Regexp 38*333d2b36SAndroid Build Coastguard Worker repl string 39*333d2b36SAndroid Build Coastguard Worker} 40*333d2b36SAndroid Build Coastguard Worker 41*333d2b36SAndroid Build Coastguard Workerfunc (r *RewriteNames) String() string { 42*333d2b36SAndroid Build Coastguard Worker return "" 43*333d2b36SAndroid Build Coastguard Worker} 44*333d2b36SAndroid Build Coastguard Worker 45*333d2b36SAndroid Build Coastguard Workerfunc (r *RewriteNames) Set(v string) error { 46*333d2b36SAndroid Build Coastguard Worker split := strings.SplitN(v, "=", 2) 47*333d2b36SAndroid Build Coastguard Worker if len(split) != 2 { 48*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf("Must be in the form of <regex>=<replace>") 49*333d2b36SAndroid Build Coastguard Worker } 50*333d2b36SAndroid Build Coastguard Worker regex, err := regexp.Compile(split[0]) 51*333d2b36SAndroid Build Coastguard Worker if err != nil { 52*333d2b36SAndroid Build Coastguard Worker return nil 53*333d2b36SAndroid Build Coastguard Worker } 54*333d2b36SAndroid Build Coastguard Worker *r = append(*r, RewriteName{ 55*333d2b36SAndroid Build Coastguard Worker regexp: regex, 56*333d2b36SAndroid Build Coastguard Worker repl: split[1], 57*333d2b36SAndroid Build Coastguard Worker }) 58*333d2b36SAndroid Build Coastguard Worker return nil 59*333d2b36SAndroid Build Coastguard Worker} 60*333d2b36SAndroid Build Coastguard Worker 61*333d2b36SAndroid Build Coastguard Workerfunc (r *RewriteNames) MavenToMk(groupId string, artifactId string) string { 62*333d2b36SAndroid Build Coastguard Worker for _, r := range *r { 63*333d2b36SAndroid Build Coastguard Worker if r.regexp.MatchString(groupId + ":" + artifactId) { 64*333d2b36SAndroid Build Coastguard Worker return r.regexp.ReplaceAllString(groupId+":"+artifactId, r.repl) 65*333d2b36SAndroid Build Coastguard Worker } else if r.regexp.MatchString(artifactId) { 66*333d2b36SAndroid Build Coastguard Worker return r.regexp.ReplaceAllString(artifactId, r.repl) 67*333d2b36SAndroid Build Coastguard Worker } 68*333d2b36SAndroid Build Coastguard Worker } 69*333d2b36SAndroid Build Coastguard Worker return artifactId 70*333d2b36SAndroid Build Coastguard Worker} 71*333d2b36SAndroid Build Coastguard Worker 72*333d2b36SAndroid Build Coastguard Workervar rewriteNames = RewriteNames{} 73*333d2b36SAndroid Build Coastguard Worker 74*333d2b36SAndroid Build Coastguard Workertype ExtraDeps map[string][]string 75*333d2b36SAndroid Build Coastguard Worker 76*333d2b36SAndroid Build Coastguard Workerfunc (d ExtraDeps) String() string { 77*333d2b36SAndroid Build Coastguard Worker return "" 78*333d2b36SAndroid Build Coastguard Worker} 79*333d2b36SAndroid Build Coastguard Worker 80*333d2b36SAndroid Build Coastguard Workerfunc (d ExtraDeps) Set(v string) error { 81*333d2b36SAndroid Build Coastguard Worker split := strings.SplitN(v, "=", 2) 82*333d2b36SAndroid Build Coastguard Worker if len(split) != 2 { 83*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf("Must be in the form of <module>=<module>[,<module>]") 84*333d2b36SAndroid Build Coastguard Worker } 85*333d2b36SAndroid Build Coastguard Worker d[split[0]] = strings.Split(split[1], ",") 86*333d2b36SAndroid Build Coastguard Worker return nil 87*333d2b36SAndroid Build Coastguard Worker} 88*333d2b36SAndroid Build Coastguard Worker 89*333d2b36SAndroid Build Coastguard Workervar extraDeps = make(ExtraDeps) 90*333d2b36SAndroid Build Coastguard Worker 91*333d2b36SAndroid Build Coastguard Workertype Exclude map[string]bool 92*333d2b36SAndroid Build Coastguard Worker 93*333d2b36SAndroid Build Coastguard Workerfunc (e Exclude) String() string { 94*333d2b36SAndroid Build Coastguard Worker return "" 95*333d2b36SAndroid Build Coastguard Worker} 96*333d2b36SAndroid Build Coastguard Worker 97*333d2b36SAndroid Build Coastguard Workerfunc (e Exclude) Set(v string) error { 98*333d2b36SAndroid Build Coastguard Worker e[v] = true 99*333d2b36SAndroid Build Coastguard Worker return nil 100*333d2b36SAndroid Build Coastguard Worker} 101*333d2b36SAndroid Build Coastguard Worker 102*333d2b36SAndroid Build Coastguard Workervar excludes = make(Exclude) 103*333d2b36SAndroid Build Coastguard Worker 104*333d2b36SAndroid Build Coastguard Workervar sdkVersion string 105*333d2b36SAndroid Build Coastguard Workervar useVersion string 106*333d2b36SAndroid Build Coastguard Workervar staticDeps bool 107*333d2b36SAndroid Build Coastguard Workervar jetifier bool 108*333d2b36SAndroid Build Coastguard Worker 109*333d2b36SAndroid Build Coastguard Workerfunc InList(s string, list []string) bool { 110*333d2b36SAndroid Build Coastguard Worker for _, l := range list { 111*333d2b36SAndroid Build Coastguard Worker if l == s { 112*333d2b36SAndroid Build Coastguard Worker return true 113*333d2b36SAndroid Build Coastguard Worker } 114*333d2b36SAndroid Build Coastguard Worker } 115*333d2b36SAndroid Build Coastguard Worker 116*333d2b36SAndroid Build Coastguard Worker return false 117*333d2b36SAndroid Build Coastguard Worker} 118*333d2b36SAndroid Build Coastguard Worker 119*333d2b36SAndroid Build Coastguard Workertype Dependency struct { 120*333d2b36SAndroid Build Coastguard Worker XMLName xml.Name `xml:"dependency"` 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Worker MakeTarget string `xml:"-"` 123*333d2b36SAndroid Build Coastguard Worker 124*333d2b36SAndroid Build Coastguard Worker GroupId string `xml:"groupId"` 125*333d2b36SAndroid Build Coastguard Worker ArtifactId string `xml:"artifactId"` 126*333d2b36SAndroid Build Coastguard Worker Version string `xml:"version"` 127*333d2b36SAndroid Build Coastguard Worker Type string `xml:"type"` 128*333d2b36SAndroid Build Coastguard Worker Scope string `xml:"scope"` 129*333d2b36SAndroid Build Coastguard Worker} 130*333d2b36SAndroid Build Coastguard Worker 131*333d2b36SAndroid Build Coastguard Workerfunc (d Dependency) MkName() string { 132*333d2b36SAndroid Build Coastguard Worker if d.MakeTarget == "" { 133*333d2b36SAndroid Build Coastguard Worker d.MakeTarget = rewriteNames.MavenToMk(d.GroupId, d.ArtifactId) 134*333d2b36SAndroid Build Coastguard Worker } 135*333d2b36SAndroid Build Coastguard Worker return d.MakeTarget 136*333d2b36SAndroid Build Coastguard Worker} 137*333d2b36SAndroid Build Coastguard Worker 138*333d2b36SAndroid Build Coastguard Workertype Pom struct { 139*333d2b36SAndroid Build Coastguard Worker XMLName xml.Name `xml:"http://maven.apache.org/POM/4.0.0 project"` 140*333d2b36SAndroid Build Coastguard Worker 141*333d2b36SAndroid Build Coastguard Worker PomFile string `xml:"-"` 142*333d2b36SAndroid Build Coastguard Worker ArtifactFile string `xml:"-"` 143*333d2b36SAndroid Build Coastguard Worker MakeTarget string `xml:"-"` 144*333d2b36SAndroid Build Coastguard Worker 145*333d2b36SAndroid Build Coastguard Worker GroupId string `xml:"groupId"` 146*333d2b36SAndroid Build Coastguard Worker ArtifactId string `xml:"artifactId"` 147*333d2b36SAndroid Build Coastguard Worker Version string `xml:"version"` 148*333d2b36SAndroid Build Coastguard Worker Packaging string `xml:"packaging"` 149*333d2b36SAndroid Build Coastguard Worker 150*333d2b36SAndroid Build Coastguard Worker Dependencies []*Dependency `xml:"dependencies>dependency"` 151*333d2b36SAndroid Build Coastguard Worker} 152*333d2b36SAndroid Build Coastguard Worker 153*333d2b36SAndroid Build Coastguard Workerfunc (p Pom) IsAar() bool { 154*333d2b36SAndroid Build Coastguard Worker return p.Packaging == "aar" 155*333d2b36SAndroid Build Coastguard Worker} 156*333d2b36SAndroid Build Coastguard Worker 157*333d2b36SAndroid Build Coastguard Workerfunc (p Pom) IsJar() bool { 158*333d2b36SAndroid Build Coastguard Worker return p.Packaging == "jar" 159*333d2b36SAndroid Build Coastguard Worker} 160*333d2b36SAndroid Build Coastguard Worker 161*333d2b36SAndroid Build Coastguard Workerfunc (p Pom) MkName() string { 162*333d2b36SAndroid Build Coastguard Worker if p.MakeTarget == "" { 163*333d2b36SAndroid Build Coastguard Worker p.MakeTarget = rewriteNames.MavenToMk(p.GroupId, p.ArtifactId) 164*333d2b36SAndroid Build Coastguard Worker } 165*333d2b36SAndroid Build Coastguard Worker return p.MakeTarget 166*333d2b36SAndroid Build Coastguard Worker} 167*333d2b36SAndroid Build Coastguard Worker 168*333d2b36SAndroid Build Coastguard Workerfunc (p Pom) MkJarDeps() []string { 169*333d2b36SAndroid Build Coastguard Worker return p.MkDeps("jar", []string{"compile", "runtime"}) 170*333d2b36SAndroid Build Coastguard Worker} 171*333d2b36SAndroid Build Coastguard Worker 172*333d2b36SAndroid Build Coastguard Workerfunc (p Pom) MkAarDeps() []string { 173*333d2b36SAndroid Build Coastguard Worker return p.MkDeps("aar", []string{"compile", "runtime"}) 174*333d2b36SAndroid Build Coastguard Worker} 175*333d2b36SAndroid Build Coastguard Worker 176*333d2b36SAndroid Build Coastguard Worker// MkDeps obtains dependencies filtered by type and scope. The results of this 177*333d2b36SAndroid Build Coastguard Worker// method are formatted as Make targets, e.g. run through MavenToMk rules. 178*333d2b36SAndroid Build Coastguard Workerfunc (p Pom) MkDeps(typeExt string, scopes []string) []string { 179*333d2b36SAndroid Build Coastguard Worker var ret []string 180*333d2b36SAndroid Build Coastguard Worker if typeExt == "jar" { 181*333d2b36SAndroid Build Coastguard Worker // all top-level extra deps are assumed to be of type "jar" until we add syntax to specify other types 182*333d2b36SAndroid Build Coastguard Worker ret = append(ret, extraDeps[p.MkName()]...) 183*333d2b36SAndroid Build Coastguard Worker } 184*333d2b36SAndroid Build Coastguard Worker for _, d := range p.Dependencies { 185*333d2b36SAndroid Build Coastguard Worker if d.Type != typeExt || !InList(d.Scope, scopes) { 186*333d2b36SAndroid Build Coastguard Worker continue 187*333d2b36SAndroid Build Coastguard Worker } 188*333d2b36SAndroid Build Coastguard Worker name := rewriteNames.MavenToMk(d.GroupId, d.ArtifactId) 189*333d2b36SAndroid Build Coastguard Worker ret = append(ret, name) 190*333d2b36SAndroid Build Coastguard Worker ret = append(ret, extraDeps[name]...) 191*333d2b36SAndroid Build Coastguard Worker } 192*333d2b36SAndroid Build Coastguard Worker return ret 193*333d2b36SAndroid Build Coastguard Worker} 194*333d2b36SAndroid Build Coastguard Worker 195*333d2b36SAndroid Build Coastguard Workerfunc (p Pom) SdkVersion() string { 196*333d2b36SAndroid Build Coastguard Worker return sdkVersion 197*333d2b36SAndroid Build Coastguard Worker} 198*333d2b36SAndroid Build Coastguard Worker 199*333d2b36SAndroid Build Coastguard Workerfunc (p Pom) Jetifier() bool { 200*333d2b36SAndroid Build Coastguard Worker return jetifier 201*333d2b36SAndroid Build Coastguard Worker} 202*333d2b36SAndroid Build Coastguard Worker 203*333d2b36SAndroid Build Coastguard Workerfunc (p *Pom) FixDeps(modules map[string]*Pom) { 204*333d2b36SAndroid Build Coastguard Worker for _, d := range p.Dependencies { 205*333d2b36SAndroid Build Coastguard Worker if d.Type == "" { 206*333d2b36SAndroid Build Coastguard Worker if depPom, ok := modules[d.MkName()]; ok { 207*333d2b36SAndroid Build Coastguard Worker // We've seen the POM for this dependency, use its packaging 208*333d2b36SAndroid Build Coastguard Worker // as the dependency type rather than Maven spec default. 209*333d2b36SAndroid Build Coastguard Worker d.Type = depPom.Packaging 210*333d2b36SAndroid Build Coastguard Worker } else { 211*333d2b36SAndroid Build Coastguard Worker // Dependency type was not specified and we don't have the POM 212*333d2b36SAndroid Build Coastguard Worker // for this artifact, use the default from Maven spec. 213*333d2b36SAndroid Build Coastguard Worker d.Type = "jar" 214*333d2b36SAndroid Build Coastguard Worker } 215*333d2b36SAndroid Build Coastguard Worker } 216*333d2b36SAndroid Build Coastguard Worker if d.Scope == "" { 217*333d2b36SAndroid Build Coastguard Worker // Scope was not specified, use the default from Maven spec. 218*333d2b36SAndroid Build Coastguard Worker d.Scope = "compile" 219*333d2b36SAndroid Build Coastguard Worker } 220*333d2b36SAndroid Build Coastguard Worker } 221*333d2b36SAndroid Build Coastguard Worker} 222*333d2b36SAndroid Build Coastguard Worker 223*333d2b36SAndroid Build Coastguard Workervar mkTemplate = template.Must(template.New("mk").Parse(` 224*333d2b36SAndroid Build Coastguard Workerinclude $(CLEAR_VARS) 225*333d2b36SAndroid Build Coastguard WorkerLOCAL_MODULE := {{.MkName}} 226*333d2b36SAndroid Build Coastguard WorkerLOCAL_MODULE_CLASS := JAVA_LIBRARIES 227*333d2b36SAndroid Build Coastguard WorkerLOCAL_UNINSTALLABLE_MODULE := true 228*333d2b36SAndroid Build Coastguard WorkerLOCAL_SRC_FILES := {{.ArtifactFile}} 229*333d2b36SAndroid Build Coastguard WorkerLOCAL_BUILT_MODULE_STEM := javalib.jar 230*333d2b36SAndroid Build Coastguard WorkerLOCAL_MODULE_SUFFIX := .{{.Packaging}} 231*333d2b36SAndroid Build Coastguard WorkerLOCAL_USE_AAPT2 := true 232*333d2b36SAndroid Build Coastguard WorkerLOCAL_SDK_VERSION := {{.SdkVersion}} 233*333d2b36SAndroid Build Coastguard WorkerLOCAL_STATIC_JAVA_LIBRARIES :={{range .MkJarDeps}} \ 234*333d2b36SAndroid Build Coastguard Worker {{.}}{{end}} 235*333d2b36SAndroid Build Coastguard WorkerLOCAL_STATIC_ANDROID_LIBRARIES :={{range .MkAarDeps}} \ 236*333d2b36SAndroid Build Coastguard Worker {{.}}{{end}} 237*333d2b36SAndroid Build Coastguard WorkerLOCAL_JETIFIER_ENABLED := {{if .Jetifier}}true{{end}} 238*333d2b36SAndroid Build Coastguard Workerinclude $(BUILD_PREBUILT) 239*333d2b36SAndroid Build Coastguard Worker`)) 240*333d2b36SAndroid Build Coastguard Worker 241*333d2b36SAndroid Build Coastguard Workervar mkDepsTemplate = template.Must(template.New("mk").Parse(` 242*333d2b36SAndroid Build Coastguard Workerinclude $(CLEAR_VARS) 243*333d2b36SAndroid Build Coastguard WorkerLOCAL_MODULE := {{.MkName}}-nodeps 244*333d2b36SAndroid Build Coastguard WorkerLOCAL_MODULE_CLASS := JAVA_LIBRARIES 245*333d2b36SAndroid Build Coastguard WorkerLOCAL_UNINSTALLABLE_MODULE := true 246*333d2b36SAndroid Build Coastguard WorkerLOCAL_SRC_FILES := {{.ArtifactFile}} 247*333d2b36SAndroid Build Coastguard WorkerLOCAL_BUILT_MODULE_STEM := javalib.jar 248*333d2b36SAndroid Build Coastguard WorkerLOCAL_MODULE_SUFFIX := .{{.Packaging}} 249*333d2b36SAndroid Build Coastguard WorkerLOCAL_USE_AAPT2 := true 250*333d2b36SAndroid Build Coastguard WorkerLOCAL_SDK_VERSION := {{.SdkVersion}} 251*333d2b36SAndroid Build Coastguard WorkerLOCAL_STATIC_ANDROID_LIBRARIES :={{range .MkAarDeps}} \ 252*333d2b36SAndroid Build Coastguard Worker {{.}}{{end}} 253*333d2b36SAndroid Build Coastguard Workerinclude $(BUILD_PREBUILT) 254*333d2b36SAndroid Build Coastguard Workerinclude $(CLEAR_VARS) 255*333d2b36SAndroid Build Coastguard WorkerLOCAL_MODULE := {{.MkName}} 256*333d2b36SAndroid Build Coastguard WorkerLOCAL_SDK_VERSION := {{.SdkVersion}}{{if .IsAar}} 257*333d2b36SAndroid Build Coastguard WorkerLOCAL_MANIFEST_FILE := manifests/{{.MkName}}/AndroidManifest.xml{{end}} 258*333d2b36SAndroid Build Coastguard WorkerLOCAL_STATIC_JAVA_LIBRARIES :={{if .IsJar}} \ 259*333d2b36SAndroid Build Coastguard Worker {{.MkName}}-nodeps{{end}}{{range .MkJarDeps}} \ 260*333d2b36SAndroid Build Coastguard Worker {{.}}{{end}} 261*333d2b36SAndroid Build Coastguard WorkerLOCAL_STATIC_ANDROID_LIBRARIES :={{if .IsAar}} \ 262*333d2b36SAndroid Build Coastguard Worker {{.MkName}}-nodeps{{end}}{{range .MkAarDeps}} \ 263*333d2b36SAndroid Build Coastguard Worker {{.}}{{end}} 264*333d2b36SAndroid Build Coastguard WorkerLOCAL_JAR_EXCLUDE_FILES := none 265*333d2b36SAndroid Build Coastguard WorkerLOCAL_JAVA_LANGUAGE_VERSION := 1.8 266*333d2b36SAndroid Build Coastguard WorkerLOCAL_USE_AAPT2 := true 267*333d2b36SAndroid Build Coastguard Workerinclude $(BUILD_STATIC_JAVA_LIBRARY) 268*333d2b36SAndroid Build Coastguard Worker`)) 269*333d2b36SAndroid Build Coastguard Worker 270*333d2b36SAndroid Build Coastguard Workerfunc parse(filename string) (*Pom, error) { 271*333d2b36SAndroid Build Coastguard Worker data, err := ioutil.ReadFile(filename) 272*333d2b36SAndroid Build Coastguard Worker if err != nil { 273*333d2b36SAndroid Build Coastguard Worker return nil, err 274*333d2b36SAndroid Build Coastguard Worker } 275*333d2b36SAndroid Build Coastguard Worker 276*333d2b36SAndroid Build Coastguard Worker var pom Pom 277*333d2b36SAndroid Build Coastguard Worker err = xml.Unmarshal(data, &pom) 278*333d2b36SAndroid Build Coastguard Worker if err != nil { 279*333d2b36SAndroid Build Coastguard Worker return nil, err 280*333d2b36SAndroid Build Coastguard Worker } 281*333d2b36SAndroid Build Coastguard Worker 282*333d2b36SAndroid Build Coastguard Worker if useVersion != "" && pom.Version != useVersion { 283*333d2b36SAndroid Build Coastguard Worker return nil, nil 284*333d2b36SAndroid Build Coastguard Worker } 285*333d2b36SAndroid Build Coastguard Worker 286*333d2b36SAndroid Build Coastguard Worker if pom.Packaging == "" { 287*333d2b36SAndroid Build Coastguard Worker pom.Packaging = "jar" 288*333d2b36SAndroid Build Coastguard Worker } 289*333d2b36SAndroid Build Coastguard Worker 290*333d2b36SAndroid Build Coastguard Worker pom.PomFile = filename 291*333d2b36SAndroid Build Coastguard Worker pom.ArtifactFile = strings.TrimSuffix(filename, ".pom") + "." + pom.Packaging 292*333d2b36SAndroid Build Coastguard Worker 293*333d2b36SAndroid Build Coastguard Worker return &pom, nil 294*333d2b36SAndroid Build Coastguard Worker} 295*333d2b36SAndroid Build Coastguard Worker 296*333d2b36SAndroid Build Coastguard Workerfunc rerunForRegen(filename string) error { 297*333d2b36SAndroid Build Coastguard Worker buf, err := ioutil.ReadFile(filename) 298*333d2b36SAndroid Build Coastguard Worker if err != nil { 299*333d2b36SAndroid Build Coastguard Worker return err 300*333d2b36SAndroid Build Coastguard Worker } 301*333d2b36SAndroid Build Coastguard Worker 302*333d2b36SAndroid Build Coastguard Worker scanner := bufio.NewScanner(bytes.NewBuffer(buf)) 303*333d2b36SAndroid Build Coastguard Worker 304*333d2b36SAndroid Build Coastguard Worker // Skip the first line in the file 305*333d2b36SAndroid Build Coastguard Worker for i := 0; i < 2; i++ { 306*333d2b36SAndroid Build Coastguard Worker if !scanner.Scan() { 307*333d2b36SAndroid Build Coastguard Worker if scanner.Err() != nil { 308*333d2b36SAndroid Build Coastguard Worker return scanner.Err() 309*333d2b36SAndroid Build Coastguard Worker } else { 310*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf("unexpected EOF") 311*333d2b36SAndroid Build Coastguard Worker } 312*333d2b36SAndroid Build Coastguard Worker } 313*333d2b36SAndroid Build Coastguard Worker } 314*333d2b36SAndroid Build Coastguard Worker 315*333d2b36SAndroid Build Coastguard Worker // Extract the old args from the file 316*333d2b36SAndroid Build Coastguard Worker line := scanner.Text() 317*333d2b36SAndroid Build Coastguard Worker if strings.HasPrefix(line, "# pom2mk ") { 318*333d2b36SAndroid Build Coastguard Worker line = strings.TrimPrefix(line, "# pom2mk ") 319*333d2b36SAndroid Build Coastguard Worker } else { 320*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf("unexpected second line: %q", line) 321*333d2b36SAndroid Build Coastguard Worker } 322*333d2b36SAndroid Build Coastguard Worker args := strings.Split(line, " ") 323*333d2b36SAndroid Build Coastguard Worker lastArg := args[len(args)-1] 324*333d2b36SAndroid Build Coastguard Worker args = args[:len(args)-1] 325*333d2b36SAndroid Build Coastguard Worker 326*333d2b36SAndroid Build Coastguard Worker // Append all current command line args except -regen <file> to the ones from the file 327*333d2b36SAndroid Build Coastguard Worker for i := 1; i < len(os.Args); i++ { 328*333d2b36SAndroid Build Coastguard Worker if os.Args[i] == "-regen" { 329*333d2b36SAndroid Build Coastguard Worker i++ 330*333d2b36SAndroid Build Coastguard Worker } else { 331*333d2b36SAndroid Build Coastguard Worker args = append(args, os.Args[i]) 332*333d2b36SAndroid Build Coastguard Worker } 333*333d2b36SAndroid Build Coastguard Worker } 334*333d2b36SAndroid Build Coastguard Worker args = append(args, lastArg) 335*333d2b36SAndroid Build Coastguard Worker 336*333d2b36SAndroid Build Coastguard Worker cmd := os.Args[0] + " " + strings.Join(args, " ") 337*333d2b36SAndroid Build Coastguard Worker // Re-exec pom2mk with the new arguments 338*333d2b36SAndroid Build Coastguard Worker output, err := exec.Command("/bin/sh", "-c", cmd).Output() 339*333d2b36SAndroid Build Coastguard Worker if exitErr, _ := err.(*exec.ExitError); exitErr != nil { 340*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf("failed to run %s\n%s", cmd, string(exitErr.Stderr)) 341*333d2b36SAndroid Build Coastguard Worker } else if err != nil { 342*333d2b36SAndroid Build Coastguard Worker return err 343*333d2b36SAndroid Build Coastguard Worker } 344*333d2b36SAndroid Build Coastguard Worker 345*333d2b36SAndroid Build Coastguard Worker return ioutil.WriteFile(filename, output, 0666) 346*333d2b36SAndroid Build Coastguard Worker} 347*333d2b36SAndroid Build Coastguard Worker 348*333d2b36SAndroid Build Coastguard Workerfunc main() { 349*333d2b36SAndroid Build Coastguard Worker flag.Usage = func() { 350*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(os.Stderr, `pom2mk, a tool to create Android.mk files from maven repos 351*333d2b36SAndroid Build Coastguard Worker 352*333d2b36SAndroid Build Coastguard WorkerThe tool will extract the necessary information from *.pom files to create an Android.mk whose 353*333d2b36SAndroid Build Coastguard Workeraar libraries can be linked against when using AAPT2. 354*333d2b36SAndroid Build Coastguard Worker 355*333d2b36SAndroid Build Coastguard WorkerUsage: %s [--rewrite <regex>=<replace>] [-exclude <module>] [--extra-deps <module>=<module>[,<module>]] [<dir>] [-regen <file>] 356*333d2b36SAndroid Build Coastguard Worker 357*333d2b36SAndroid Build Coastguard Worker -rewrite <regex>=<replace> 358*333d2b36SAndroid Build Coastguard Worker rewrite can be used to specify mappings between Maven projects and Make modules. The -rewrite 359*333d2b36SAndroid Build Coastguard Worker option can be specified multiple times. When determining the Make module for a given Maven 360*333d2b36SAndroid Build Coastguard Worker project, mappings are searched in the order they were specified. The first <regex> matching 361*333d2b36SAndroid Build Coastguard Worker either the Maven project's <groupId>:<artifactId> or <artifactId> will be used to generate 362*333d2b36SAndroid Build Coastguard Worker the Make module name using <replace>. If no matches are found, <artifactId> is used. 363*333d2b36SAndroid Build Coastguard Worker -exclude <module> 364*333d2b36SAndroid Build Coastguard Worker Don't put the specified module in the makefile. 365*333d2b36SAndroid Build Coastguard Worker -extra-deps <module>=<module>[,<module>] 366*333d2b36SAndroid Build Coastguard Worker Some Android.mk modules have transitive dependencies that must be specified when they are 367*333d2b36SAndroid Build Coastguard Worker depended upon (like android-support-v7-mediarouter requires android-support-v7-appcompat). 368*333d2b36SAndroid Build Coastguard Worker This may be specified multiple times to declare these dependencies. 369*333d2b36SAndroid Build Coastguard Worker -sdk-version <version> 370*333d2b36SAndroid Build Coastguard Worker Sets LOCAL_SDK_VERSION := <version> for all modules. 371*333d2b36SAndroid Build Coastguard Worker -use-version <version> 372*333d2b36SAndroid Build Coastguard Worker If the maven directory contains multiple versions of artifacts and their pom files, 373*333d2b36SAndroid Build Coastguard Worker -use-version can be used to only write makefiles for a specific version of those artifacts. 374*333d2b36SAndroid Build Coastguard Worker -static-deps 375*333d2b36SAndroid Build Coastguard Worker Whether to statically include direct dependencies. 376*333d2b36SAndroid Build Coastguard Worker -jetifier 377*333d2b36SAndroid Build Coastguard Worker Enable jetifier in order to use androidx 378*333d2b36SAndroid Build Coastguard Worker <dir> 379*333d2b36SAndroid Build Coastguard Worker The directory to search for *.pom files under. 380*333d2b36SAndroid Build Coastguard Worker The makefile is written to stdout, to be put in the current directory (often as Android.mk) 381*333d2b36SAndroid Build Coastguard Worker -regen <file> 382*333d2b36SAndroid Build Coastguard Worker Read arguments from <file> and overwrite it. 383*333d2b36SAndroid Build Coastguard Worker`, os.Args[0]) 384*333d2b36SAndroid Build Coastguard Worker } 385*333d2b36SAndroid Build Coastguard Worker 386*333d2b36SAndroid Build Coastguard Worker var regen string 387*333d2b36SAndroid Build Coastguard Worker 388*333d2b36SAndroid Build Coastguard Worker flag.Var(&excludes, "exclude", "Exclude module") 389*333d2b36SAndroid Build Coastguard Worker flag.Var(&extraDeps, "extra-deps", "Extra dependencies needed when depending on a module") 390*333d2b36SAndroid Build Coastguard Worker flag.Var(&rewriteNames, "rewrite", "Regex(es) to rewrite artifact names") 391*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&sdkVersion, "sdk-version", "", "What to write to LOCAL_SDK_VERSION") 392*333d2b36SAndroid Build Coastguard Worker flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version") 393*333d2b36SAndroid Build Coastguard Worker flag.BoolVar(&staticDeps, "static-deps", false, "Statically include direct dependencies") 394*333d2b36SAndroid Build Coastguard Worker flag.BoolVar(&jetifier, "jetifier", false, "Enable jetifier in order to use androidx") 395*333d2b36SAndroid Build Coastguard Worker flag.StringVar(®en, "regen", "", "Rewrite specified file") 396*333d2b36SAndroid Build Coastguard Worker flag.Parse() 397*333d2b36SAndroid Build Coastguard Worker 398*333d2b36SAndroid Build Coastguard Worker if regen != "" { 399*333d2b36SAndroid Build Coastguard Worker err := rerunForRegen(regen) 400*333d2b36SAndroid Build Coastguard Worker if err != nil { 401*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, err) 402*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 403*333d2b36SAndroid Build Coastguard Worker } 404*333d2b36SAndroid Build Coastguard Worker os.Exit(0) 405*333d2b36SAndroid Build Coastguard Worker } 406*333d2b36SAndroid Build Coastguard Worker 407*333d2b36SAndroid Build Coastguard Worker if flag.NArg() == 0 { 408*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "Directory argument is required") 409*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 410*333d2b36SAndroid Build Coastguard Worker } else if flag.NArg() > 1 { 411*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "Multiple directories provided:", strings.Join(flag.Args(), " ")) 412*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 413*333d2b36SAndroid Build Coastguard Worker } 414*333d2b36SAndroid Build Coastguard Worker 415*333d2b36SAndroid Build Coastguard Worker dir := flag.Arg(0) 416*333d2b36SAndroid Build Coastguard Worker absDir, err := filepath.Abs(dir) 417*333d2b36SAndroid Build Coastguard Worker if err != nil { 418*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "Failed to get absolute directory:", err) 419*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 420*333d2b36SAndroid Build Coastguard Worker } 421*333d2b36SAndroid Build Coastguard Worker 422*333d2b36SAndroid Build Coastguard Worker var filenames []string 423*333d2b36SAndroid Build Coastguard Worker err = filepath.Walk(absDir, func(path string, info os.FileInfo, err error) error { 424*333d2b36SAndroid Build Coastguard Worker if err != nil { 425*333d2b36SAndroid Build Coastguard Worker return err 426*333d2b36SAndroid Build Coastguard Worker } 427*333d2b36SAndroid Build Coastguard Worker 428*333d2b36SAndroid Build Coastguard Worker name := info.Name() 429*333d2b36SAndroid Build Coastguard Worker if info.IsDir() { 430*333d2b36SAndroid Build Coastguard Worker if strings.HasPrefix(name, ".") { 431*333d2b36SAndroid Build Coastguard Worker return filepath.SkipDir 432*333d2b36SAndroid Build Coastguard Worker } 433*333d2b36SAndroid Build Coastguard Worker return nil 434*333d2b36SAndroid Build Coastguard Worker } 435*333d2b36SAndroid Build Coastguard Worker 436*333d2b36SAndroid Build Coastguard Worker if strings.HasPrefix(name, ".") { 437*333d2b36SAndroid Build Coastguard Worker return nil 438*333d2b36SAndroid Build Coastguard Worker } 439*333d2b36SAndroid Build Coastguard Worker 440*333d2b36SAndroid Build Coastguard Worker if strings.HasSuffix(name, ".pom") { 441*333d2b36SAndroid Build Coastguard Worker path, err = filepath.Rel(absDir, path) 442*333d2b36SAndroid Build Coastguard Worker if err != nil { 443*333d2b36SAndroid Build Coastguard Worker return err 444*333d2b36SAndroid Build Coastguard Worker } 445*333d2b36SAndroid Build Coastguard Worker filenames = append(filenames, filepath.Join(dir, path)) 446*333d2b36SAndroid Build Coastguard Worker } 447*333d2b36SAndroid Build Coastguard Worker return nil 448*333d2b36SAndroid Build Coastguard Worker }) 449*333d2b36SAndroid Build Coastguard Worker if err != nil { 450*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "Error walking files:", err) 451*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 452*333d2b36SAndroid Build Coastguard Worker } 453*333d2b36SAndroid Build Coastguard Worker 454*333d2b36SAndroid Build Coastguard Worker if len(filenames) == 0 { 455*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "Error: no *.pom files found under", dir) 456*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 457*333d2b36SAndroid Build Coastguard Worker } 458*333d2b36SAndroid Build Coastguard Worker 459*333d2b36SAndroid Build Coastguard Worker sort.Strings(filenames) 460*333d2b36SAndroid Build Coastguard Worker 461*333d2b36SAndroid Build Coastguard Worker poms := []*Pom{} 462*333d2b36SAndroid Build Coastguard Worker modules := make(map[string]*Pom) 463*333d2b36SAndroid Build Coastguard Worker duplicate := false 464*333d2b36SAndroid Build Coastguard Worker for _, filename := range filenames { 465*333d2b36SAndroid Build Coastguard Worker pom, err := parse(filename) 466*333d2b36SAndroid Build Coastguard Worker if err != nil { 467*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "Error converting", filename, err) 468*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 469*333d2b36SAndroid Build Coastguard Worker } 470*333d2b36SAndroid Build Coastguard Worker 471*333d2b36SAndroid Build Coastguard Worker if pom != nil { 472*333d2b36SAndroid Build Coastguard Worker key := pom.MkName() 473*333d2b36SAndroid Build Coastguard Worker if excludes[key] { 474*333d2b36SAndroid Build Coastguard Worker continue 475*333d2b36SAndroid Build Coastguard Worker } 476*333d2b36SAndroid Build Coastguard Worker 477*333d2b36SAndroid Build Coastguard Worker if old, ok := modules[key]; ok { 478*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "Module", key, "defined twice:", old.PomFile, pom.PomFile) 479*333d2b36SAndroid Build Coastguard Worker duplicate = true 480*333d2b36SAndroid Build Coastguard Worker } 481*333d2b36SAndroid Build Coastguard Worker 482*333d2b36SAndroid Build Coastguard Worker poms = append(poms, pom) 483*333d2b36SAndroid Build Coastguard Worker modules[key] = pom 484*333d2b36SAndroid Build Coastguard Worker } 485*333d2b36SAndroid Build Coastguard Worker } 486*333d2b36SAndroid Build Coastguard Worker if duplicate { 487*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 488*333d2b36SAndroid Build Coastguard Worker } 489*333d2b36SAndroid Build Coastguard Worker 490*333d2b36SAndroid Build Coastguard Worker for _, pom := range poms { 491*333d2b36SAndroid Build Coastguard Worker pom.FixDeps(modules) 492*333d2b36SAndroid Build Coastguard Worker } 493*333d2b36SAndroid Build Coastguard Worker 494*333d2b36SAndroid Build Coastguard Worker fmt.Println("# Automatically generated with:") 495*333d2b36SAndroid Build Coastguard Worker fmt.Println("# pom2mk", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " ")) 496*333d2b36SAndroid Build Coastguard Worker fmt.Println("LOCAL_PATH := $(call my-dir)") 497*333d2b36SAndroid Build Coastguard Worker 498*333d2b36SAndroid Build Coastguard Worker for _, pom := range poms { 499*333d2b36SAndroid Build Coastguard Worker var err error 500*333d2b36SAndroid Build Coastguard Worker if staticDeps { 501*333d2b36SAndroid Build Coastguard Worker err = mkDepsTemplate.Execute(os.Stdout, pom) 502*333d2b36SAndroid Build Coastguard Worker } else { 503*333d2b36SAndroid Build Coastguard Worker err = mkTemplate.Execute(os.Stdout, pom) 504*333d2b36SAndroid Build Coastguard Worker } 505*333d2b36SAndroid Build Coastguard Worker if err != nil { 506*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "Error writing", pom.PomFile, pom.MkName(), err) 507*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 508*333d2b36SAndroid Build Coastguard Worker } 509*333d2b36SAndroid Build Coastguard Worker } 510*333d2b36SAndroid Build Coastguard Worker} 511