summaryrefslogtreecommitdiff
path: root/src/pkg/go/build/build.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/go/build/build.go')
-rw-r--r--src/pkg/go/build/build.go144
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
}