diff options
Diffstat (limited to 'src/pkg/go/build/build.go')
-rw-r--r-- | src/pkg/go/build/build.go | 144 |
1 files changed, 121 insertions, 23 deletions
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go index 7a81d5030..16c3da458 100644 --- a/src/pkg/go/build/build.go +++ b/src/pkg/go/build/build.go @@ -33,6 +33,7 @@ type Context struct { GOPATH string // Go path CgoEnabled bool // whether cgo can be used BuildTags []string // additional tags to recognize in +build lines + InstallTag string // package install directory suffix UseAllFiles bool // use files regardless of +build lines, file names Compiler string // compiler to assume when computing target paths @@ -116,12 +117,27 @@ func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) { return f(root, dir) } - if p, err := filepath.EvalSymlinks(root); err == nil { - root = p + // Try using paths we received. + if rel, ok = hasSubdir(root, dir); ok { + return } - if p, err := filepath.EvalSymlinks(dir); err == nil { - dir = p + + // Try expanding symlinks and comparing + // expanded against unexpanded and + // expanded against expanded. + rootSym, _ := filepath.EvalSymlinks(root) + dirSym, _ := filepath.EvalSymlinks(dir) + + if rel, ok = hasSubdir(rootSym, dir); ok { + return + } + if rel, ok = hasSubdir(root, dirSym); ok { + return } + return hasSubdir(rootSym, dirSym) +} + +func hasSubdir(root, dir string) (rel string, ok bool) { const sep = string(filepath.Separator) root = filepath.Clean(root) if !strings.HasSuffix(root, sep) { @@ -180,6 +196,21 @@ func (ctxt *Context) gopath() []string { // Do not get confused by this common mistake. continue } + if strings.Contains(p, "~") && runtime.GOOS != "windows" { + // Path segments containing ~ on Unix are almost always + // users who have incorrectly quoted ~ while setting GOPATH, + // preventing it from expanding to $HOME. + // The situation is made more confusing by the fact that + // bash allows quoted ~ in $PATH (most shells do not). + // Do not get confused by this, and do not try to use the path. + // It does not exist, and printing errors about it confuses + // those users even more, because they think "sure ~ exists!". + // The go command diagnoses this situation and prints a + // useful error. + // On Windows, ~ is used in short names, such as c:\progra~1 + // for c:\program files. + continue + } all = append(all, p) } return all @@ -213,10 +244,16 @@ var Default Context = defaultContext() var cgoEnabled = map[string]bool{ "darwin/386": true, "darwin/amd64": true, - "linux/386": true, - "linux/amd64": true, "freebsd/386": true, "freebsd/amd64": true, + "linux/386": true, + "linux/amd64": true, + "linux/arm": true, + "netbsd/386": true, + "netbsd/amd64": true, + "netbsd/arm": true, + "openbsd/386": true, + "openbsd/amd64": true, "windows/386": true, "windows/amd64": true, } @@ -278,12 +315,15 @@ type Package struct { PkgObj string // installed .a file // Source files - GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) - CgoFiles []string // .go source files that import "C" - CFiles []string // .c source files - HFiles []string // .h source files - SFiles []string // .s source files - SysoFiles []string // .syso system object files to add to archive + GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string // .go source files that import "C" + IgnoredGoFiles []string // .go source files ignored for this build + CFiles []string // .c source files + HFiles []string // .h source files + SFiles []string // .s source files + SysoFiles []string // .syso system object files to add to archive + SwigFiles []string // .swig files + SwigCXXFiles []string // .swigcxx files // Cgo directives CgoPkgConfig []string // Cgo pkg-config directives @@ -346,6 +386,9 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa p := &Package{ ImportPath: path, } + if path == "" { + return p, fmt.Errorf("import %q: invalid import path", path) + } var pkga string var pkgerr error @@ -354,7 +397,11 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa dir, elem := pathpkg.Split(p.ImportPath) pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a" case "gc": - pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + p.ImportPath + ".a" + tag := "" + if ctxt.InstallTag != "" { + tag = "_" + ctxt.InstallTag + } + pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + tag + "/" + p.ImportPath + ".a" default: // Save error for end of function. pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler) @@ -410,6 +457,13 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa if strings.HasPrefix(path, "/") { return p, fmt.Errorf("import %q: cannot import absolute path", path) } + + // tried records the location of unsucsessful package lookups + var tried struct { + goroot string + gopath []string + } + // Determine directory from import path. if ctxt.GOROOT != "" { dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", path) @@ -421,6 +475,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa p.Root = ctxt.GOROOT goto Found } + tried.goroot = dir } for _, root := range ctxt.gopath() { dir := ctxt.joinPath(root, "src", path) @@ -431,8 +486,28 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa p.Root = root goto Found } + tried.gopath = append(tried.gopath, dir) + } + + // package was not found + var paths []string + if tried.goroot != "" { + paths = append(paths, fmt.Sprintf("\t%s (from $GOROOT)", tried.goroot)) + } else { + paths = append(paths, "\t($GOROOT not set)") } - return p, fmt.Errorf("import %q: cannot find package", path) + var i int + var format = "\t%s (from $GOPATH)" + for ; i < len(tried.gopath); i++ { + if i > 0 { + format = "\t%s" + } + paths = append(paths, fmt.Sprintf(format, tried.gopath[i])) + } + if i == 0 { + paths = append(paths, "\t($GOPATH not set)") + } + return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n")) } Found: @@ -476,17 +551,22 @@ Found: strings.HasPrefix(name, ".") { continue } - if !ctxt.UseAllFiles && !ctxt.goodOSArchFile(name) { - continue - } i := strings.LastIndex(name, ".") if i < 0 { i = len(name) } ext := name[i:] + + if !ctxt.UseAllFiles && !ctxt.goodOSArchFile(name) { + if ext == ".go" { + p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) + } + continue + } + switch ext { - case ".go", ".c", ".s", ".h", ".S": + case ".go", ".c", ".s", ".h", ".S", ".swig", ".swigcxx": // tentatively okay - read to make sure case ".syso": // binary objects to add to package archive @@ -504,7 +584,13 @@ Found: if err != nil { return p, err } - data, err := ioutil.ReadAll(f) + + var data []byte + if strings.HasSuffix(filename, ".go") { + data, err = readImports(f, false) + } else { + data, err = readComments(f) + } f.Close() if err != nil { return p, fmt.Errorf("read %s: %v", filename, err) @@ -512,6 +598,9 @@ Found: // Look for +build comments to accept or reject the file. if !ctxt.UseAllFiles && !ctxt.shouldBuild(data) { + if ext == ".go" { + p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) + } continue } @@ -529,6 +618,12 @@ Found: case ".S": Sfiles = append(Sfiles, name) continue + case ".swig": + p.SwigFiles = append(p.SwigFiles, name) + continue + case ".swigcxx": + p.SwigCXXFiles = append(p.SwigCXXFiles, name) + continue } pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments) @@ -536,8 +631,9 @@ Found: return p, err } - pkg := string(pf.Name.Name) + pkg := pf.Name.Name if pkg == "documentation" { + p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) continue } @@ -570,7 +666,7 @@ Found: if !ok { continue } - quoted := string(spec.Path.Value) + quoted := spec.Path.Value path, err := strconv.Unquote(quoted) if err != nil { log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted) @@ -678,7 +774,7 @@ func (ctxt *Context) shouldBuild(content []byte) bool { } line = bytes.TrimSpace(line) if len(line) == 0 { // Blank line - end = cap(content) - cap(line) // &line[0] - &content[0] + end = len(content) - len(p) continue } if !bytes.HasPrefix(line, slashslash) { // Not comment line @@ -872,6 +968,8 @@ func splitQuoted(s string) (r []string, err error) { // $GOARCH // cgo (if cgo is enabled) // !cgo (if cgo is disabled) +// ctxt.Compiler +// !ctxt.Compiler // tag (if tag is listed in ctxt.BuildTags) // !tag (if tag is not listed in ctxt.BuildTags) // a comma-separated list of any of these @@ -903,7 +1001,7 @@ func (ctxt *Context) match(name string) bool { if ctxt.CgoEnabled && name == "cgo" { return true } - if name == ctxt.GOOS || name == ctxt.GOARCH { + if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler { return true } |