xref: /aosp_15_r20/build/soong/cmd/go2bp/go2bp.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2021 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/json"
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	"sort"
28*333d2b36SAndroid Build Coastguard Worker	"strings"
29*333d2b36SAndroid Build Coastguard Worker	"text/template"
30*333d2b36SAndroid Build Coastguard Worker
31*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
32*333d2b36SAndroid Build Coastguard Worker
33*333d2b36SAndroid Build Coastguard Worker	"android/soong/bpfix/bpfix"
34*333d2b36SAndroid Build Coastguard Worker)
35*333d2b36SAndroid Build Coastguard Worker
36*333d2b36SAndroid Build Coastguard Workertype RewriteNames []RewriteName
37*333d2b36SAndroid Build Coastguard Workertype RewriteName struct {
38*333d2b36SAndroid Build Coastguard Worker	prefix string
39*333d2b36SAndroid Build Coastguard Worker	repl   string
40*333d2b36SAndroid Build Coastguard Worker}
41*333d2b36SAndroid Build Coastguard Worker
42*333d2b36SAndroid Build Coastguard Workerfunc (r *RewriteNames) String() string {
43*333d2b36SAndroid Build Coastguard Worker	return ""
44*333d2b36SAndroid Build Coastguard Worker}
45*333d2b36SAndroid Build Coastguard Worker
46*333d2b36SAndroid Build Coastguard Workerfunc (r *RewriteNames) Set(v string) error {
47*333d2b36SAndroid Build Coastguard Worker	split := strings.SplitN(v, "=", 2)
48*333d2b36SAndroid Build Coastguard Worker	if len(split) != 2 {
49*333d2b36SAndroid Build Coastguard Worker		return fmt.Errorf("Must be in the form of <prefix>=<replace>")
50*333d2b36SAndroid Build Coastguard Worker	}
51*333d2b36SAndroid Build Coastguard Worker	*r = append(*r, RewriteName{
52*333d2b36SAndroid Build Coastguard Worker		prefix: split[0],
53*333d2b36SAndroid Build Coastguard Worker		repl:   split[1],
54*333d2b36SAndroid Build Coastguard Worker	})
55*333d2b36SAndroid Build Coastguard Worker	return nil
56*333d2b36SAndroid Build Coastguard Worker}
57*333d2b36SAndroid Build Coastguard Worker
58*333d2b36SAndroid Build Coastguard Workerfunc (r *RewriteNames) GoToBp(name string) string {
59*333d2b36SAndroid Build Coastguard Worker	ret := name
60*333d2b36SAndroid Build Coastguard Worker	for _, r := range *r {
61*333d2b36SAndroid Build Coastguard Worker		prefix := r.prefix
62*333d2b36SAndroid Build Coastguard Worker		if name == prefix {
63*333d2b36SAndroid Build Coastguard Worker			ret = r.repl
64*333d2b36SAndroid Build Coastguard Worker			break
65*333d2b36SAndroid Build Coastguard Worker		}
66*333d2b36SAndroid Build Coastguard Worker		prefix += "/"
67*333d2b36SAndroid Build Coastguard Worker		if strings.HasPrefix(name, prefix) {
68*333d2b36SAndroid Build Coastguard Worker			ret = r.repl + "-" + strings.TrimPrefix(name, prefix)
69*333d2b36SAndroid Build Coastguard Worker		}
70*333d2b36SAndroid Build Coastguard Worker	}
71*333d2b36SAndroid Build Coastguard Worker	return strings.ReplaceAll(ret, "/", "-")
72*333d2b36SAndroid Build Coastguard Worker}
73*333d2b36SAndroid Build Coastguard Worker
74*333d2b36SAndroid Build Coastguard Workervar rewriteNames = RewriteNames{}
75*333d2b36SAndroid Build Coastguard Worker
76*333d2b36SAndroid Build Coastguard Workertype Exclude map[string]bool
77*333d2b36SAndroid Build Coastguard Worker
78*333d2b36SAndroid Build Coastguard Workerfunc (e Exclude) String() string {
79*333d2b36SAndroid Build Coastguard Worker	return ""
80*333d2b36SAndroid Build Coastguard Worker}
81*333d2b36SAndroid Build Coastguard Worker
82*333d2b36SAndroid Build Coastguard Workerfunc (e Exclude) Set(v string) error {
83*333d2b36SAndroid Build Coastguard Worker	e[v] = true
84*333d2b36SAndroid Build Coastguard Worker	return nil
85*333d2b36SAndroid Build Coastguard Worker}
86*333d2b36SAndroid Build Coastguard Worker
87*333d2b36SAndroid Build Coastguard Workervar excludes = make(Exclude)
88*333d2b36SAndroid Build Coastguard Workervar excludeDeps = make(Exclude)
89*333d2b36SAndroid Build Coastguard Workervar excludeSrcs = make(Exclude)
90*333d2b36SAndroid Build Coastguard Worker
91*333d2b36SAndroid Build Coastguard Workertype StringList []string
92*333d2b36SAndroid Build Coastguard Worker
93*333d2b36SAndroid Build Coastguard Workerfunc (l *StringList) String() string {
94*333d2b36SAndroid Build Coastguard Worker	return strings.Join(*l, " ")
95*333d2b36SAndroid Build Coastguard Worker}
96*333d2b36SAndroid Build Coastguard Worker
97*333d2b36SAndroid Build Coastguard Workerfunc (l *StringList) Set(v string) error {
98*333d2b36SAndroid Build Coastguard Worker	*l = append(*l, strings.Fields(v)...)
99*333d2b36SAndroid Build Coastguard Worker	return nil
100*333d2b36SAndroid Build Coastguard Worker}
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Workertype GoModule struct {
103*333d2b36SAndroid Build Coastguard Worker	Dir string
104*333d2b36SAndroid Build Coastguard Worker}
105*333d2b36SAndroid Build Coastguard Worker
106*333d2b36SAndroid Build Coastguard Workertype GoPackage struct {
107*333d2b36SAndroid Build Coastguard Worker	ExportToAndroid bool
108*333d2b36SAndroid Build Coastguard Worker
109*333d2b36SAndroid Build Coastguard Worker	Dir         string
110*333d2b36SAndroid Build Coastguard Worker	ImportPath  string
111*333d2b36SAndroid Build Coastguard Worker	Name        string
112*333d2b36SAndroid Build Coastguard Worker	Imports     []string
113*333d2b36SAndroid Build Coastguard Worker	GoFiles     []string
114*333d2b36SAndroid Build Coastguard Worker	TestGoFiles []string
115*333d2b36SAndroid Build Coastguard Worker	TestImports []string
116*333d2b36SAndroid Build Coastguard Worker
117*333d2b36SAndroid Build Coastguard Worker	Module *GoModule
118*333d2b36SAndroid Build Coastguard Worker}
119*333d2b36SAndroid Build Coastguard Worker
120*333d2b36SAndroid Build Coastguard Workerfunc (g GoPackage) IsCommand() bool {
121*333d2b36SAndroid Build Coastguard Worker	return g.Name == "main"
122*333d2b36SAndroid Build Coastguard Worker}
123*333d2b36SAndroid Build Coastguard Worker
124*333d2b36SAndroid Build Coastguard Workerfunc (g GoPackage) BpModuleType() string {
125*333d2b36SAndroid Build Coastguard Worker	if g.IsCommand() {
126*333d2b36SAndroid Build Coastguard Worker		return "blueprint_go_binary"
127*333d2b36SAndroid Build Coastguard Worker	}
128*333d2b36SAndroid Build Coastguard Worker	return "bootstrap_go_package"
129*333d2b36SAndroid Build Coastguard Worker}
130*333d2b36SAndroid Build Coastguard Worker
131*333d2b36SAndroid Build Coastguard Workerfunc (g GoPackage) BpName() string {
132*333d2b36SAndroid Build Coastguard Worker	if g.IsCommand() {
133*333d2b36SAndroid Build Coastguard Worker		return rewriteNames.GoToBp(filepath.Base(g.ImportPath))
134*333d2b36SAndroid Build Coastguard Worker	}
135*333d2b36SAndroid Build Coastguard Worker	return rewriteNames.GoToBp(g.ImportPath)
136*333d2b36SAndroid Build Coastguard Worker}
137*333d2b36SAndroid Build Coastguard Worker
138*333d2b36SAndroid Build Coastguard Workerfunc (g GoPackage) BpDeps(deps []string) []string {
139*333d2b36SAndroid Build Coastguard Worker	var ret []string
140*333d2b36SAndroid Build Coastguard Worker	for _, d := range deps {
141*333d2b36SAndroid Build Coastguard Worker		// Ignore stdlib dependencies
142*333d2b36SAndroid Build Coastguard Worker		if !strings.Contains(d, ".") {
143*333d2b36SAndroid Build Coastguard Worker			continue
144*333d2b36SAndroid Build Coastguard Worker		}
145*333d2b36SAndroid Build Coastguard Worker		if _, ok := excludeDeps[d]; ok {
146*333d2b36SAndroid Build Coastguard Worker			continue
147*333d2b36SAndroid Build Coastguard Worker		}
148*333d2b36SAndroid Build Coastguard Worker		name := rewriteNames.GoToBp(d)
149*333d2b36SAndroid Build Coastguard Worker		ret = append(ret, name)
150*333d2b36SAndroid Build Coastguard Worker	}
151*333d2b36SAndroid Build Coastguard Worker	return ret
152*333d2b36SAndroid Build Coastguard Worker}
153*333d2b36SAndroid Build Coastguard Worker
154*333d2b36SAndroid Build Coastguard Workerfunc (g GoPackage) BpSrcs(srcs []string) []string {
155*333d2b36SAndroid Build Coastguard Worker	var ret []string
156*333d2b36SAndroid Build Coastguard Worker	prefix, err := filepath.Rel(g.Module.Dir, g.Dir)
157*333d2b36SAndroid Build Coastguard Worker	if err != nil {
158*333d2b36SAndroid Build Coastguard Worker		panic(err)
159*333d2b36SAndroid Build Coastguard Worker	}
160*333d2b36SAndroid Build Coastguard Worker	for _, f := range srcs {
161*333d2b36SAndroid Build Coastguard Worker		f = filepath.Join(prefix, f)
162*333d2b36SAndroid Build Coastguard Worker		if _, ok := excludeSrcs[f]; ok {
163*333d2b36SAndroid Build Coastguard Worker			continue
164*333d2b36SAndroid Build Coastguard Worker		}
165*333d2b36SAndroid Build Coastguard Worker		ret = append(ret, f)
166*333d2b36SAndroid Build Coastguard Worker	}
167*333d2b36SAndroid Build Coastguard Worker	return ret
168*333d2b36SAndroid Build Coastguard Worker}
169*333d2b36SAndroid Build Coastguard Worker
170*333d2b36SAndroid Build Coastguard Worker// AllImports combines Imports and TestImports, as blueprint does not differentiate these.
171*333d2b36SAndroid Build Coastguard Workerfunc (g GoPackage) AllImports() []string {
172*333d2b36SAndroid Build Coastguard Worker	imports := append([]string(nil), g.Imports...)
173*333d2b36SAndroid Build Coastguard Worker	imports = append(imports, g.TestImports...)
174*333d2b36SAndroid Build Coastguard Worker
175*333d2b36SAndroid Build Coastguard Worker	if len(imports) == 0 {
176*333d2b36SAndroid Build Coastguard Worker		return nil
177*333d2b36SAndroid Build Coastguard Worker	}
178*333d2b36SAndroid Build Coastguard Worker
179*333d2b36SAndroid Build Coastguard Worker	// Sort and de-duplicate
180*333d2b36SAndroid Build Coastguard Worker	sort.Strings(imports)
181*333d2b36SAndroid Build Coastguard Worker	j := 0
182*333d2b36SAndroid Build Coastguard Worker	for i := 1; i < len(imports); i++ {
183*333d2b36SAndroid Build Coastguard Worker		if imports[i] == imports[j] {
184*333d2b36SAndroid Build Coastguard Worker			continue
185*333d2b36SAndroid Build Coastguard Worker		}
186*333d2b36SAndroid Build Coastguard Worker		j++
187*333d2b36SAndroid Build Coastguard Worker		imports[j] = imports[i]
188*333d2b36SAndroid Build Coastguard Worker	}
189*333d2b36SAndroid Build Coastguard Worker	return imports[:j+1]
190*333d2b36SAndroid Build Coastguard Worker}
191*333d2b36SAndroid Build Coastguard Worker
192*333d2b36SAndroid Build Coastguard Workervar bpTemplate = template.Must(template.New("bp").Parse(`
193*333d2b36SAndroid Build Coastguard Worker{{.BpModuleType}} {
194*333d2b36SAndroid Build Coastguard Worker    name: "{{.BpName}}",
195*333d2b36SAndroid Build Coastguard Worker    {{- if not .IsCommand}}
196*333d2b36SAndroid Build Coastguard Worker    pkgPath: "{{.ImportPath}}",
197*333d2b36SAndroid Build Coastguard Worker    {{- end}}
198*333d2b36SAndroid Build Coastguard Worker    {{- if .BpDeps .AllImports}}
199*333d2b36SAndroid Build Coastguard Worker    deps: [
200*333d2b36SAndroid Build Coastguard Worker        {{- range .BpDeps .AllImports}}
201*333d2b36SAndroid Build Coastguard Worker        "{{.}}",
202*333d2b36SAndroid Build Coastguard Worker        {{- end}}
203*333d2b36SAndroid Build Coastguard Worker    ],
204*333d2b36SAndroid Build Coastguard Worker    {{- end}}
205*333d2b36SAndroid Build Coastguard Worker    {{- if .BpSrcs .GoFiles}}
206*333d2b36SAndroid Build Coastguard Worker    srcs: [
207*333d2b36SAndroid Build Coastguard Worker        {{- range .BpSrcs .GoFiles}}
208*333d2b36SAndroid Build Coastguard Worker        "{{.}}",
209*333d2b36SAndroid Build Coastguard Worker        {{- end}}
210*333d2b36SAndroid Build Coastguard Worker    ],
211*333d2b36SAndroid Build Coastguard Worker    {{- end}}
212*333d2b36SAndroid Build Coastguard Worker    {{- if .BpSrcs .TestGoFiles}}
213*333d2b36SAndroid Build Coastguard Worker    testSrcs: [
214*333d2b36SAndroid Build Coastguard Worker    	{{- range .BpSrcs .TestGoFiles}}
215*333d2b36SAndroid Build Coastguard Worker        "{{.}}",
216*333d2b36SAndroid Build Coastguard Worker       {{- end}}
217*333d2b36SAndroid Build Coastguard Worker    ],
218*333d2b36SAndroid Build Coastguard Worker    {{- end}}
219*333d2b36SAndroid Build Coastguard Worker}
220*333d2b36SAndroid Build Coastguard Worker`))
221*333d2b36SAndroid Build Coastguard Worker
222*333d2b36SAndroid Build Coastguard Workerfunc rerunForRegen(filename string) error {
223*333d2b36SAndroid Build Coastguard Worker	buf, err := ioutil.ReadFile(filename)
224*333d2b36SAndroid Build Coastguard Worker	if err != nil {
225*333d2b36SAndroid Build Coastguard Worker		return err
226*333d2b36SAndroid Build Coastguard Worker	}
227*333d2b36SAndroid Build Coastguard Worker
228*333d2b36SAndroid Build Coastguard Worker	scanner := bufio.NewScanner(bytes.NewBuffer(buf))
229*333d2b36SAndroid Build Coastguard Worker
230*333d2b36SAndroid Build Coastguard Worker	// Skip the first line in the file
231*333d2b36SAndroid Build Coastguard Worker	for i := 0; i < 2; i++ {
232*333d2b36SAndroid Build Coastguard Worker		if !scanner.Scan() {
233*333d2b36SAndroid Build Coastguard Worker			if scanner.Err() != nil {
234*333d2b36SAndroid Build Coastguard Worker				return scanner.Err()
235*333d2b36SAndroid Build Coastguard Worker			} else {
236*333d2b36SAndroid Build Coastguard Worker				return fmt.Errorf("unexpected EOF")
237*333d2b36SAndroid Build Coastguard Worker			}
238*333d2b36SAndroid Build Coastguard Worker		}
239*333d2b36SAndroid Build Coastguard Worker	}
240*333d2b36SAndroid Build Coastguard Worker
241*333d2b36SAndroid Build Coastguard Worker	// Extract the old args from the file
242*333d2b36SAndroid Build Coastguard Worker	line := scanner.Text()
243*333d2b36SAndroid Build Coastguard Worker	if strings.HasPrefix(line, "// go2bp ") {
244*333d2b36SAndroid Build Coastguard Worker		line = strings.TrimPrefix(line, "// go2bp ")
245*333d2b36SAndroid Build Coastguard Worker	} else {
246*333d2b36SAndroid Build Coastguard Worker		return fmt.Errorf("unexpected second line: %q", line)
247*333d2b36SAndroid Build Coastguard Worker	}
248*333d2b36SAndroid Build Coastguard Worker	args := strings.Split(line, " ")
249*333d2b36SAndroid Build Coastguard Worker	lastArg := args[len(args)-1]
250*333d2b36SAndroid Build Coastguard Worker	args = args[:len(args)-1]
251*333d2b36SAndroid Build Coastguard Worker
252*333d2b36SAndroid Build Coastguard Worker	// Append all current command line args except -regen <file> to the ones from the file
253*333d2b36SAndroid Build Coastguard Worker	for i := 1; i < len(os.Args); i++ {
254*333d2b36SAndroid Build Coastguard Worker		if os.Args[i] == "-regen" || os.Args[i] == "--regen" {
255*333d2b36SAndroid Build Coastguard Worker			i++
256*333d2b36SAndroid Build Coastguard Worker		} else {
257*333d2b36SAndroid Build Coastguard Worker			args = append(args, os.Args[i])
258*333d2b36SAndroid Build Coastguard Worker		}
259*333d2b36SAndroid Build Coastguard Worker	}
260*333d2b36SAndroid Build Coastguard Worker	args = append(args, lastArg)
261*333d2b36SAndroid Build Coastguard Worker
262*333d2b36SAndroid Build Coastguard Worker	cmd := os.Args[0] + " " + strings.Join(args, " ")
263*333d2b36SAndroid Build Coastguard Worker	// Re-exec pom2bp with the new arguments
264*333d2b36SAndroid Build Coastguard Worker	output, err := exec.Command("/bin/sh", "-c", cmd).Output()
265*333d2b36SAndroid Build Coastguard Worker	if exitErr, _ := err.(*exec.ExitError); exitErr != nil {
266*333d2b36SAndroid Build Coastguard Worker		return fmt.Errorf("failed to run %s\n%s", cmd, string(exitErr.Stderr))
267*333d2b36SAndroid Build Coastguard Worker	} else if err != nil {
268*333d2b36SAndroid Build Coastguard Worker		return err
269*333d2b36SAndroid Build Coastguard Worker	}
270*333d2b36SAndroid Build Coastguard Worker
271*333d2b36SAndroid Build Coastguard Worker	return ioutil.WriteFile(filename, output, 0666)
272*333d2b36SAndroid Build Coastguard Worker}
273*333d2b36SAndroid Build Coastguard Worker
274*333d2b36SAndroid Build Coastguard Workerfunc main() {
275*333d2b36SAndroid Build Coastguard Worker	flag.Usage = func() {
276*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintf(os.Stderr, `go2bp, a tool to create Android.bp files from go modules
277*333d2b36SAndroid Build Coastguard Worker
278*333d2b36SAndroid Build Coastguard WorkerThe tool will extract the necessary information from Go files to create an Android.bp that can
279*333d2b36SAndroid Build Coastguard Workercompile them. This needs to be run from the same directory as the go.mod file.
280*333d2b36SAndroid Build Coastguard Worker
281*333d2b36SAndroid Build Coastguard WorkerUsage: %s [--rewrite <pkg-prefix>=<replace>] [-exclude <package>] [-regen <file>]
282*333d2b36SAndroid Build Coastguard Worker
283*333d2b36SAndroid Build Coastguard Worker  -rewrite <pkg-prefix>=<replace>
284*333d2b36SAndroid Build Coastguard Worker     rewrite can be used to specify mappings between go package paths and Android.bp modules. The -rewrite
285*333d2b36SAndroid Build Coastguard Worker     option can be specified multiple times. When determining the Android.bp module for a given Go
286*333d2b36SAndroid Build Coastguard Worker     package, mappings are searched in the order they were specified. The first <pkg-prefix> matching
287*333d2b36SAndroid Build Coastguard Worker     either the package directly, or as the prefix '<pkg-prefix>/' will be replaced with <replace>.
288*333d2b36SAndroid Build Coastguard Worker     After all replacements are finished, all '/' characters are replaced with '-'.
289*333d2b36SAndroid Build Coastguard Worker  -exclude <package>
290*333d2b36SAndroid Build Coastguard Worker     Don't put the specified go package in the Android.bp file.
291*333d2b36SAndroid Build Coastguard Worker  -exclude-deps <package>
292*333d2b36SAndroid Build Coastguard Worker     Don't put the specified go package in the dependency lists.
293*333d2b36SAndroid Build Coastguard Worker  -exclude-srcs <module>
294*333d2b36SAndroid Build Coastguard Worker     Don't put the specified source files in srcs or testSrcs lists.
295*333d2b36SAndroid Build Coastguard Worker  -limit <package>
296*333d2b36SAndroid Build Coastguard Worker     If set, limit the output to the specified packages and their dependencies.
297*333d2b36SAndroid Build Coastguard Worker  -skip-tests
298*333d2b36SAndroid Build Coastguard Worker     If passed, don't write out any test srcs or dependencies to the Android.bp output.
299*333d2b36SAndroid Build Coastguard Worker  -regen <file>
300*333d2b36SAndroid Build Coastguard Worker     Read arguments from <file> and overwrite it.
301*333d2b36SAndroid Build Coastguard Worker
302*333d2b36SAndroid Build Coastguard Worker`, os.Args[0])
303*333d2b36SAndroid Build Coastguard Worker	}
304*333d2b36SAndroid Build Coastguard Worker
305*333d2b36SAndroid Build Coastguard Worker	var regen string
306*333d2b36SAndroid Build Coastguard Worker	var skipTests bool
307*333d2b36SAndroid Build Coastguard Worker	limit := StringList{}
308*333d2b36SAndroid Build Coastguard Worker
309*333d2b36SAndroid Build Coastguard Worker	flag.Var(&excludes, "exclude", "Exclude go package")
310*333d2b36SAndroid Build Coastguard Worker	flag.Var(&excludeDeps, "exclude-dep", "Exclude go package from deps")
311*333d2b36SAndroid Build Coastguard Worker	flag.Var(&excludeSrcs, "exclude-src", "Exclude go file from source lists")
312*333d2b36SAndroid Build Coastguard Worker	flag.Var(&rewriteNames, "rewrite", "Regex(es) to rewrite artifact names")
313*333d2b36SAndroid Build Coastguard Worker	flag.Var(&limit, "limit", "If set, only includes the dependencies of the listed packages")
314*333d2b36SAndroid Build Coastguard Worker	flag.BoolVar(&skipTests, "skip-tests", false, "Whether to skip test sources")
315*333d2b36SAndroid Build Coastguard Worker	flag.StringVar(&regen, "regen", "", "Rewrite specified file")
316*333d2b36SAndroid Build Coastguard Worker	flag.Parse()
317*333d2b36SAndroid Build Coastguard Worker
318*333d2b36SAndroid Build Coastguard Worker	if regen != "" {
319*333d2b36SAndroid Build Coastguard Worker		err := rerunForRegen(regen)
320*333d2b36SAndroid Build Coastguard Worker		if err != nil {
321*333d2b36SAndroid Build Coastguard Worker			fmt.Fprintln(os.Stderr, err)
322*333d2b36SAndroid Build Coastguard Worker			os.Exit(1)
323*333d2b36SAndroid Build Coastguard Worker		}
324*333d2b36SAndroid Build Coastguard Worker		os.Exit(0)
325*333d2b36SAndroid Build Coastguard Worker	}
326*333d2b36SAndroid Build Coastguard Worker
327*333d2b36SAndroid Build Coastguard Worker	if flag.NArg() != 0 {
328*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintf(os.Stderr, "Unused argument detected: %v\n", flag.Args())
329*333d2b36SAndroid Build Coastguard Worker		os.Exit(1)
330*333d2b36SAndroid Build Coastguard Worker	}
331*333d2b36SAndroid Build Coastguard Worker
332*333d2b36SAndroid Build Coastguard Worker	if _, err := os.Stat("go.mod"); err != nil {
333*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(os.Stderr, "go.mod file not found")
334*333d2b36SAndroid Build Coastguard Worker		os.Exit(1)
335*333d2b36SAndroid Build Coastguard Worker	}
336*333d2b36SAndroid Build Coastguard Worker
337*333d2b36SAndroid Build Coastguard Worker	cmd := exec.Command("go", "list", "-json", "./...")
338*333d2b36SAndroid Build Coastguard Worker	var stdoutb, stderrb bytes.Buffer
339*333d2b36SAndroid Build Coastguard Worker	cmd.Stdout = &stdoutb
340*333d2b36SAndroid Build Coastguard Worker	cmd.Stderr = &stderrb
341*333d2b36SAndroid Build Coastguard Worker	if err := cmd.Run(); err != nil {
342*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintf(os.Stderr, "Running %q to dump the Go packages failed: %v, stderr:\n%s\n",
343*333d2b36SAndroid Build Coastguard Worker			cmd.String(), err, stderrb.Bytes())
344*333d2b36SAndroid Build Coastguard Worker		os.Exit(1)
345*333d2b36SAndroid Build Coastguard Worker	}
346*333d2b36SAndroid Build Coastguard Worker	decoder := json.NewDecoder(bytes.NewReader(stdoutb.Bytes()))
347*333d2b36SAndroid Build Coastguard Worker
348*333d2b36SAndroid Build Coastguard Worker	pkgs := []*GoPackage{}
349*333d2b36SAndroid Build Coastguard Worker	pkgMap := map[string]*GoPackage{}
350*333d2b36SAndroid Build Coastguard Worker	for decoder.More() {
351*333d2b36SAndroid Build Coastguard Worker		pkg := GoPackage{}
352*333d2b36SAndroid Build Coastguard Worker		err := decoder.Decode(&pkg)
353*333d2b36SAndroid Build Coastguard Worker		if err != nil {
354*333d2b36SAndroid Build Coastguard Worker			fmt.Fprintf(os.Stderr, "Failed to parse json: %v\n", err)
355*333d2b36SAndroid Build Coastguard Worker			os.Exit(1)
356*333d2b36SAndroid Build Coastguard Worker		}
357*333d2b36SAndroid Build Coastguard Worker		if len(limit) == 0 {
358*333d2b36SAndroid Build Coastguard Worker			pkg.ExportToAndroid = true
359*333d2b36SAndroid Build Coastguard Worker		}
360*333d2b36SAndroid Build Coastguard Worker		if skipTests {
361*333d2b36SAndroid Build Coastguard Worker			pkg.TestGoFiles = nil
362*333d2b36SAndroid Build Coastguard Worker			pkg.TestImports = nil
363*333d2b36SAndroid Build Coastguard Worker		}
364*333d2b36SAndroid Build Coastguard Worker		pkgs = append(pkgs, &pkg)
365*333d2b36SAndroid Build Coastguard Worker		pkgMap[pkg.ImportPath] = &pkg
366*333d2b36SAndroid Build Coastguard Worker	}
367*333d2b36SAndroid Build Coastguard Worker
368*333d2b36SAndroid Build Coastguard Worker	buf := &bytes.Buffer{}
369*333d2b36SAndroid Build Coastguard Worker
370*333d2b36SAndroid Build Coastguard Worker	fmt.Fprintln(buf, "// Automatically generated with:")
371*333d2b36SAndroid Build Coastguard Worker	fmt.Fprintln(buf, "// go2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
372*333d2b36SAndroid Build Coastguard Worker
373*333d2b36SAndroid Build Coastguard Worker	var mark func(string)
374*333d2b36SAndroid Build Coastguard Worker	mark = func(pkgName string) {
375*333d2b36SAndroid Build Coastguard Worker		if excludes[pkgName] {
376*333d2b36SAndroid Build Coastguard Worker			return
377*333d2b36SAndroid Build Coastguard Worker		}
378*333d2b36SAndroid Build Coastguard Worker		if pkg, ok := pkgMap[pkgName]; ok && !pkg.ExportToAndroid {
379*333d2b36SAndroid Build Coastguard Worker			pkg.ExportToAndroid = true
380*333d2b36SAndroid Build Coastguard Worker			for _, dep := range pkg.AllImports() {
381*333d2b36SAndroid Build Coastguard Worker				if !excludeDeps[dep] {
382*333d2b36SAndroid Build Coastguard Worker					mark(dep)
383*333d2b36SAndroid Build Coastguard Worker				}
384*333d2b36SAndroid Build Coastguard Worker			}
385*333d2b36SAndroid Build Coastguard Worker		}
386*333d2b36SAndroid Build Coastguard Worker	}
387*333d2b36SAndroid Build Coastguard Worker
388*333d2b36SAndroid Build Coastguard Worker	for _, pkgName := range limit {
389*333d2b36SAndroid Build Coastguard Worker		mark(pkgName)
390*333d2b36SAndroid Build Coastguard Worker	}
391*333d2b36SAndroid Build Coastguard Worker
392*333d2b36SAndroid Build Coastguard Worker	for _, pkg := range pkgs {
393*333d2b36SAndroid Build Coastguard Worker		if !pkg.ExportToAndroid || excludes[pkg.ImportPath] {
394*333d2b36SAndroid Build Coastguard Worker			continue
395*333d2b36SAndroid Build Coastguard Worker		}
396*333d2b36SAndroid Build Coastguard Worker		if len(pkg.BpSrcs(pkg.GoFiles)) == 0 && len(pkg.BpSrcs(pkg.TestGoFiles)) == 0 {
397*333d2b36SAndroid Build Coastguard Worker			continue
398*333d2b36SAndroid Build Coastguard Worker		}
399*333d2b36SAndroid Build Coastguard Worker		err := bpTemplate.Execute(buf, pkg)
400*333d2b36SAndroid Build Coastguard Worker		if err != nil {
401*333d2b36SAndroid Build Coastguard Worker			fmt.Fprintln(os.Stderr, "Error writing", pkg.Name, err)
402*333d2b36SAndroid Build Coastguard Worker			os.Exit(1)
403*333d2b36SAndroid Build Coastguard Worker		}
404*333d2b36SAndroid Build Coastguard Worker	}
405*333d2b36SAndroid Build Coastguard Worker
406*333d2b36SAndroid Build Coastguard Worker	out, err := bpfix.Reformat(buf.String())
407*333d2b36SAndroid Build Coastguard Worker	if err != nil {
408*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(os.Stderr, "Error formatting output", err)
409*333d2b36SAndroid Build Coastguard Worker		os.Exit(1)
410*333d2b36SAndroid Build Coastguard Worker	}
411*333d2b36SAndroid Build Coastguard Worker
412*333d2b36SAndroid Build Coastguard Worker	os.Stdout.WriteString(out)
413*333d2b36SAndroid Build Coastguard Worker}
414