4 // Copyright 2013 The Go Authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file.
8 // Command mkindex creates the file "pkgindex.go" containing an index of the Go
9 // standard library. The file is intended to be built as part of the imports
10 // package, so that the package may be used in environments where a GOROOT is
11 // not available (such as App Engine).
31 pkgIndex = make(map[string][]pkg)
32 exports = make(map[string]map[string]bool)
40 // Populate pkgIndex global from GOROOT.
41 for _, path := range ctx.SrcDirs() {
42 f, err := os.Open(path)
47 children, err := f.Readdir(-1)
53 for _, child := range children {
55 loadPkg(path, child.Name())
59 // Populate exports global.
60 for _, ps := range pkgIndex {
61 for _, p := range ps {
62 e := loadExports(p.dir)
69 // Construct source file.
71 fmt.Fprint(&buf, pkgIndexHead)
72 fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex)
73 fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports)
76 // Replace main.pkg type name with pkg.
77 src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1)
78 // Replace actual GOROOT with "/go".
79 src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1)
80 // Add some line wrapping.
81 src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1)
82 src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1)
85 src, err = format.Source(src)
90 // Write out source file.
91 err = ioutil.WriteFile("pkgindex.go", src, 0644)
97 const pkgIndexHead = `package imports
100 pkgIndexOnce.Do(func() {
101 pkgIndex.m = pkgIndexMaster
103 loadExports = func(dir string) map[string]bool {
104 return exportsMaster[dir]
110 importpath string // full pkg import path, e.g. "net/http"
111 dir string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
114 var fset = token.NewFileSet()
116 func loadPkg(root, importpath string) {
117 shortName := path.Base(importpath)
118 if shortName == "testdata" {
122 dir := filepath.Join(root, importpath)
123 pkgIndex[shortName] = append(pkgIndex[shortName], pkg{
124 importpath: importpath,
128 pkgDir, err := os.Open(dir)
132 children, err := pkgDir.Readdir(-1)
137 for _, child := range children {
142 if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
146 loadPkg(root, filepath.Join(importpath, name))
151 func loadExports(dir string) map[string]bool {
152 exports := make(map[string]bool)
153 buildPkg, err := build.ImportDir(dir, 0)
155 if strings.Contains(err.Error(), "no buildable Go source files in") {
158 log.Printf("could not import %q: %v", dir, err)
161 for _, file := range buildPkg.GoFiles {
162 f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
164 log.Printf("could not parse %q: %v", file, err)
167 for name := range f.Scope.Objects {
168 if ast.IsExported(name) {