diff options
| author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
|---|---|---|
| committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
| commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
| tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/go/build | |
| parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
| download | golang-upstream/1.4.tar.gz | |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/pkg/go/build')
| -rw-r--r-- | src/pkg/go/build/build.go | 1219 | ||||
| -rw-r--r-- | src/pkg/go/build/build_test.go | 186 | ||||
| -rw-r--r-- | src/pkg/go/build/deps_test.go | 442 | ||||
| -rw-r--r-- | src/pkg/go/build/doc.go | 137 | ||||
| -rw-r--r-- | src/pkg/go/build/read.go | 238 | ||||
| -rw-r--r-- | src/pkg/go/build/read_test.go | 226 | ||||
| -rw-r--r-- | src/pkg/go/build/syslist.go | 8 | ||||
| -rw-r--r-- | src/pkg/go/build/syslist_test.go | 62 | ||||
| -rw-r--r-- | src/pkg/go/build/testdata/other/file/file.go | 5 | ||||
| -rw-r--r-- | src/pkg/go/build/testdata/other/main.go | 11 |
10 files changed, 0 insertions, 2534 deletions
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go deleted file mode 100644 index 412abea3a..000000000 --- a/src/pkg/go/build/build.go +++ /dev/null @@ -1,1219 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "bytes" - "errors" - "fmt" - "go/ast" - "go/doc" - "go/parser" - "go/token" - "io" - "io/ioutil" - "log" - "os" - pathpkg "path" - "path/filepath" - "runtime" - "sort" - "strconv" - "strings" - "unicode" -) - -// A Context specifies the supporting context for a build. -type Context struct { - GOARCH string // target architecture - GOOS string // target operating system - GOROOT string // Go root - GOPATH string // Go path - CgoEnabled bool // whether cgo can be used - UseAllFiles bool // use files regardless of +build lines, file names - Compiler string // compiler to assume when computing target paths - - // The build and release tags specify build constraints - // that should be considered satisfied when processing +build lines. - // Clients creating a new context may customize BuildTags, which - // defaults to empty, but it is usually an error to customize ReleaseTags, - // which defaults to the list of Go releases the current release is compatible with. - // In addition to the BuildTags and ReleaseTags, build constraints - // consider the values of GOARCH and GOOS as satisfied tags. - BuildTags []string - ReleaseTags []string - - // The install suffix specifies a suffix to use in the name of the installation - // directory. By default it is empty, but custom builds that need to keep - // their outputs separate can set InstallSuffix to do so. For example, when - // using the race detector, the go command uses InstallSuffix = "race", so - // that on a Linux/386 system, packages are written to a directory named - // "linux_386_race" instead of the usual "linux_386". - InstallSuffix string - - // By default, Import uses the operating system's file system calls - // to read directories and files. To read from other sources, - // callers can set the following functions. They all have default - // behaviors that use the local file system, so clients need only set - // the functions whose behaviors they wish to change. - - // JoinPath joins the sequence of path fragments into a single path. - // If JoinPath is nil, Import uses filepath.Join. - JoinPath func(elem ...string) string - - // SplitPathList splits the path list into a slice of individual paths. - // If SplitPathList is nil, Import uses filepath.SplitList. - SplitPathList func(list string) []string - - // IsAbsPath reports whether path is an absolute path. - // If IsAbsPath is nil, Import uses filepath.IsAbs. - IsAbsPath func(path string) bool - - // IsDir reports whether the path names a directory. - // If IsDir is nil, Import calls os.Stat and uses the result's IsDir method. - IsDir func(path string) bool - - // HasSubdir reports whether dir is a subdirectory of - // (perhaps multiple levels below) root. - // If so, HasSubdir sets rel to a slash-separated path that - // can be joined to root to produce a path equivalent to dir. - // If HasSubdir is nil, Import uses an implementation built on - // filepath.EvalSymlinks. - HasSubdir func(root, dir string) (rel string, ok bool) - - // ReadDir returns a slice of os.FileInfo, sorted by Name, - // describing the content of the named directory. - // If ReadDir is nil, Import uses ioutil.ReadDir. - ReadDir func(dir string) (fi []os.FileInfo, err error) - - // OpenFile opens a file (not a directory) for reading. - // If OpenFile is nil, Import uses os.Open. - OpenFile func(path string) (r io.ReadCloser, err error) -} - -// joinPath calls ctxt.JoinPath (if not nil) or else filepath.Join. -func (ctxt *Context) joinPath(elem ...string) string { - if f := ctxt.JoinPath; f != nil { - return f(elem...) - } - return filepath.Join(elem...) -} - -// splitPathList calls ctxt.SplitPathList (if not nil) or else filepath.SplitList. -func (ctxt *Context) splitPathList(s string) []string { - if f := ctxt.SplitPathList; f != nil { - return f(s) - } - return filepath.SplitList(s) -} - -// isAbsPath calls ctxt.IsAbsSPath (if not nil) or else filepath.IsAbs. -func (ctxt *Context) isAbsPath(path string) bool { - if f := ctxt.IsAbsPath; f != nil { - return f(path) - } - return filepath.IsAbs(path) -} - -// isDir calls ctxt.IsDir (if not nil) or else uses os.Stat. -func (ctxt *Context) isDir(path string) bool { - if f := ctxt.IsDir; f != nil { - return f(path) - } - fi, err := os.Stat(path) - return err == nil && fi.IsDir() -} - -// hasSubdir calls ctxt.HasSubdir (if not nil) or else uses -// the local file system to answer the question. -func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) { - if f := ctxt.HasSubdir; f != nil { - return f(root, dir) - } - - // Try using paths we received. - if rel, ok = hasSubdir(root, dir); ok { - return - } - - // 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) { - root += sep - } - dir = filepath.Clean(dir) - if !strings.HasPrefix(dir, root) { - return "", false - } - return filepath.ToSlash(dir[len(root):]), true -} - -// readDir calls ctxt.ReadDir (if not nil) or else ioutil.ReadDir. -func (ctxt *Context) readDir(path string) ([]os.FileInfo, error) { - if f := ctxt.ReadDir; f != nil { - return f(path) - } - return ioutil.ReadDir(path) -} - -// openFile calls ctxt.OpenFile (if not nil) or else os.Open. -func (ctxt *Context) openFile(path string) (io.ReadCloser, error) { - if fn := ctxt.OpenFile; fn != nil { - return fn(path) - } - - f, err := os.Open(path) - if err != nil { - return nil, err // nil interface - } - return f, nil -} - -// isFile determines whether path is a file by trying to open it. -// It reuses openFile instead of adding another function to the -// list in Context. -func (ctxt *Context) isFile(path string) bool { - f, err := ctxt.openFile(path) - if err != nil { - return false - } - f.Close() - return true -} - -// gopath returns the list of Go path directories. -func (ctxt *Context) gopath() []string { - var all []string - for _, p := range ctxt.splitPathList(ctxt.GOPATH) { - if p == "" || p == ctxt.GOROOT { - // Empty paths are uninteresting. - // If the path is the GOROOT, ignore it. - // People sometimes set GOPATH=$GOROOT, which is useless - // but would cause us to find packages with import paths - // like "pkg/math". - // Do not get confused by this common mistake. - continue - } - if strings.HasPrefix(p, "~") { - // Path segments starting with ~ 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 -} - -// SrcDirs returns a list of package source root directories. -// It draws from the current Go root and Go path but omits directories -// that do not exist. -func (ctxt *Context) SrcDirs() []string { - var all []string - if ctxt.GOROOT != "" { - dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg") - if ctxt.isDir(dir) { - all = append(all, dir) - } - } - for _, p := range ctxt.gopath() { - dir := ctxt.joinPath(p, "src") - if ctxt.isDir(dir) { - all = append(all, dir) - } - } - return all -} - -// Default is the default Context for builds. -// It uses the GOARCH, GOOS, GOROOT, and GOPATH environment variables -// if set, or else the compiled code's GOARCH, GOOS, and GOROOT. -var Default Context = defaultContext() - -var cgoEnabled = map[string]bool{ - "darwin/386": true, - "darwin/amd64": true, - "dragonfly/386": true, - "dragonfly/amd64": true, - "freebsd/386": true, - "freebsd/amd64": true, - "freebsd/arm": 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, -} - -func defaultContext() Context { - var c Context - - c.GOARCH = envOr("GOARCH", runtime.GOARCH) - c.GOOS = envOr("GOOS", runtime.GOOS) - c.GOROOT = runtime.GOROOT() - c.GOPATH = envOr("GOPATH", "") - c.Compiler = runtime.Compiler - - // Each major Go release in the Go 1.x series should add a tag here. - // Old tags should not be removed. That is, the go1.x tag is present - // in all releases >= Go 1.x. Code that requires Go 1.x or later should - // say "+build go1.x", and code that should only be built before Go 1.x - // (perhaps it is the stub to use in that case) should say "+build !go1.x". - // - // When we reach Go 1.4 the line will read - // c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4"} - // and so on. - c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"} - - switch os.Getenv("CGO_ENABLED") { - case "1": - c.CgoEnabled = true - case "0": - c.CgoEnabled = false - default: - // cgo must be explicitly enabled for cross compilation builds - if runtime.GOARCH == c.GOARCH && runtime.GOOS == c.GOOS { - c.CgoEnabled = cgoEnabled[c.GOOS+"/"+c.GOARCH] - break - } - c.CgoEnabled = false - } - - return c -} - -func envOr(name, def string) string { - s := os.Getenv(name) - if s == "" { - return def - } - return s -} - -// An ImportMode controls the behavior of the Import method. -type ImportMode uint - -const ( - // If FindOnly is set, Import stops after locating the directory - // that should contain the sources for a package. It does not - // read any files in the directory. - FindOnly ImportMode = 1 << iota - - // If AllowBinary is set, Import can be satisfied by a compiled - // package object without corresponding sources. - AllowBinary -) - -// A Package describes the Go package found in a directory. -type Package struct { - Dir string // directory containing package sources - Name string // package name - Doc string // documentation synopsis - ImportPath string // import path of package ("" if unknown) - Root string // root of Go tree where this package lives - SrcRoot string // package source root directory ("" if unknown) - PkgRoot string // package install root directory ("" if unknown) - BinDir string // command install directory ("" if unknown) - Goroot bool // package found in Go root - PkgObj string // installed .a file - AllTags []string // tags that can influence file selection in this directory - ConflictDir string // this directory shadows Dir in $GOPATH - - // Source files - 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 - CXXFiles []string // .cc, .cpp and .cxx source files - MFiles []string // .m (Objective-C) source files - HFiles []string // .h, .hh, .hpp and .hxx source files - SFiles []string // .s source files - SwigFiles []string // .swig files - SwigCXXFiles []string // .swigcxx files - SysoFiles []string // .syso system object files to add to archive - - // Cgo directives - CgoCFLAGS []string // Cgo CFLAGS directives - CgoCPPFLAGS []string // Cgo CPPFLAGS directives - CgoCXXFLAGS []string // Cgo CXXFLAGS directives - CgoLDFLAGS []string // Cgo LDFLAGS directives - CgoPkgConfig []string // Cgo pkg-config directives - - // Dependency information - Imports []string // imports from GoFiles, CgoFiles - ImportPos map[string][]token.Position // line information for Imports - - // Test information - TestGoFiles []string // _test.go files in package - TestImports []string // imports from TestGoFiles - TestImportPos map[string][]token.Position // line information for TestImports - XTestGoFiles []string // _test.go files outside package - XTestImports []string // imports from XTestGoFiles - XTestImportPos map[string][]token.Position // line information for XTestImports -} - -// IsCommand reports whether the package is considered a -// command to be installed (not just a library). -// Packages named "main" are treated as commands. -func (p *Package) IsCommand() bool { - return p.Name == "main" -} - -// ImportDir is like Import but processes the Go package found in -// the named directory. -func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) { - return ctxt.Import(".", dir, mode) -} - -// NoGoError is the error used by Import to describe a directory -// containing no buildable Go source files. (It may still contain -// test files, files hidden by build tags, and so on.) -type NoGoError struct { - Dir string -} - -func (e *NoGoError) Error() string { - return "no buildable Go source files in " + e.Dir -} - -func nameExt(name string) string { - i := strings.LastIndex(name, ".") - if i < 0 { - return "" - } - return name[i:] -} - -// Import returns details about the Go package named by the import path, -// interpreting local import paths relative to the srcDir directory. -// If the path is a local import path naming a package that can be imported -// using a standard import path, the returned package will set p.ImportPath -// to that path. -// -// In the directory containing the package, .go, .c, .h, and .s files are -// considered part of the package except for: -// -// - .go files in package documentation -// - files starting with _ or . (likely editor temporary files) -// - files with build constraints not satisfied by the context -// -// If an error occurs, Import returns a non-nil error and a non-nil -// *Package containing partial information. -// -func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) { - p := &Package{ - ImportPath: path, - } - if path == "" { - return p, fmt.Errorf("import %q: invalid import path", path) - } - - var pkga string - var pkgerr error - switch ctxt.Compiler { - case "gccgo": - dir, elem := pathpkg.Split(p.ImportPath) - pkga = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + dir + "lib" + elem + ".a" - case "gc": - suffix := "" - if ctxt.InstallSuffix != "" { - suffix = "_" + ctxt.InstallSuffix - } - pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix + "/" + p.ImportPath + ".a" - default: - // Save error for end of function. - pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler) - } - - binaryOnly := false - if IsLocalImport(path) { - pkga = "" // local imports have no installed path - if srcDir == "" { - return p, fmt.Errorf("import %q: import relative to unknown directory", path) - } - if !ctxt.isAbsPath(path) { - p.Dir = ctxt.joinPath(srcDir, path) - } - // Determine canonical import path, if any. - if ctxt.GOROOT != "" { - root := ctxt.joinPath(ctxt.GOROOT, "src", "pkg") - if sub, ok := ctxt.hasSubdir(root, p.Dir); ok { - p.Goroot = true - p.ImportPath = sub - p.Root = ctxt.GOROOT - goto Found - } - } - all := ctxt.gopath() - for i, root := range all { - rootsrc := ctxt.joinPath(root, "src") - if sub, ok := ctxt.hasSubdir(rootsrc, p.Dir); ok { - // We found a potential import path for dir, - // but check that using it wouldn't find something - // else first. - if ctxt.GOROOT != "" { - if dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", sub); ctxt.isDir(dir) { - p.ConflictDir = dir - goto Found - } - } - for _, earlyRoot := range all[:i] { - if dir := ctxt.joinPath(earlyRoot, "src", sub); ctxt.isDir(dir) { - p.ConflictDir = dir - goto Found - } - } - - // sub would not name some other directory instead of this one. - // Record it. - p.ImportPath = sub - p.Root = root - goto Found - } - } - // It's okay that we didn't find a root containing dir. - // Keep going with the information we have. - } else { - if strings.HasPrefix(path, "/") { - return p, fmt.Errorf("import %q: cannot import absolute path", path) - } - - // tried records the location of unsuccessful 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) - isDir := ctxt.isDir(dir) - binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga)) - if isDir || binaryOnly { - p.Dir = dir - p.Goroot = true - p.Root = ctxt.GOROOT - goto Found - } - tried.goroot = dir - } - for _, root := range ctxt.gopath() { - dir := ctxt.joinPath(root, "src", path) - isDir := ctxt.isDir(dir) - binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(root, pkga)) - if isDir || binaryOnly { - p.Dir = dir - 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)") - } - 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: - if p.Root != "" { - if p.Goroot { - p.SrcRoot = ctxt.joinPath(p.Root, "src", "pkg") - } else { - p.SrcRoot = ctxt.joinPath(p.Root, "src") - } - p.PkgRoot = ctxt.joinPath(p.Root, "pkg") - p.BinDir = ctxt.joinPath(p.Root, "bin") - if pkga != "" { - p.PkgObj = ctxt.joinPath(p.Root, pkga) - } - } - - if mode&FindOnly != 0 { - return p, pkgerr - } - if binaryOnly && (mode&AllowBinary) != 0 { - return p, pkgerr - } - - dirs, err := ctxt.readDir(p.Dir) - if err != nil { - return p, err - } - - var Sfiles []string // files with ".S" (capital S) - var firstFile string - imported := make(map[string][]token.Position) - testImported := make(map[string][]token.Position) - xTestImported := make(map[string][]token.Position) - allTags := make(map[string]bool) - fset := token.NewFileSet() - for _, d := range dirs { - if d.IsDir() { - continue - } - - name := d.Name() - ext := nameExt(name) - - match, data, filename, err := ctxt.matchFile(p.Dir, name, true, allTags) - if err != nil { - return p, err - } - if !match { - if ext == ".go" { - p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) - } - continue - } - - // Going to save the file. For non-Go files, can stop here. - switch ext { - case ".c": - p.CFiles = append(p.CFiles, name) - continue - case ".cc", ".cpp", ".cxx": - p.CXXFiles = append(p.CXXFiles, name) - continue - case ".m": - p.MFiles = append(p.MFiles, name) - continue - case ".h", ".hh", ".hpp", ".hxx": - p.HFiles = append(p.HFiles, name) - continue - case ".s": - p.SFiles = append(p.SFiles, name) - continue - 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 - case ".syso": - // binary objects to add to package archive - // Likely of the form foo_windows.syso, but - // the name was vetted above with goodOSArchFile. - p.SysoFiles = append(p.SysoFiles, name) - continue - } - - pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments) - if err != nil { - return p, err - } - - pkg := pf.Name.Name - if pkg == "documentation" { - p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) - continue - } - - isTest := strings.HasSuffix(name, "_test.go") - isXTest := false - if isTest && strings.HasSuffix(pkg, "_test") { - isXTest = true - pkg = pkg[:len(pkg)-len("_test")] - } - - if p.Name == "" { - p.Name = pkg - firstFile = name - } else if pkg != p.Name { - return p, fmt.Errorf("found packages %s (%s) and %s (%s) in %s", p.Name, firstFile, pkg, name, p.Dir) - } - if pf.Doc != nil && p.Doc == "" { - p.Doc = doc.Synopsis(pf.Doc.Text()) - } - - // Record imports and information about cgo. - isCgo := false - for _, decl := range pf.Decls { - d, ok := decl.(*ast.GenDecl) - if !ok { - continue - } - for _, dspec := range d.Specs { - spec, ok := dspec.(*ast.ImportSpec) - if !ok { - continue - } - quoted := spec.Path.Value - path, err := strconv.Unquote(quoted) - if err != nil { - log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted) - } - if isXTest { - xTestImported[path] = append(xTestImported[path], fset.Position(spec.Pos())) - } else if isTest { - testImported[path] = append(testImported[path], fset.Position(spec.Pos())) - } else { - imported[path] = append(imported[path], fset.Position(spec.Pos())) - } - if path == "C" { - if isTest { - return p, fmt.Errorf("use of cgo in test %s not supported", filename) - } - cg := spec.Doc - if cg == nil && len(d.Specs) == 1 { - cg = d.Doc - } - if cg != nil { - if err := ctxt.saveCgo(filename, p, cg); err != nil { - return p, err - } - } - isCgo = true - } - } - } - if isCgo { - allTags["cgo"] = true - if ctxt.CgoEnabled { - p.CgoFiles = append(p.CgoFiles, name) - } else { - p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) - } - } else if isXTest { - p.XTestGoFiles = append(p.XTestGoFiles, name) - } else if isTest { - p.TestGoFiles = append(p.TestGoFiles, name) - } else { - p.GoFiles = append(p.GoFiles, name) - } - } - if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 { - return p, &NoGoError{p.Dir} - } - - for tag := range allTags { - p.AllTags = append(p.AllTags, tag) - } - sort.Strings(p.AllTags) - - p.Imports, p.ImportPos = cleanImports(imported) - p.TestImports, p.TestImportPos = cleanImports(testImported) - p.XTestImports, p.XTestImportPos = cleanImports(xTestImported) - - // add the .S files only if we are using cgo - // (which means gcc will compile them). - // The standard assemblers expect .s files. - if len(p.CgoFiles) > 0 { - p.SFiles = append(p.SFiles, Sfiles...) - sort.Strings(p.SFiles) - } - - return p, pkgerr -} - -// MatchFile reports whether the file with the given name in the given directory -// matches the context and would be included in a Package created by ImportDir -// of that directory. -// -// MatchFile considers the name of the file and may use ctxt.OpenFile to -// read some or all of the file's content. -func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) { - match, _, _, err = ctxt.matchFile(dir, name, false, nil) - return -} - -// matchFile determines whether the file with the given name in the given directory -// should be included in the package being constructed. -// It returns the data read from the file. -// If returnImports is true and name denotes a Go program, matchFile reads -// until the end of the imports (and returns that data) even though it only -// considers text until the first non-comment. -// If allTags is non-nil, matchFile records any encountered build tag -// by setting allTags[tag] = true. -func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map[string]bool) (match bool, data []byte, filename string, err error) { - if strings.HasPrefix(name, "_") || - strings.HasPrefix(name, ".") { - return - } - - i := strings.LastIndex(name, ".") - if i < 0 { - i = len(name) - } - ext := name[i:] - - if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles { - return - } - - switch ext { - case ".go", ".c", ".cc", ".cxx", ".cpp", ".m", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx": - // tentatively okay - read to make sure - case ".syso": - // binary, no reading - match = true - return - default: - // skip - return - } - - filename = ctxt.joinPath(dir, name) - f, err := ctxt.openFile(filename) - if err != nil { - return - } - - if strings.HasSuffix(filename, ".go") { - data, err = readImports(f, false) - } else { - data, err = readComments(f) - } - f.Close() - if err != nil { - err = fmt.Errorf("read %s: %v", filename, err) - return - } - - // Look for +build comments to accept or reject the file. - if !ctxt.shouldBuild(data, allTags) && !ctxt.UseAllFiles { - return - } - - match = true - return -} - -func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) { - all := make([]string, 0, len(m)) - for path := range m { - all = append(all, path) - } - sort.Strings(all) - return all, m -} - -// Import is shorthand for Default.Import. -func Import(path, srcDir string, mode ImportMode) (*Package, error) { - return Default.Import(path, srcDir, mode) -} - -// ImportDir is shorthand for Default.ImportDir. -func ImportDir(dir string, mode ImportMode) (*Package, error) { - return Default.ImportDir(dir, mode) -} - -var slashslash = []byte("//") - -// shouldBuild reports whether it is okay to use this file, -// The rule is that in the file's leading run of // comments -// and blank lines, which must be followed by a blank line -// (to avoid including a Go package clause doc comment), -// lines beginning with '// +build' are taken as build directives. -// -// The file is accepted only if each such line lists something -// matching the file. For example: -// -// // +build windows linux -// -// marks the file as applicable only on Windows and Linux. -// -func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) bool { - // Pass 1. Identify leading run of // comments and blank lines, - // which must be followed by a blank line. - end := 0 - p := content - for len(p) > 0 { - line := p - if i := bytes.IndexByte(line, '\n'); i >= 0 { - line, p = line[:i], p[i+1:] - } else { - p = p[len(p):] - } - line = bytes.TrimSpace(line) - if len(line) == 0 { // Blank line - end = len(content) - len(p) - continue - } - if !bytes.HasPrefix(line, slashslash) { // Not comment line - break - } - } - content = content[:end] - - // Pass 2. Process each line in the run. - p = content - allok := true - for len(p) > 0 { - line := p - if i := bytes.IndexByte(line, '\n'); i >= 0 { - line, p = line[:i], p[i+1:] - } else { - p = p[len(p):] - } - line = bytes.TrimSpace(line) - if bytes.HasPrefix(line, slashslash) { - line = bytes.TrimSpace(line[len(slashslash):]) - if len(line) > 0 && line[0] == '+' { - // Looks like a comment +line. - f := strings.Fields(string(line)) - if f[0] == "+build" { - ok := false - for _, tok := range f[1:] { - if ctxt.match(tok, allTags) { - ok = true - } - } - if !ok { - allok = false - } - } - } - } - } - - return allok -} - -// saveCgo saves the information from the #cgo lines in the import "C" comment. -// These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives -// that affect the way cgo's C code is built. -// -// TODO(rsc): This duplicates code in cgo. -// Once the dust settles, remove this code from cgo. -func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) error { - text := cg.Text() - for _, line := range strings.Split(text, "\n") { - orig := line - - // Line is - // #cgo [GOOS/GOARCH...] LDFLAGS: stuff - // - line = strings.TrimSpace(line) - if len(line) < 5 || line[:4] != "#cgo" || (line[4] != ' ' && line[4] != '\t') { - continue - } - - // Split at colon. - line = strings.TrimSpace(line[4:]) - i := strings.Index(line, ":") - if i < 0 { - return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) - } - line, argstr := line[:i], line[i+1:] - - // Parse GOOS/GOARCH stuff. - f := strings.Fields(line) - if len(f) < 1 { - return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) - } - - cond, verb := f[:len(f)-1], f[len(f)-1] - if len(cond) > 0 { - ok := false - for _, c := range cond { - if ctxt.match(c, nil) { - ok = true - break - } - } - if !ok { - continue - } - } - - args, err := splitQuoted(argstr) - if err != nil { - return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) - } - for _, arg := range args { - if !safeCgoName(arg) { - return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg) - } - } - - switch verb { - case "CFLAGS": - di.CgoCFLAGS = append(di.CgoCFLAGS, args...) - case "CPPFLAGS": - di.CgoCPPFLAGS = append(di.CgoCPPFLAGS, args...) - case "CXXFLAGS": - di.CgoCXXFLAGS = append(di.CgoCXXFLAGS, args...) - case "LDFLAGS": - di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...) - case "pkg-config": - di.CgoPkgConfig = append(di.CgoPkgConfig, args...) - default: - return fmt.Errorf("%s: invalid #cgo verb: %s", filename, orig) - } - } - return nil -} - -// NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN. -// We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay. -// See golang.org/issue/6038. -var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$") - -func safeCgoName(s string) bool { - if s == "" { - return false - } - for i := 0; i < len(s); i++ { - if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 { - return false - } - } - return true -} - -// splitQuoted splits the string s around each instance of one or more consecutive -// white space characters while taking into account quotes and escaping, and -// returns an array of substrings of s or an empty list if s contains only white space. -// Single quotes and double quotes are recognized to prevent splitting within the -// quoted region, and are removed from the resulting substrings. If a quote in s -// isn't closed err will be set and r will have the unclosed argument as the -// last element. The backslash is used for escaping. -// -// For example, the following string: -// -// a b:"c d" 'e''f' "g\"" -// -// Would be parsed as: -// -// []string{"a", "b:c d", "ef", `g"`} -// -func splitQuoted(s string) (r []string, err error) { - var args []string - arg := make([]rune, len(s)) - escaped := false - quoted := false - quote := '\x00' - i := 0 - for _, rune := range s { - switch { - case escaped: - escaped = false - case rune == '\\': - escaped = true - continue - case quote != '\x00': - if rune == quote { - quote = '\x00' - continue - } - case rune == '"' || rune == '\'': - quoted = true - quote = rune - continue - case unicode.IsSpace(rune): - if quoted || i > 0 { - quoted = false - args = append(args, string(arg[:i])) - i = 0 - } - continue - } - arg[i] = rune - i++ - } - if quoted || i > 0 { - args = append(args, string(arg[:i])) - } - if quote != 0 { - err = errors.New("unclosed quote") - } else if escaped { - err = errors.New("unfinished escaping") - } - return args, err -} - -// match returns true if the name is one of: -// -// $GOOS -// $GOARCH -// cgo (if cgo is enabled) -// !cgo (if cgo is disabled) -// ctxt.Compiler -// !ctxt.Compiler -// tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags) -// !tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags) -// a comma-separated list of any of these -// -func (ctxt *Context) match(name string, allTags map[string]bool) bool { - if name == "" { - if allTags != nil { - allTags[name] = true - } - return false - } - if i := strings.Index(name, ","); i >= 0 { - // comma-separated list - ok1 := ctxt.match(name[:i], allTags) - ok2 := ctxt.match(name[i+1:], allTags) - return ok1 && ok2 - } - if strings.HasPrefix(name, "!!") { // bad syntax, reject always - return false - } - if strings.HasPrefix(name, "!") { // negation - return len(name) > 1 && !ctxt.match(name[1:], allTags) - } - - if allTags != nil { - allTags[name] = true - } - - // Tags must be letters, digits, underscores or dots. - // Unlike in Go identifiers, all digits are fine (e.g., "386"). - for _, c := range name { - if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { - return false - } - } - - // special tags - if ctxt.CgoEnabled && name == "cgo" { - return true - } - if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler { - return true - } - - // other tags - for _, tag := range ctxt.BuildTags { - if tag == name { - return true - } - } - for _, tag := range ctxt.ReleaseTags { - if tag == name { - return true - } - } - - return false -} - -// goodOSArchFile returns false if the name contains a $GOOS or $GOARCH -// suffix which does not match the current system. -// The recognized name formats are: -// -// name_$(GOOS).* -// name_$(GOARCH).* -// name_$(GOOS)_$(GOARCH).* -// name_$(GOOS)_test.* -// name_$(GOARCH)_test.* -// name_$(GOOS)_$(GOARCH)_test.* -// -func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool { - if dot := strings.Index(name, "."); dot != -1 { - name = name[:dot] - } - l := strings.Split(name, "_") - if n := len(l); n > 0 && l[n-1] == "test" { - l = l[:n-1] - } - n := len(l) - if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] { - if allTags != nil { - allTags[l[n-2]] = true - allTags[l[n-1]] = true - } - return l[n-2] == ctxt.GOOS && l[n-1] == ctxt.GOARCH - } - if n >= 1 && knownOS[l[n-1]] { - if allTags != nil { - allTags[l[n-1]] = true - } - return l[n-1] == ctxt.GOOS - } - if n >= 1 && knownArch[l[n-1]] { - if allTags != nil { - allTags[l[n-1]] = true - } - return l[n-1] == ctxt.GOARCH - } - return true -} - -var knownOS = make(map[string]bool) -var knownArch = make(map[string]bool) - -func init() { - for _, v := range strings.Fields(goosList) { - knownOS[v] = true - } - for _, v := range strings.Fields(goarchList) { - knownArch[v] = true - } -} - -// ToolDir is the directory containing build tools. -var ToolDir = filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) - -// IsLocalImport reports whether the import path is -// a local import path, like ".", "..", "./foo", or "../foo". -func IsLocalImport(path string) bool { - return path == "." || path == ".." || - strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../") -} - -// ArchChar returns the architecture character for the given goarch. -// For example, ArchChar("amd64") returns "6". -func ArchChar(goarch string) (string, error) { - switch goarch { - case "386": - return "8", nil - case "amd64", "amd64p32": - return "6", nil - case "arm": - return "5", nil - } - return "", errors.New("unsupported GOARCH " + goarch) -} diff --git a/src/pkg/go/build/build_test.go b/src/pkg/go/build/build_test.go deleted file mode 100644 index fca8d4bdb..000000000 --- a/src/pkg/go/build/build_test.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "io" - "os" - "path/filepath" - "reflect" - "runtime" - "strings" - "testing" -) - -func TestMatch(t *testing.T) { - ctxt := Default - what := "default" - match := func(tag string, want map[string]bool) { - m := make(map[string]bool) - if !ctxt.match(tag, m) { - t.Errorf("%s context should match %s, does not", what, tag) - } - if !reflect.DeepEqual(m, want) { - t.Errorf("%s tags = %v, want %v", tag, m, want) - } - } - nomatch := func(tag string, want map[string]bool) { - m := make(map[string]bool) - if ctxt.match(tag, m) { - t.Errorf("%s context should NOT match %s, does", what, tag) - } - if !reflect.DeepEqual(m, want) { - t.Errorf("%s tags = %v, want %v", tag, m, want) - } - } - - match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true}) - match(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true}) - nomatch(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true}) - - what = "modified" - ctxt.BuildTags = []string{"foo"} - match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true}) - match(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true}) - nomatch(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true}) - match(runtime.GOOS+","+runtime.GOARCH+",!bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true}) - nomatch(runtime.GOOS+","+runtime.GOARCH+",bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true}) - nomatch("!", map[string]bool{}) -} - -func TestDotSlashImport(t *testing.T) { - p, err := ImportDir("testdata/other", 0) - if err != nil { - t.Fatal(err) - } - if len(p.Imports) != 1 || p.Imports[0] != "./file" { - t.Fatalf("testdata/other: Imports=%v, want [./file]", p.Imports) - } - - p1, err := Import("./file", "testdata/other", 0) - if err != nil { - t.Fatal(err) - } - if p1.Name != "file" { - t.Fatalf("./file: Name=%q, want %q", p1.Name, "file") - } - dir := filepath.Clean("testdata/other/file") // Clean to use \ on Windows - if p1.Dir != dir { - t.Fatalf("./file: Dir=%q, want %q", p1.Name, dir) - } -} - -func TestEmptyImport(t *testing.T) { - p, err := Import("", Default.GOROOT, FindOnly) - if err == nil { - t.Fatal(`Import("") returned nil error.`) - } - if p == nil { - t.Fatal(`Import("") returned nil package.`) - } - if p.ImportPath != "" { - t.Fatalf("ImportPath=%q, want %q.", p.ImportPath, "") - } -} - -func TestLocalDirectory(t *testing.T) { - cwd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - - p, err := ImportDir(cwd, 0) - if err != nil { - t.Fatal(err) - } - if p.ImportPath != "go/build" { - t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "go/build") - } -} - -func TestShouldBuild(t *testing.T) { - const file1 = "// +build tag1\n\n" + - "package main\n" - want1 := map[string]bool{"tag1": true} - - const file2 = "// +build cgo\n\n" + - "// This package implements parsing of tags like\n" + - "// +build tag1\n" + - "package build" - want2 := map[string]bool{"cgo": true} - - const file3 = "// Copyright The Go Authors.\n\n" + - "package build\n\n" + - "// shouldBuild checks tags given by lines of the form\n" + - "// +build tag\n" + - "func shouldBuild(content []byte)\n" - want3 := map[string]bool{} - - ctx := &Context{BuildTags: []string{"tag1"}} - m := map[string]bool{} - if !ctx.shouldBuild([]byte(file1), m) { - t.Errorf("shouldBuild(file1) = false, want true") - } - if !reflect.DeepEqual(m, want1) { - t.Errorf("shoudBuild(file1) tags = %v, want %v", m, want1) - } - - m = map[string]bool{} - if ctx.shouldBuild([]byte(file2), m) { - t.Errorf("shouldBuild(file2) = true, want fakse") - } - if !reflect.DeepEqual(m, want2) { - t.Errorf("shoudBuild(file2) tags = %v, want %v", m, want2) - } - - m = map[string]bool{} - ctx = &Context{BuildTags: nil} - if !ctx.shouldBuild([]byte(file3), m) { - t.Errorf("shouldBuild(file3) = false, want true") - } - if !reflect.DeepEqual(m, want3) { - t.Errorf("shoudBuild(file3) tags = %v, want %v", m, want3) - } -} - -type readNopCloser struct { - io.Reader -} - -func (r readNopCloser) Close() error { - return nil -} - -var matchFileTests = []struct { - name string - data string - match bool -}{ - {"foo_arm.go", "", true}, - {"foo1_arm.go", "// +build linux\n\npackage main\n", false}, - {"foo_darwin.go", "", false}, - {"foo.go", "", true}, - {"foo1.go", "// +build linux\n\npackage main\n", false}, - {"foo.badsuffix", "", false}, -} - -func TestMatchFile(t *testing.T) { - for _, tt := range matchFileTests { - ctxt := Context{GOARCH: "arm", GOOS: "plan9"} - ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) { - if path != "x+"+tt.name { - t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name) - } - return &readNopCloser{strings.NewReader(tt.data)}, nil - } - ctxt.JoinPath = func(elem ...string) string { - return strings.Join(elem, "+") - } - match, err := ctxt.MatchFile("x", tt.name) - if match != tt.match || err != nil { - t.Fatalf("MatchFile(%q) = %v, %v, want %v, nil", tt.name, match, err, tt.match) - } - } -} diff --git a/src/pkg/go/build/deps_test.go b/src/pkg/go/build/deps_test.go deleted file mode 100644 index 7421e144f..000000000 --- a/src/pkg/go/build/deps_test.go +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file exercises the import parser but also checks that -// some low-level packages do not have new dependencies added. - -package build - -import ( - "runtime" - "sort" - "testing" -) - -// pkgDeps defines the expected dependencies between packages in -// the Go source tree. It is a statement of policy. -// Changes should not be made to this map without prior discussion. -// -// The map contains two kinds of entries: -// 1) Lower-case keys are standard import paths and list the -// allowed imports in that package. -// 2) Upper-case keys define aliases for package sets, which can then -// be used as dependencies by other rules. -// -// DO NOT CHANGE THIS DATA TO FIX BUILDS. -// -var pkgDeps = map[string][]string{ - // L0 is the lowest level, core, nearly unavoidable packages. - "errors": {}, - "io": {"errors", "sync"}, - "runtime": {"unsafe"}, - "sync": {"runtime", "sync/atomic", "unsafe"}, - "sync/atomic": {"unsafe"}, - "unsafe": {}, - - "L0": { - "errors", - "io", - "runtime", - "sync", - "sync/atomic", - "unsafe", - }, - - // L1 adds simple functions and strings processing, - // but not Unicode tables. - "math": {"unsafe"}, - "math/cmplx": {"math"}, - "math/rand": {"L0", "math"}, - "sort": {}, - "strconv": {"L0", "unicode/utf8", "math"}, - "unicode/utf16": {}, - "unicode/utf8": {}, - - "L1": { - "L0", - "math", - "math/cmplx", - "math/rand", - "sort", - "strconv", - "unicode/utf16", - "unicode/utf8", - }, - - // L2 adds Unicode and strings processing. - "bufio": {"L0", "unicode/utf8", "bytes"}, - "bytes": {"L0", "unicode", "unicode/utf8"}, - "path": {"L0", "unicode/utf8", "strings"}, - "strings": {"L0", "unicode", "unicode/utf8"}, - "unicode": {}, - - "L2": { - "L1", - "bufio", - "bytes", - "path", - "strings", - "unicode", - }, - - // L3 adds reflection and some basic utility packages - // and interface definitions, but nothing that makes - // system calls. - "crypto": {"L2", "hash"}, // interfaces - "crypto/cipher": {"L2", "crypto/subtle"}, // interfaces - "crypto/subtle": {}, - "encoding/base32": {"L2"}, - "encoding/base64": {"L2"}, - "encoding/binary": {"L2", "reflect"}, - "hash": {"L2"}, // interfaces - "hash/adler32": {"L2", "hash"}, - "hash/crc32": {"L2", "hash"}, - "hash/crc64": {"L2", "hash"}, - "hash/fnv": {"L2", "hash"}, - "image": {"L2", "image/color"}, // interfaces - "image/color": {"L2"}, // interfaces - "image/color/palette": {"L2", "image/color"}, - "reflect": {"L2"}, - - "L3": { - "L2", - "crypto", - "crypto/cipher", - "crypto/subtle", - "encoding/base32", - "encoding/base64", - "encoding/binary", - "hash", - "hash/adler32", - "hash/crc32", - "hash/crc64", - "hash/fnv", - "image", - "image/color", - "image/color/palette", - "reflect", - }, - - // End of linear dependency definitions. - - // Operating system access. - "syscall": {"L0", "unicode/utf16"}, - "time": {"L0", "syscall"}, - "os": {"L1", "os", "syscall", "time"}, - "path/filepath": {"L2", "os", "syscall"}, - "io/ioutil": {"L2", "os", "path/filepath", "time"}, - "os/exec": {"L2", "os", "path/filepath", "syscall"}, - "os/signal": {"L2", "os", "syscall"}, - - // OS enables basic operating system functionality, - // but not direct use of package syscall, nor os/signal. - "OS": { - "io/ioutil", - "os", - "os/exec", - "path/filepath", - "time", - }, - - // Formatted I/O: few dependencies (L1) but we must add reflect. - "fmt": {"L1", "os", "reflect"}, - "log": {"L1", "os", "fmt", "time"}, - - // Packages used by testing must be low-level (L2+fmt). - "regexp": {"L2", "regexp/syntax"}, - "regexp/syntax": {"L2"}, - "runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"}, - "runtime/pprof": {"L2", "fmt", "text/tabwriter"}, - "text/tabwriter": {"L2"}, - - "testing": {"L2", "flag", "fmt", "os", "runtime/pprof", "time"}, - "testing/iotest": {"L2", "log"}, - "testing/quick": {"L2", "flag", "fmt", "reflect"}, - - // L4 is defined as L3+fmt+log+time, because in general once - // you're using L3 packages, use of fmt, log, or time is not a big deal. - "L4": { - "L3", - "fmt", - "log", - "time", - }, - - // Go parser. - "go/ast": {"L4", "OS", "go/scanner", "go/token"}, - "go/doc": {"L4", "go/ast", "go/token", "regexp", "text/template"}, - "go/parser": {"L4", "OS", "go/ast", "go/scanner", "go/token"}, - "go/printer": {"L4", "OS", "go/ast", "go/scanner", "go/token", "text/tabwriter"}, - "go/scanner": {"L4", "OS", "go/token"}, - "go/token": {"L4"}, - - "GOPARSER": { - "go/ast", - "go/doc", - "go/parser", - "go/printer", - "go/scanner", - "go/token", - }, - - // One of a kind. - "archive/tar": {"L4", "OS", "syscall"}, - "archive/zip": {"L4", "OS", "compress/flate"}, - "compress/bzip2": {"L4"}, - "compress/flate": {"L4"}, - "compress/gzip": {"L4", "compress/flate"}, - "compress/lzw": {"L4"}, - "compress/zlib": {"L4", "compress/flate"}, - "database/sql": {"L4", "container/list", "database/sql/driver"}, - "database/sql/driver": {"L4", "time"}, - "debug/dwarf": {"L4"}, - "debug/elf": {"L4", "OS", "debug/dwarf"}, - "debug/gosym": {"L4"}, - "debug/macho": {"L4", "OS", "debug/dwarf"}, - "debug/pe": {"L4", "OS", "debug/dwarf"}, - "encoding": {"L4"}, - "encoding/ascii85": {"L4"}, - "encoding/asn1": {"L4", "math/big"}, - "encoding/csv": {"L4"}, - "encoding/gob": {"L4", "OS", "encoding"}, - "encoding/hex": {"L4"}, - "encoding/json": {"L4", "encoding"}, - "encoding/pem": {"L4"}, - "encoding/xml": {"L4", "encoding"}, - "flag": {"L4", "OS"}, - "go/build": {"L4", "OS", "GOPARSER"}, - "html": {"L4"}, - "image/draw": {"L4"}, - "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"}, - "image/jpeg": {"L4"}, - "image/png": {"L4", "compress/zlib"}, - "index/suffixarray": {"L4", "regexp"}, - "math/big": {"L4"}, - "mime": {"L4", "OS", "syscall"}, - "net/url": {"L4"}, - "text/scanner": {"L4", "OS"}, - "text/template/parse": {"L4"}, - - "html/template": { - "L4", "OS", "encoding/json", "html", "text/template", - "text/template/parse", - }, - "text/template": { - "L4", "OS", "net/url", "text/template/parse", - }, - - // Cgo. - "runtime/cgo": {"L0", "C"}, - "CGO": {"C", "runtime/cgo"}, - - // Fake entry to satisfy the pseudo-import "C" - // that shows up in programs that use cgo. - "C": {}, - - // Plan 9 alone needs io/ioutil and os. - "os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"}, - - // Basic networking. - // Because net must be used by any package that wants to - // do networking portably, it must have a small dependency set: just L1+basic os. - "net": {"L1", "CGO", "os", "syscall", "time"}, - - // NET enables use of basic network-related packages. - "NET": { - "net", - "mime", - "net/textproto", - "net/url", - }, - - // Uses of networking. - "log/syslog": {"L4", "OS", "net"}, - "net/mail": {"L4", "NET", "OS"}, - "net/textproto": {"L4", "OS", "net"}, - - // Core crypto. - "crypto/aes": {"L3"}, - "crypto/des": {"L3"}, - "crypto/hmac": {"L3"}, - "crypto/md5": {"L3"}, - "crypto/rc4": {"L3"}, - "crypto/sha1": {"L3"}, - "crypto/sha256": {"L3"}, - "crypto/sha512": {"L3"}, - - "CRYPTO": { - "crypto/aes", - "crypto/des", - "crypto/hmac", - "crypto/md5", - "crypto/rc4", - "crypto/sha1", - "crypto/sha256", - "crypto/sha512", - }, - - // Random byte, number generation. - // This would be part of core crypto except that it imports - // math/big, which imports fmt. - "crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall"}, - - // Mathematical crypto: dependencies on fmt (L4) and math/big. - // We could avoid some of the fmt, but math/big imports fmt anyway. - "crypto/dsa": {"L4", "CRYPTO", "math/big"}, - "crypto/ecdsa": {"L4", "CRYPTO", "crypto/elliptic", "math/big"}, - "crypto/elliptic": {"L4", "CRYPTO", "math/big"}, - "crypto/rsa": {"L4", "CRYPTO", "crypto/rand", "math/big"}, - - "CRYPTO-MATH": { - "CRYPTO", - "crypto/dsa", - "crypto/ecdsa", - "crypto/elliptic", - "crypto/rand", - "crypto/rsa", - "encoding/asn1", - "math/big", - }, - - // SSL/TLS. - "crypto/tls": { - "L4", "CRYPTO-MATH", "CGO", "OS", - "container/list", "crypto/x509", "encoding/pem", "net", "syscall", - }, - "crypto/x509": { - "L4", "CRYPTO-MATH", "OS", "CGO", - "crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "syscall", - }, - "crypto/x509/pkix": {"L4", "CRYPTO-MATH"}, - - // Simple net+crypto-aware packages. - "mime/multipart": {"L4", "OS", "mime", "crypto/rand", "net/textproto"}, - "net/smtp": {"L4", "CRYPTO", "NET", "crypto/tls"}, - - // HTTP, kingpin of dependencies. - "net/http": { - "L4", "NET", "OS", - "compress/gzip", "crypto/tls", "mime/multipart", "runtime/debug", - }, - - // HTTP-using packages. - "expvar": {"L4", "OS", "encoding/json", "net/http"}, - "net/http/cgi": {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"}, - "net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"}, - "net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"}, - "net/http/httputil": {"L4", "NET", "OS", "net/http"}, - "net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof"}, - "net/rpc": {"L4", "NET", "encoding/gob", "net/http", "text/template"}, - "net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"}, -} - -// isMacro reports whether p is a package dependency macro -// (uppercase name). -func isMacro(p string) bool { - return 'A' <= p[0] && p[0] <= 'Z' -} - -func allowed(pkg string) map[string]bool { - m := map[string]bool{} - var allow func(string) - allow = func(p string) { - if m[p] { - return - } - m[p] = true // set even for macros, to avoid loop on cycle - - // Upper-case names are macro-expanded. - if isMacro(p) { - for _, pp := range pkgDeps[p] { - allow(pp) - } - } - } - for _, pp := range pkgDeps[pkg] { - allow(pp) - } - return m -} - -var bools = []bool{false, true} -var geese = []string{"darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"} -var goarches = []string{"386", "amd64", "arm"} - -type osPkg struct { - goos, pkg string -} - -// allowedErrors are the operating systems and packages known to contain errors -// (currently just "no Go source files") -var allowedErrors = map[osPkg]bool{ - osPkg{"windows", "log/syslog"}: true, - osPkg{"plan9", "log/syslog"}: true, -} - -func TestDependencies(t *testing.T) { - if runtime.GOOS == "nacl" { - // NaCl tests run in a limited file system and we do not - // provide access to every source file. - t.Skip("skipping on NaCl") - } - var all []string - - for k := range pkgDeps { - all = append(all, k) - } - sort.Strings(all) - - ctxt := Default - test := func(mustImport bool) { - for _, pkg := range all { - if isMacro(pkg) { - continue - } - if pkg == "runtime/cgo" && !ctxt.CgoEnabled { - continue - } - p, err := ctxt.Import(pkg, "", 0) - if err != nil { - if allowedErrors[osPkg{ctxt.GOOS, pkg}] { - continue - } - if !ctxt.CgoEnabled && pkg == "runtime/cgo" { - continue - } - // Some of the combinations we try might not - // be reasonable (like arm,plan9,cgo), so ignore - // errors for the auto-generated combinations. - if !mustImport { - continue - } - t.Errorf("%s/%s/cgo=%v %v", ctxt.GOOS, ctxt.GOARCH, ctxt.CgoEnabled, err) - continue - } - ok := allowed(pkg) - var bad []string - for _, imp := range p.Imports { - if !ok[imp] { - bad = append(bad, imp) - } - } - if bad != nil { - t.Errorf("%s/%s/cgo=%v unexpected dependency: %s imports %v", ctxt.GOOS, ctxt.GOARCH, ctxt.CgoEnabled, pkg, bad) - } - } - } - test(true) - - if testing.Short() { - t.Logf("skipping other systems") - return - } - - for _, ctxt.GOOS = range geese { - for _, ctxt.GOARCH = range goarches { - for _, ctxt.CgoEnabled = range bools { - test(false) - } - } - } -} diff --git a/src/pkg/go/build/doc.go b/src/pkg/go/build/doc.go deleted file mode 100644 index f17f76ccc..000000000 --- a/src/pkg/go/build/doc.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package build gathers information about Go packages. -// -// Go Path -// -// The Go path is a list of directory trees containing Go source code. -// It is consulted to resolve imports that cannot be found in the standard -// Go tree. The default path is the value of the GOPATH environment -// variable, interpreted as a path list appropriate to the operating system -// (on Unix, the variable is a colon-separated string; -// on Windows, a semicolon-separated string; -// on Plan 9, a list). -// -// Each directory listed in the Go path must have a prescribed structure: -// -// The src/ directory holds source code. The path below 'src' determines -// the import path or executable name. -// -// The pkg/ directory holds installed package objects. -// As in the Go tree, each target operating system and -// architecture pair has its own subdirectory of pkg -// (pkg/GOOS_GOARCH). -// -// If DIR is a directory listed in the Go path, a package with -// source in DIR/src/foo/bar can be imported as "foo/bar" and -// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a" -// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a"). -// -// The bin/ directory holds compiled commands. -// Each command is named for its source directory, but only -// using the final element, not the entire path. That is, the -// command with source in DIR/src/foo/quux is installed into -// DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped -// so that you can add DIR/bin to your PATH to get at the -// installed commands. -// -// Here's an example directory layout: -// -// GOPATH=/home/user/gocode -// -// /home/user/gocode/ -// src/ -// foo/ -// bar/ (go code in package bar) -// x.go -// quux/ (go code in package main) -// y.go -// bin/ -// quux (installed command) -// pkg/ -// linux_amd64/ -// foo/ -// bar.a (installed package object) -// -// Build Constraints -// -// A build constraint, also known as a build tag, is a line comment that begins -// -// // +build -// -// that lists the conditions under which a file should be included in the package. -// Constraints may appear in any kind of source file (not just Go), but -// they must appear near the top of the file, preceded -// only by blank lines and other line comments. These rules mean that in Go -// files a build constraint must appear before the package clause. -// -// To distinguish build constraints from package documentation, a series of -// build constraints must be followed by a blank line. -// -// A build constraint is evaluated as the OR of space-separated options; -// each option evaluates as the AND of its comma-separated terms; -// and each term is an alphanumeric word or, preceded by !, its negation. -// That is, the build constraint: -// -// // +build linux,386 darwin,!cgo -// -// corresponds to the boolean formula: -// -// (linux AND 386) OR (darwin AND (NOT cgo)) -// -// A file may have multiple build constraints. The overall constraint is the AND -// of the individual constraints. That is, the build constraints: -// -// // +build linux darwin -// // +build 386 -// -// corresponds to the boolean formula: -// -// (linux OR darwin) AND 386 -// -// During a particular build, the following words are satisfied: -// -// - the target operating system, as spelled by runtime.GOOS -// - the target architecture, as spelled by runtime.GOARCH -// - the compiler being used, either "gc" or "gccgo" -// - "cgo", if ctxt.CgoEnabled is true -// - "go1.1", from Go version 1.1 onward -// - "go1.2", from Go version 1.2 onward -// - "go1.3", from Go version 1.3 onward -// - any additional words listed in ctxt.BuildTags -// -// If a file's name, after stripping the extension and a possible _test suffix, -// matches any of the following patterns: -// *_GOOS -// *_GOARCH -// *_GOOS_GOARCH -// (example: source_windows_amd64.go) or the literals: -// GOOS -// GOARCH -// (example: windows.go) where GOOS and GOARCH represent any known operating -// system and architecture values respectively, then the file is considered to -// have an implicit build constraint requiring those terms. -// -// To keep a file from being considered for the build: -// -// // +build ignore -// -// (any other unsatisfied word will work as well, but ``ignore'' is conventional.) -// -// To build a file only when using cgo, and only on Linux and OS X: -// -// // +build linux,cgo darwin,cgo -// -// Such a file is usually paired with another file implementing the -// default functionality for other systems, which in this case would -// carry the constraint: -// -// // +build !linux,!darwin !cgo -// -// Naming a file dns_windows.go will cause it to be included only when -// building the package for Windows; similarly, math_386.s will be included -// only when building the package for 32-bit x86. -// -package build diff --git a/src/pkg/go/build/read.go b/src/pkg/go/build/read.go deleted file mode 100644 index c8079dfd1..000000000 --- a/src/pkg/go/build/read.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "bufio" - "errors" - "io" -) - -type importReader struct { - b *bufio.Reader - buf []byte - peek byte - err error - eof bool - nerr int -} - -func isIdent(c byte) bool { - return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= 0x80 -} - -var ( - errSyntax = errors.New("syntax error") - errNUL = errors.New("unexpected NUL in input") -) - -// syntaxError records a syntax error, but only if an I/O error has not already been recorded. -func (r *importReader) syntaxError() { - if r.err == nil { - r.err = errSyntax - } -} - -// readByte reads the next byte from the input, saves it in buf, and returns it. -// If an error occurs, readByte records the error in r.err and returns 0. -func (r *importReader) readByte() byte { - c, err := r.b.ReadByte() - if err == nil { - r.buf = append(r.buf, c) - if c == 0 { - err = errNUL - } - } - if err != nil { - if err == io.EOF { - r.eof = true - } else if r.err == nil { - r.err = err - } - c = 0 - } - return c -} - -// peekByte returns the next byte from the input reader but does not advance beyond it. -// If skipSpace is set, peekByte skips leading spaces and comments. -func (r *importReader) peekByte(skipSpace bool) byte { - if r.err != nil { - if r.nerr++; r.nerr > 10000 { - panic("go/build: import reader looping") - } - return 0 - } - - // Use r.peek as first input byte. - // Don't just return r.peek here: it might have been left by peekByte(false) - // and this might be peekByte(true). - c := r.peek - if c == 0 { - c = r.readByte() - } - for r.err == nil && !r.eof { - if skipSpace { - // For the purposes of this reader, semicolons are never necessary to - // understand the input and are treated as spaces. - switch c { - case ' ', '\f', '\t', '\r', '\n', ';': - c = r.readByte() - continue - - case '/': - c = r.readByte() - if c == '/' { - for c != '\n' && r.err == nil && !r.eof { - c = r.readByte() - } - } else if c == '*' { - var c1 byte - for (c != '*' || c1 != '/') && r.err == nil { - if r.eof { - r.syntaxError() - } - c, c1 = c1, r.readByte() - } - } else { - r.syntaxError() - } - c = r.readByte() - continue - } - } - break - } - r.peek = c - return r.peek -} - -// nextByte is like peekByte but advances beyond the returned byte. -func (r *importReader) nextByte(skipSpace bool) byte { - c := r.peekByte(skipSpace) - r.peek = 0 - return c -} - -// readKeyword reads the given keyword from the input. -// If the keyword is not present, readKeyword records a syntax error. -func (r *importReader) readKeyword(kw string) { - r.peekByte(true) - for i := 0; i < len(kw); i++ { - if r.nextByte(false) != kw[i] { - r.syntaxError() - return - } - } - if isIdent(r.peekByte(false)) { - r.syntaxError() - } -} - -// readIdent reads an identifier from the input. -// If an identifier is not present, readIdent records a syntax error. -func (r *importReader) readIdent() { - c := r.peekByte(true) - if !isIdent(c) { - r.syntaxError() - return - } - for isIdent(r.peekByte(false)) { - r.peek = 0 - } -} - -// readString reads a quoted string literal from the input. -// If an identifier is not present, readString records a syntax error. -func (r *importReader) readString() { - switch r.nextByte(true) { - case '`': - for r.err == nil { - if r.nextByte(false) == '`' { - break - } - if r.eof { - r.syntaxError() - } - } - case '"': - for r.err == nil { - c := r.nextByte(false) - if c == '"' { - break - } - if r.eof || c == '\n' { - r.syntaxError() - } - if c == '\\' { - r.nextByte(false) - } - } - default: - r.syntaxError() - } -} - -// readImport reads an import clause - optional identifier followed by quoted string - -// from the input. -func (r *importReader) readImport() { - c := r.peekByte(true) - if c == '.' { - r.peek = 0 - } else if isIdent(c) { - r.readIdent() - } - r.readString() -} - -// readComments is like ioutil.ReadAll, except that it only reads the leading -// block of comments in the file. -func readComments(f io.Reader) ([]byte, error) { - r := &importReader{b: bufio.NewReader(f)} - r.peekByte(true) - if r.err == nil && !r.eof { - // Didn't reach EOF, so must have found a non-space byte. Remove it. - r.buf = r.buf[:len(r.buf)-1] - } - return r.buf, r.err -} - -// readImports is like ioutil.ReadAll, except that it expects a Go file as input -// and stops reading the input once the imports have completed. -func readImports(f io.Reader, reportSyntaxError bool) ([]byte, error) { - r := &importReader{b: bufio.NewReader(f)} - - r.readKeyword("package") - r.readIdent() - for r.peekByte(true) == 'i' { - r.readKeyword("import") - if r.peekByte(true) == '(' { - r.nextByte(false) - for r.peekByte(true) != ')' && r.err == nil { - r.readImport() - } - r.nextByte(false) - } else { - r.readImport() - } - } - - // If we stopped successfully before EOF, we read a byte that told us we were done. - // Return all but that last byte, which would cause a syntax error if we let it through. - if r.err == nil && !r.eof { - return r.buf[:len(r.buf)-1], nil - } - - // If we stopped for a syntax error, consume the whole file so that - // we are sure we don't change the errors that go/parser returns. - if r.err == errSyntax && !reportSyntaxError { - r.err = nil - for r.err == nil && !r.eof { - r.readByte() - } - } - - return r.buf, r.err -} diff --git a/src/pkg/go/build/read_test.go b/src/pkg/go/build/read_test.go deleted file mode 100644 index 2dcc1208f..000000000 --- a/src/pkg/go/build/read_test.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "io" - "strings" - "testing" -) - -const quote = "`" - -type readTest struct { - // Test input contains ℙ where readImports should stop. - in string - err string -} - -var readImportsTests = []readTest{ - { - `package p`, - "", - }, - { - `package p; import "x"`, - "", - }, - { - `package p; import . "x"`, - "", - }, - { - `package p; import "x";ℙvar x = 1`, - "", - }, - { - `package p - - // comment - - import "x" - import _ "x" - import a "x" - - /* comment */ - - import ( - "x" /* comment */ - _ "x" - a "x" // comment - ` + quote + `x` + quote + ` - _ /*comment*/ ` + quote + `x` + quote + ` - a ` + quote + `x` + quote + ` - ) - import ( - ) - import () - import()import()import() - import();import();import() - - ℙvar x = 1 - `, - "", - }, -} - -var readCommentsTests = []readTest{ - { - `ℙpackage p`, - "", - }, - { - `ℙpackage p; import "x"`, - "", - }, - { - `ℙpackage p; import . "x"`, - "", - }, - { - `// foo - - /* bar */ - - /* quux */ // baz - - /*/ zot */ - - // asdf - ℙHello, world`, - "", - }, -} - -func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) { - for i, tt := range tests { - var in, testOut string - j := strings.Index(tt.in, "ℙ") - if j < 0 { - in = tt.in - testOut = tt.in - } else { - in = tt.in[:j] + tt.in[j+len("ℙ"):] - testOut = tt.in[:j] - } - r := strings.NewReader(in) - buf, err := read(r) - if err != nil { - if tt.err == "" { - t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf)) - continue - } - if !strings.Contains(err.Error(), tt.err) { - t.Errorf("#%d: err=%q, expected %q", i, err, tt.err) - continue - } - continue - } - if err == nil && tt.err != "" { - t.Errorf("#%d: success, expected %q", i, tt.err) - continue - } - - out := string(buf) - if out != testOut { - t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut) - } - } -} - -func TestReadImports(t *testing.T) { - testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true) }) -} - -func TestReadComments(t *testing.T) { - testRead(t, readCommentsTests, readComments) -} - -var readFailuresTests = []readTest{ - { - `package`, - "syntax error", - }, - { - "package p\n\x00\nimport `math`\n", - "unexpected NUL in input", - }, - { - `package p; import`, - "syntax error", - }, - { - `package p; import "`, - "syntax error", - }, - { - "package p; import ` \n\n", - "syntax error", - }, - { - `package p; import "x`, - "syntax error", - }, - { - `package p; import _`, - "syntax error", - }, - { - `package p; import _ "`, - "syntax error", - }, - { - `package p; import _ "x`, - "syntax error", - }, - { - `package p; import .`, - "syntax error", - }, - { - `package p; import . "`, - "syntax error", - }, - { - `package p; import . "x`, - "syntax error", - }, - { - `package p; import (`, - "syntax error", - }, - { - `package p; import ("`, - "syntax error", - }, - { - `package p; import ("x`, - "syntax error", - }, - { - `package p; import ("x"`, - "syntax error", - }, -} - -func TestReadFailures(t *testing.T) { - // Errors should be reported (true arg to readImports). - testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true) }) -} - -func TestReadFailuresIgnored(t *testing.T) { - // Syntax errors should not be reported (false arg to readImports). - // Instead, entire file should be the output and no error. - // Convert tests not to return syntax errors. - tests := make([]readTest, len(readFailuresTests)) - copy(tests, readFailuresTests) - for i := range tests { - tt := &tests[i] - if !strings.Contains(tt.err, "NUL") { - tt.err = "" - } - } - testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false) }) -} diff --git a/src/pkg/go/build/syslist.go b/src/pkg/go/build/syslist.go deleted file mode 100644 index 5c42b946b..000000000 --- a/src/pkg/go/build/syslist.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -const goosList = "darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows " -const goarchList = "386 amd64 amd64p32 arm " diff --git a/src/pkg/go/build/syslist_test.go b/src/pkg/go/build/syslist_test.go deleted file mode 100644 index 3be2928f5..000000000 --- a/src/pkg/go/build/syslist_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package build - -import ( - "runtime" - "testing" -) - -var ( - thisOS = runtime.GOOS - thisArch = runtime.GOARCH - otherOS = anotherOS() - otherArch = anotherArch() -) - -func anotherOS() string { - if thisOS != "darwin" { - return "darwin" - } - return "linux" -} - -func anotherArch() string { - if thisArch != "amd64" { - return "amd64" - } - return "386" -} - -type GoodFileTest struct { - name string - result bool -} - -var tests = []GoodFileTest{ - {"file.go", true}, - {"file.c", true}, - {"file_foo.go", true}, - {"file_" + thisArch + ".go", true}, - {"file_" + otherArch + ".go", false}, - {"file_" + thisOS + ".go", true}, - {"file_" + otherOS + ".go", false}, - {"file_" + thisOS + "_" + thisArch + ".go", true}, - {"file_" + otherOS + "_" + thisArch + ".go", false}, - {"file_" + thisOS + "_" + otherArch + ".go", false}, - {"file_" + otherOS + "_" + otherArch + ".go", false}, - {"file_foo_" + thisArch + ".go", true}, - {"file_foo_" + otherArch + ".go", false}, - {"file_" + thisOS + ".c", true}, - {"file_" + otherOS + ".c", false}, -} - -func TestGoodOSArch(t *testing.T) { - for _, test := range tests { - if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result { - t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result) - } - } -} diff --git a/src/pkg/go/build/testdata/other/file/file.go b/src/pkg/go/build/testdata/other/file/file.go deleted file mode 100644 index bbfd3e9e5..000000000 --- a/src/pkg/go/build/testdata/other/file/file.go +++ /dev/null @@ -1,5 +0,0 @@ -// Test data - not compiled. - -package file - -func F() {} diff --git a/src/pkg/go/build/testdata/other/main.go b/src/pkg/go/build/testdata/other/main.go deleted file mode 100644 index e0904357c..000000000 --- a/src/pkg/go/build/testdata/other/main.go +++ /dev/null @@ -1,11 +0,0 @@ -// Test data - not compiled. - -package main - -import ( - "./file" -) - -func main() { - file.F() -} |
