func run()

in cmd/gobind/main.go [47:161]


func run() {
	var langs []string
	if *lang != "" {
		langs = strings.Split(*lang, ",")
	} else {
		langs = []string{"go", "java", "objc"}
	}

	// We need to give appropriate environment variables like CC or CXX so that the returned packages no longer have errors.
	// However, getting such environment variables is difficult or impossible so far.
	// Gomobile can obtain such environment variables in env.go, but this logic assumes some condiitons gobind doesn't assume.
	cfg := &packages.Config{
		Mode: packages.NeedName | packages.NeedFiles |
			packages.NeedImports | packages.NeedDeps |
			packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo,
		BuildFlags: []string{"-tags", strings.Join(strings.Split(*tags, ","), " ")},
	}

	// Call Load twice to warm the cache. There is a known issue that the result of Load
	// depends on build cache state. See golang/go#33687.
	packages.Load(cfg, flag.Args()...)

	allPkg, err := packages.Load(cfg, flag.Args()...)
	if err != nil {
		log.Fatal(err)
	}

	jrefs, err := importers.AnalyzePackages(allPkg, "Java/")
	if err != nil {
		log.Fatal(err)
	}
	orefs, err := importers.AnalyzePackages(allPkg, "ObjC/")
	if err != nil {
		log.Fatal(err)
	}
	var classes []*java.Class
	if len(jrefs.Refs) > 0 {
		jimp := &java.Importer{
			Bootclasspath: *bootclasspath,
			Classpath:     *classpath,
			JavaPkg:       *javaPkg,
		}
		classes, err = jimp.Import(jrefs)
		if err != nil {
			log.Fatal(err)
		}
	}
	var otypes []*objc.Named
	if len(orefs.Refs) > 0 {
		otypes, err = objc.Import(orefs)
		if err != nil {
			log.Fatal(err)
		}
	}

	if len(classes) > 0 || len(otypes) > 0 {
		srcDir := *outdir
		if srcDir == "" {
			srcDir, err = ioutil.TempDir(os.TempDir(), "gobind-")
			if err != nil {
				log.Fatal(err)
			}
			defer os.RemoveAll(srcDir)
		} else {
			srcDir, err = filepath.Abs(srcDir)
			if err != nil {
				log.Fatal(err)
			}
		}
		if len(classes) > 0 {
			if err := genJavaPackages(srcDir, classes, jrefs.Embedders); err != nil {
				log.Fatal(err)
			}
		}
		if len(otypes) > 0 {
			if err := genObjcPackages(srcDir, otypes, orefs.Embedders); err != nil {
				log.Fatal(err)
			}
		}

		// Add a new directory to GOPATH where the file for reverse bindings exist, and recreate allPkg.
		// It is because the current allPkg did not solve imports for reverse bindings.
		var gopath string
		if out, err := exec.Command("go", "env", "GOPATH").Output(); err != nil {
			log.Fatal(err)
		} else {
			gopath = string(bytes.TrimSpace(out))
		}
		if gopath != "" {
			gopath = string(filepath.ListSeparator) + gopath
		}
		gopath = srcDir + gopath
		cfg.Env = append(os.Environ(), "GOPATH="+gopath)
		allPkg, err = packages.Load(cfg, flag.Args()...)
		if err != nil {
			log.Fatal(err)
		}
	}

	typePkgs := make([]*types.Package, len(allPkg))
	astPkgs := make([][]*ast.File, len(allPkg))
	for i, pkg := range allPkg {
		// Ignore pkg.Errors. pkg.Errors can exist when Cgo is used, but this should not affect the result.
		// See the discussion at golang/go#36547.
		typePkgs[i] = pkg.Types
		astPkgs[i] = pkg.Syntax
	}
	for _, l := range langs {
		for i, pkg := range typePkgs {
			genPkg(l, pkg, astPkgs[i], typePkgs, classes, otypes)
		}
		// Generate the error package and support files
		genPkg(l, nil, nil, typePkgs, classes, otypes)
	}
}