diff options
Diffstat (limited to 'libgo/go/go/build/build.go')
-rw-r--r-- | libgo/go/go/build/build.go | 84 |
1 files changed, 63 insertions, 21 deletions
diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go index cce5d482ada..5aa32d0ae44 100644 --- a/libgo/go/go/build/build.go +++ b/libgo/go/go/build/build.go @@ -155,6 +155,7 @@ func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) { return hasSubdir(rootSym, dirSym) } +// hasSubdir reports if dir is within root by performing lexical analysis only. func hasSubdir(root, dir string) (rel string, ok bool) { const sep = string(filepath.Separator) root = filepath.Clean(root) @@ -290,7 +291,8 @@ func defaultContext() Context { // 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". - c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8"} + // NOTE: If you add to this list, also update the doc comment in doc.go. + c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8", "go1.9"} env := os.Getenv("CGO_ENABLED") // No defaultCGO_ENABLED in gccgo. @@ -529,6 +531,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa if !ctxt.isAbsPath(path) { p.Dir = ctxt.joinPath(srcDir, path) } + // p.Dir directory may or may not exist. Gather partial information first, check if it exists later. // Determine canonical import path, if any. // Exclude results where the import path would include /testdata/. inTestdata := func(sub string) bool { @@ -683,6 +686,16 @@ Found: } } + // If it's a local import path, by the time we get here, we still haven't checked + // that p.Dir directory exists. This is the right time to do that check. + // We can't do it earlier, because we want to gather partial information for the + // non-nil *Package returned when an error occurs. + // We need to do this before we return early on FindOnly flag. + if IsLocalImport(path) && !ctxt.isDir(p.Dir) { + // package was not found + return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir) + } + if mode&FindOnly != 0 { return p, pkgerr } @@ -718,7 +731,7 @@ Found: p.InvalidGoFiles = append(p.InvalidGoFiles, name) } - match, data, filename, err := ctxt.matchFile(p.Dir, name, true, allTags, &p.BinaryOnly) + match, data, filename, err := ctxt.matchFile(p.Dir, name, allTags, &p.BinaryOnly) if err != nil { badFile(err) continue @@ -1032,19 +1045,19 @@ func parseWord(data []byte) (word, rest []byte) { // 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, nil) + match, _, _, err = ctxt.matchFile(dir, name, nil, 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 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, binaryOnly *bool) (match bool, data []byte, filename string, err error) { +func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binaryOnly *bool) (match bool, data []byte, filename string, err error) { if strings.HasPrefix(name, "_") || strings.HasPrefix(name, ".") { return @@ -1271,6 +1284,12 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) } switch verb { + case "CFLAGS", "CPPFLAGS", "CXXFLAGS", "FFLAGS", "LDFLAGS": + // Change relative paths to absolute. + ctxt.makePathsAbsolute(args, di.Dir) + } + + switch verb { case "CFLAGS": di.CgoCFLAGS = append(di.CgoCFLAGS, args...) case "CPPFLAGS": @@ -1298,40 +1317,63 @@ func expandSrcDir(str string, srcdir string) (string, bool) { // to "/" before starting (eg: on windows). srcdir = filepath.ToSlash(srcdir) - // Spaces are tolerated in ${SRCDIR}, but not anywhere else. chunks := strings.Split(str, "${SRCDIR}") if len(chunks) < 2 { - return str, safeCgoName(str, false) + return str, safeCgoName(str) } ok := true for _, chunk := range chunks { - ok = ok && (chunk == "" || safeCgoName(chunk, false)) + ok = ok && (chunk == "" || safeCgoName(chunk)) } - ok = ok && (srcdir == "" || safeCgoName(srcdir, true)) + ok = ok && (srcdir == "" || safeCgoName(srcdir)) res := strings.Join(chunks, srcdir) return res, ok && res != "" } +// makePathsAbsolute looks for compiler options that take paths and +// makes them absolute. We do this because through the 1.8 release we +// ran the compiler in the package directory, so any relative -I or -L +// options would be relative to that directory. In 1.9 we changed to +// running the compiler in the build directory, to get consistent +// build results (issue #19964). To keep builds working, we change any +// relative -I or -L options to be absolute. +// +// Using filepath.IsAbs and filepath.Join here means the results will be +// different on different systems, but that's OK: -I and -L options are +// inherently system-dependent. +func (ctxt *Context) makePathsAbsolute(args []string, srcDir string) { + nextPath := false + for i, arg := range args { + if nextPath { + if !filepath.IsAbs(arg) { + args[i] = filepath.Join(srcDir, arg) + } + nextPath = false + } else if strings.HasPrefix(arg, "-I") || strings.HasPrefix(arg, "-L") { + if len(arg) == 2 { + nextPath = true + } else { + if !filepath.IsAbs(arg[2:]) { + args[i] = arg[:2] + filepath.Join(srcDir, arg[2:]) + } + } + } + } +} + // 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. // The @ is for OS X. See golang.org/issue/13720. // The % is for Jenkins. See golang.org/issue/16959. -const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@%" -const safeSpaces = " " +const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@% " -var safeBytes = []byte(safeSpaces + safeString) - -func safeCgoName(s string, spaces bool) bool { +func safeCgoName(s string) bool { if s == "" { return false } - safe := safeBytes - if !spaces { - safe = safe[len(safeSpaces):] - } for i := 0; i < len(s); i++ { - if c := s[i]; c < utf8.RuneSelf && bytes.IndexByte(safe, c) < 0 { + if c := s[i]; c < utf8.RuneSelf && strings.IndexByte(safeString, c) < 0 { return false } } |