Commit b03a5f66 authored by Russ Cox's avatar Russ Cox

cmd/go: fixes

* Install tools into tool dir always
  (Fixes issue 3049.  Fixes issue 2868.  Fixes issue 2925.)
* Make packages depend on compiler, linker (Fixes issue 3036.)
* Do not recompile packages across roots (Fixes issue 3149.)
* Allow use of binary-only packages (Fixes issue 2775.)
* Avoid duplicate cgo dependencies (Fixes issue 3001.)
* Show less in go get -x.  (Fixes issue 2926.)
* Do not force repo root for existing checkout (Fixes issue 2969.)
* Show full syntax error list always (Fixes issue 2811.)
* Clean arguments before processing (Fixes issue 3034.)
* Add flags for compiler, linker arguments (Fixes issue 2996.)
* Pass flags in make.bash (Fixes issue 3091.)
* Unify build flags, defined in one place.
* Clean up error messages (Fixes issue 3075.  Fixes issue 2923.)
* Support local import paths (Fixes issue 3118.)
* Allow top-level package outside $GOPATH (Fixes issue 3009.)

In addition to these fixes, all commands now take a list of
go files as a way to specify a single package, just as go build and
go run always have.  This means you can:

        go list -json x.go
        go fix x.go
        go vet x.go
        go test x_test.go

Preliminary tests in test.bash.
Mainly testing things that the ordinary build does not.
I don't mind if the script doesn't run on Windows.

I expect that gccgo support is now broken, and I hope that
people will feel free to file issues and/or send CLs to fix it.  :-)

R=golang-dev, dsymonds, r, rogpeppe
CC=golang-dev
https://golang.org/cl/5708054
parent ebe1664d
This diff is collapsed.
......@@ -13,7 +13,7 @@ import (
)
var cmdClean = &Command{
UsageLine: "clean [-i] [-r] [-n] [-x] [importpath...]",
UsageLine: "clean [-i] [-r] [-n] [-x] [packages]",
Short: "remove object files",
Long: `
Clean removes object files from package source directories.
......@@ -50,6 +50,8 @@ The -r flag causes clean to be applied recursively to all the
dependencies of the packages named by the import paths.
The -x flag causes clean to print remove commands as it executes them.
For more about specifying packages, see 'go help packages'.
`,
}
......
This diff is collapsed.
......@@ -6,13 +6,13 @@ package main
var cmdFix = &Command{
Run: runFix,
UsageLine: "fix [importpath...]",
UsageLine: "fix [packages]",
Short: "run go tool fix on packages",
Long: `
Fix runs the Go fix command on the packages named by the import paths.
For more about fix, see 'godoc fix'.
For more about import paths, see 'go help importpath'.
For more about specifying packages, see 'go help packages'.
To run fix with specific options, run 'go tool fix'.
......
......@@ -6,14 +6,14 @@ package main
var cmdFmt = &Command{
Run: runFmt,
UsageLine: "fmt [importpath...]",
UsageLine: "fmt [packages]",
Short: "run gofmt on package sources",
Long: `
Fmt runs the command 'gofmt -l -w' on the packages named
by the import paths. It prints the names of the files that are modified.
For more about gofmt, see 'godoc gofmt'.
For more about import paths, see 'go help importpath'.
For more about specifying packages, see 'go help packages'.
To run gofmt with specific options, run gofmt itself.
......@@ -32,14 +32,14 @@ func runFmt(cmd *Command, args []string) {
var cmdDoc = &Command{
Run: runDoc,
UsageLine: "doc [importpath...]",
UsageLine: "doc [packages]",
Short: "run godoc on package sources",
Long: `
Doc runs the godoc command on the packages named by the
import paths.
For more about godoc, see 'godoc godoc'.
For more about import paths, see 'go help importpath'.
For more about specifying packages, see 'go help packages'.
To run godoc with specific options, run godoc itself.
......@@ -49,6 +49,10 @@ See also: go fix, go fmt, go vet.
func runDoc(cmd *Command, args []string) {
for _, pkg := range packages(args) {
if pkg.ImportPath == "command-line arguments" {
errorf("go doc: cannot use package file list")
continue
}
run("godoc", pkg.Dir)
}
}
......@@ -8,7 +8,6 @@ package main
import (
"fmt"
"go/build"
"os"
"path/filepath"
"runtime"
......@@ -17,7 +16,7 @@ import (
)
var cmdGet = &Command{
UsageLine: "get [-a] [-d] [-fix] [-n] [-p n] [-u] [-v] [-x] [importpath...]",
UsageLine: "get [-a] [-d] [-fix] [-n] [-p n] [-u] [-v] [-x] [packages]",
Short: "download and install packages and dependencies",
Long: `
Get downloads and installs the packages named by the import paths,
......@@ -33,12 +32,12 @@ The -fix flag instructs get to run the fix tool on the downloaded packages
before resolving dependencies or building the code.
The -u flag instructs get to use the network to update the named packages
and their dependencies. By default, get uses the network to check out
and their dependencies. By default, get uses the network to check out
missing packages but does not use it to look for updates to existing packages.
TODO: Explain versions better.
For more about import paths, see 'go help importpath'.
For more about specifying packages, see 'go help packages'.
For more about how 'go get' finds source code to
download, see 'go help remote'.
......@@ -151,22 +150,35 @@ func download(arg string, stk *importStack) {
// downloadPackage runs the create or download command
// to make the first copy of or update a copy of the given package.
func downloadPackage(p *Package) error {
// Analyze the import path to determine the version control system,
// repository, and the import path for the root of the repository.
vcs, repo, rootPath, err := vcsForImportPath(p.ImportPath)
var (
vcs *vcsCmd
repo, rootPath string
err error
)
if p.build.SrcRoot != "" {
// Directory exists. Look for checkout along path to src.
vcs, rootPath, err = vcsForDir(p)
repo = "<local>" // should be unused; make distinctive
} else {
// Analyze the import path to determine the version control system,
// repository, and the import path for the root of the repository.
vcs, repo, rootPath, err = vcsForImportPath(p.ImportPath)
}
if err != nil {
return err
}
if p.t == nil {
if p.build.SrcRoot == "" {
// Package not found. Put in first directory of $GOPATH or else $GOROOT.
p.t = build.Path[0] // $GOROOT
if len(build.Path) > 1 {
p.t = build.Path[1] // first in $GOPATH
if list := filepath.SplitList(buildContext.GOPATH); len(list) > 0 {
p.build.SrcRoot = filepath.Join(list[0], "src")
p.build.PkgRoot = filepath.Join(list[0], "pkg")
} else {
p.build.SrcRoot = filepath.Join(goroot, "src", "pkg")
p.build.PkgRoot = filepath.Join(goroot, "pkg")
}
p.Dir = filepath.Join(p.t.SrcDir(), p.ImportPath)
}
root := filepath.Join(p.t.SrcDir(), rootPath)
root := filepath.Join(p.build.SrcRoot, rootPath)
// If we've considered this repository already, don't do it again.
if downloadRootCache[root] {
return nil
......@@ -206,6 +218,14 @@ func downloadPackage(p *Package) error {
}
}
if buildN {
// Do not show tag sync in -n; it's noise more than anything,
// and since we're not running commands, no tag will be found.
// But avoid printing nothing.
fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd)
return nil
}
// Select and sync to appropriate version of the repository.
tags, err := vcs.tags(root)
if err != nil {
......
......@@ -4,13 +4,15 @@
package main
var helpImportpath = &Command{
UsageLine: "importpath",
Short: "description of import paths",
var helpPackages = &Command{
UsageLine: "packages",
Short: "description of package lists",
Long: `
Many commands apply to a set of packages named by import paths:
Many commands apply to a set of packages:
go action [importpath...]
go action [packages]
Usually, [packages] is a list of import paths.
An import path that is a rooted path or that begins with
a . or .. element is interpreted as a file system path and
......@@ -34,7 +36,7 @@ An import path is a pattern if it includes one or more "..." wildcards,
each of which can match any string, including the empty string and
strings containing slashes. Such a pattern expands to all package
directories found in the GOPATH trees with names matching the
patterns. For example, encoding/... expands to all package
patterns. For example, encoding/... expands to all packages
in subdirectories of the encoding tree, while net... expands to
net and all its subdirectories.
......@@ -47,6 +49,11 @@ unique prefix that belongs to you. For example, paths used
internally at Google all begin with 'google', and paths
denoting remote repositories begin with the path to the code,
such as 'code.google.com/p/project'.
As a special case, if the package list is a list of .go files from a
single directory, the command is applied to a single synthesized
package made up of exactly those files, ignoring any build constraints
in those files and ignoring any other files in the directory.
`,
}
......
......@@ -13,7 +13,7 @@ import (
)
var cmdList = &Command{
UsageLine: "list [-e] [-f format] [-json] [importpath...]",
UsageLine: "list [-e] [-f format] [-json] [packages]",
Short: "list packages",
Long: `
List lists the packages named by the import paths, one per line.
......@@ -69,7 +69,7 @@ printing. Erroneous packages will have a non-empty ImportPath and
a non-nil Error field; other information may or may not be missing
(zeroed).
For more about import paths, see 'go help importpath'.
For more about specifying packages, see 'go help packages'.
`,
}
......
......@@ -88,7 +88,7 @@ var commands = []*Command{
cmdVet,
helpGopath,
helpImportpath,
helpPackages,
helpRemote,
helpTestflag,
helpTestfunc,
......@@ -251,7 +251,24 @@ func importPaths(args []string) []string {
}
var out []string
for _, a := range args {
if isLocalPath(a) && strings.Contains(a, "...") {
// Arguments are supposed to be import paths, but
// as a courtesy to Windows developers, rewrite \ to /
// in command-line arguments. Handles .\... and so on.
if filepath.Separator == '\\' {
a = strings.Replace(a, `\`, `/`, -1)
}
// Put argument in canonical form, but preserve leading ./.
if strings.HasPrefix(a, "./") {
a = "./" + path.Clean(a)
if a == "./." {
a = "."
}
} else {
a = path.Clean(a)
}
if build.IsLocalImport(a) && strings.Contains(a, "...") {
out = append(out, allPackagesInFS(a)...)
continue
}
......@@ -350,7 +367,6 @@ func allPackages(pattern string) []string {
var pkgs []string
// Commands
goroot := build.Path[0].Path
cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
if err != nil || !fi.IsDir() || path == cmd {
......@@ -362,7 +378,7 @@ func allPackages(pattern string) []string {
return filepath.SkipDir
}
_, err = build.ScanDir(path)
_, err = build.ImportDir(path, 0)
if err != nil {
return nil
}
......@@ -378,11 +394,11 @@ func allPackages(pattern string) []string {
return nil
})
for _, t := range build.Path {
if pattern == "std" && !t.Goroot {
for _, src := range buildContext.SrcDirs() {
if pattern == "std" && src != gorootSrcPkg {
continue
}
src := t.SrcDir() + string(filepath.Separator)
src = filepath.Clean(src) + string(filepath.Separator)
filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
if err != nil || !fi.IsDir() || path == src {
return nil
......@@ -403,21 +419,13 @@ func allPackages(pattern string) []string {
}
have[name] = true
_, err = build.ScanDir(path)
_, err = build.ImportDir(path, 0)
if err != nil && strings.Contains(err.Error(), "no Go source files") {
return nil
}
if match(name) {
pkgs = append(pkgs, name)
}
// Avoid go/build test data.
// TODO: Move it into a testdata directory.
if path == filepath.Join(build.Path[0].SrcDir(), "go/build") {
return filepath.SkipDir
}
return nil
})
}
......@@ -465,7 +473,7 @@ func allPackagesInFS(pattern string) []string {
if !match(name) {
return nil
}
if _, err = build.ScanDir(path); err != nil {
if _, err = build.ImportDir(path, 0); err != nil {
return nil
}
pkgs = append(pkgs, name)
......@@ -494,10 +502,3 @@ func stringList(args ...interface{}) []string {
}
return x
}
// isLocalPath returns true if arg is an import path denoting
// a local file system directory. That is, it returns true if the
// path begins with ./ or ../ .
func isLocalPath(arg string) bool {
return arg == "." || arg == ".." || strings.HasPrefix(arg, "./") || strings.HasPrefix(arg, "../")
}
This diff is collapsed.
......@@ -12,14 +12,12 @@ import (
)
var cmdRun = &Command{
UsageLine: "run [-a] [-n] [-x] gofiles... [arguments...]",
UsageLine: "run [build flags] gofiles... [arguments...]",
Short: "compile and run Go program",
Long: `
Run compiles and runs the main package comprising the named Go source files.
The -a flag forces reinstallation of packages that are already up-to-date.
The -n flag prints the commands but does not run them.
The -x flag prints the commands.
For more about build flags, see 'go help build'.
See also: go build.
`,
......@@ -46,7 +44,7 @@ func runRun(cmd *Command, args []string) {
i++
}
files, cmdArgs := args[:i], args[i:]
p := goFilesPackage(files, "")
p := goFilesPackage(files)
p.target = "" // must build - not up to date
a1 := b.action(modeBuild, modeBuild, p)
a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
......
#!/bin/bash
# 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.
set -e
go build -o testgo
ok=true
# Test that error messages have file:line information
# at beginning of line.
for i in testdata/errmsg/*.go
do
# TODO: |cat should not be necessary here but is.
./testgo test $i 2>&1 | cat >err.out || true
if ! grep -q "^$i:" err.out; then
echo "$i: missing file:line in error message"
cat err.out
ok=false
fi
done
# Test local (./) imports.
./testgo build -o hello testdata/local/easy.go
./hello >hello.out
if ! grep -q '^easysub\.Hello' hello.out; then
echo "testdata/local/easy.go did not generate expected output"
cat hello.out
ok=false
fi
./testgo build -o hello testdata/local/hard.go
./hello >hello.out
if ! grep -q '^sub\.Hello' hello.out || ! grep -q '^subsub\.Hello' hello.out ; then
echo "testdata/local/hard.go did not generate expected output"
cat hello.out
ok=false
fi
rm -f err.out hello.out hello
# Test that go install x.go fails.
if ./testgo install testdata/local/easy.go >/dev/null 2>&1; then
echo "go install testdata/local/easy.go succeeded"
ok=false
fi
if $ok; then
echo PASS
else
echo FAIL
exit 1
fi
......@@ -11,7 +11,6 @@ import (
"go/build"
"go/doc"
"go/parser"
"go/scanner"
"go/token"
"os"
"os/exec"
......@@ -33,7 +32,7 @@ func init() {
var cmdTest = &Command{
CustomFlags: true,
UsageLine: "test [-c] [-i] [-p n] [-x] [importpath...] [flags for test binary]",
UsageLine: "test [-c] [-i] [build flags] [packages] [flags for test binary]",
Short: "test packages",
Long: `
'Go test' automates testing the packages named by the import paths.
......@@ -56,7 +55,7 @@ with source in the current directory, including tests, and runs the tests.
The package is built in a temporary directory so it does not interfere with the
non-test installation.
The flags handled by 'go test' itself are:
In addition to the build flags, the flags handled by 'go test' itself are:
-c Compile the test binary to pkg.test but do not run it.
......@@ -64,16 +63,11 @@ The flags handled by 'go test' itself are:
Install packages that are dependencies of the test.
Do not run the test.
-p n
Compile and test up to n packages in parallel.
The default value is the number of CPUs available.
-x Print each subcommand go test executes.
The test binary also accepts flags that control execution of the test; these
flags are also accessible by 'go test'. See 'go help testflag' for details.
See 'go help importpath' for more about import paths.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
See also: go build, go vet.
`,
......@@ -134,7 +128,7 @@ directory containing the package sources, has its own flags:
The default is 1 second.
-test.cpu 1,2,4
Specify a list of GOMAXPROCS values for which the tests or
Specify a list of GOMAXPROCS values for which the tests or
benchmarks should be executed. The default is the current value
of GOMAXPROCS.
......@@ -265,10 +259,10 @@ func runTest(cmd *Command, args []string) {
}
for _, p := range pkgs {
// Dependencies for each test.
for _, path := range p.info.Imports {
for _, path := range p.Imports {
deps[path] = true
}
for _, path := range p.info.TestImports {
for _, path := range p.TestImports {
deps[path] = true
}
}
......@@ -307,17 +301,15 @@ func runTest(cmd *Command, args []string) {
for _, p := range pkgs {
buildTest, runTest, printTest, err := b.test(p)
if err != nil {
if list, ok := err.(scanner.ErrorList); ok {
const n = 10
if len(list) > n {
list = list[:n]
}
for _, err := range list {
errorf("%s", err)
}
continue
str := err.Error()
if strings.HasPrefix(str, "\n") {
str = str[1:]
}
if p.ImportPath != "" {
errorf("# %s\n%s", p.ImportPath, str)
} else {
errorf("%s", str)
}
errorf("%s", err)
continue
}
builds = append(builds, buildTest)
......@@ -380,7 +372,7 @@ func runTest(cmd *Command, args []string) {
}
func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) {
if len(p.info.TestGoFiles)+len(p.info.XTestGoFiles) == 0 {
if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
build := &action{p: p}
run := &action{p: p}
print := &action{f: (*builder).notest, p: p, deps: []*action{build}}
......@@ -393,20 +385,23 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// pmain - pkg.test binary
var ptest, pxtest, pmain *Package
// go/build does not distinguish the dependencies used
// by the TestGoFiles from the dependencies used by the
// XTestGoFiles, so we build one list and use it for both
// ptest and pxtest. No harm done.
var imports []*Package
var imports, ximports []*Package
var stk importStack
stk.push(p.ImportPath + "_test")
for _, path := range p.info.TestImports {
p1 := loadPackage(path, &stk)
for _, path := range p.TestImports {
p1 := loadImport(path, p.Dir, &stk, p.build.TestImportPos[path])
if p1.Error != nil {
return nil, nil, nil, p1.Error
}
imports = append(imports, p1)
}
for _, path := range p.XTestImports {
p1 := loadImport(path, p.Dir, &stk, p.build.XTestImportPos[path])
if p1.Error != nil {
return nil, nil, nil, p1.Error
}
ximports = append(ximports, p1)
}
stk.pop()
// Use last element of import path, not package name.
......@@ -429,7 +424,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// We write the external test package archive to
// $WORK/unicode/utf8/_test/unicode/utf8_test.a.
testDir := filepath.Join(b.work, filepath.FromSlash(p.ImportPath+"/_test"))
ptestObj := buildToolchain.pkgpath(testDir, p)
ptestObj := buildToolchain.pkgpath(testDir, p, false)
// Create the directory for the .a files.
ptestDir, _ := filepath.Split(ptestObj)
......@@ -441,17 +436,27 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
}
// Test package.
if len(p.info.TestGoFiles) > 0 {
if len(p.TestGoFiles) > 0 {
ptest = new(Package)
*ptest = *p
ptest.GoFiles = nil
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
ptest.GoFiles = append(ptest.GoFiles, p.info.TestGoFiles...)
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
ptest.target = ""
ptest.Imports = stringList(p.info.Imports, p.info.TestImports)
ptest.Imports = stringList(p.Imports, p.TestImports)
ptest.imports = append(append([]*Package{}, p.imports...), imports...)
ptest.pkgdir = testDir
ptest.fake = true
ptest.build = new(build.Package)
*ptest.build = *p.build
m := map[string][]token.Position{}
for k, v := range p.build.ImportPos {
m[k] = append(m[k], v...)
}
for k, v := range p.build.TestImportPos {
m[k] = append(m[k], v...)
}
ptest.build.ImportPos = m
a := b.action(modeBuild, modeBuild, ptest)
a.objdir = testDir + string(filepath.Separator)
a.objpkg = ptestObj
......@@ -462,23 +467,23 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
}
// External test package.
if len(p.info.XTestGoFiles) > 0 {
if len(p.XTestGoFiles) > 0 {
pxtest = &Package{
Name: p.Name + "_test",
ImportPath: p.ImportPath + "_test",
Dir: p.Dir,
GoFiles: p.info.XTestGoFiles,
Imports: p.info.TestImports,
t: p.t,
info: &build.DirInfo{},
imports: imports,
pkgdir: testDir,
fake: true,
GoFiles: p.XTestGoFiles,
Imports: p.XTestImports,
build: &build.Package{
ImportPos: p.build.XTestImportPos,
},
imports: append(ximports, ptest),
pkgdir: testDir,
fake: true,
}
pxtest.imports = append(pxtest.imports, ptest)
a := b.action(modeBuild, modeBuild, pxtest)
a.objdir = testDir + string(filepath.Separator)
a.objpkg = buildToolchain.pkgpath(testDir, pxtest)
a.objpkg = buildToolchain.pkgpath(testDir, pxtest, false)
a.target = a.objpkg
}
......@@ -487,9 +492,8 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
Name: "main",
Dir: testDir,
GoFiles: []string{"_testmain.go"},
t: p.t,
info: &build.DirInfo{},
imports: []*Package{ptest},
build: &build.Package{},
fake: true,
}
if pxtest != nil {
......@@ -498,11 +502,11 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// The generated main also imports testing and regexp.
stk.push("testmain")
ptesting := loadPackage("testing", &stk)
ptesting := loadImport("testing", "", &stk, nil)
if ptesting.Error != nil {
return nil, nil, nil, ptesting.Error
}
pregexp := loadPackage("regexp", &stk)
pregexp := loadImport("regexp", "", &stk, nil)
if pregexp.Error != nil {
return nil, nil, nil, pregexp.Error
}
......@@ -511,7 +515,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
a := b.action(modeBuild, modeBuild, pmain)
a.objdir = testDir + string(filepath.Separator)
a.objpkg = filepath.Join(testDir, "main.a")
a.target = filepath.Join(testDir, testBinary) + b.exe
a.target = filepath.Join(testDir, testBinary) + exeSuffix
pmainAction := a
if testC {
......@@ -520,7 +524,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
f: (*builder).install,
deps: []*action{pmainAction},
p: pmain,
target: testBinary + b.exe,
target: testBinary + exeSuffix,
}
printAction = &action{p: p, deps: []*action{runAction}} // nop
} else {
......@@ -664,14 +668,13 @@ func isTest(name, prefix string) bool {
func writeTestmain(out string, p *Package) error {
t := &testFuncs{
Package: p,
Info: p.info,
}
for _, file := range p.info.TestGoFiles {
for _, file := range p.TestGoFiles {
if err := t.load(filepath.Join(p.Dir, file), "_test", &t.NeedTest); err != nil {
return err
}
}
for _, file := range p.info.XTestGoFiles {
for _, file := range p.XTestGoFiles {
if err := t.load(filepath.Join(p.Dir, file), "_xtest", &t.NeedXtest); err != nil {
return err
}
......@@ -695,7 +698,6 @@ type testFuncs struct {
Benchmarks []testFunc
Examples []testFunc
Package *Package
Info *build.DirInfo
NeedTest bool
NeedXtest bool
}
......@@ -711,7 +713,7 @@ var testFileSet = token.NewFileSet()
func (t *testFuncs) load(filename, pkg string, seen *bool) error {
f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
if err != nil {
return err
return expandScanner(err)
}
for _, d := range f.Decls {
n, ok := d.(*ast.FuncDecl)
......
package foo
import "bar"
package foo_test
import "bar"
package main
import "./easysub"
func main() {
easysub.Hello()
}
package easysub
import "fmt"
func Hello() {
fmt.Println("easysub.Hello")
}
package main
import "./sub"
func main() {
sub.Hello()
}
package sub
import (
"fmt"
subsub "./sub"
)
func Hello() {
fmt.Println("sub.Hello")
subsub.Hello()
}
package subsub
import "fmt"
func Hello() {
fmt.Println("subsub.Hello")
}
......@@ -10,6 +10,7 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
)
......@@ -269,6 +270,38 @@ type vcsPath struct {
regexp *regexp.Regexp // cached compiled form of re
}
// vcsForDir inspects dir and its parents to determine the
// version control system and code repository to use.
// On return, root is the import path
// corresponding to the root of the repository
// (thus root is a prefix of importPath).
func vcsForDir(p *Package) (vcs *vcsCmd, root string, err error) {
// Clean and double-check that dir is in (a subdirectory of) srcRoot.
dir := filepath.Clean(p.Dir)
srcRoot := filepath.Clean(p.build.SrcRoot)
if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
}
for len(dir) > len(srcRoot) {
for _, vcs := range vcsList {
if fi, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil && fi.IsDir() {
return vcs, dir[len(srcRoot)+1:], nil
}
}
// Move to parent.
ndir := filepath.Dir(dir)
if len(ndir) >= len(dir) {
// Shouldn't happen, but just in case, stop.
break
}
dir = ndir
}
return nil, "", fmt.Errorf("directory %q is not using a known version control system", dir)
}
// vcsForImportPath analyzes importPath to determine the
// version control system, and code repository to use.
// On return, repo is the repository URL and root is the
......
......@@ -6,13 +6,13 @@ package main
var cmdVet = &Command{
Run: runVet,
UsageLine: "vet [importpath...]",
UsageLine: "vet [packages]",
Short: "run go tool vet on packages",
Long: `
Vet runs the Go vet command on the packages named by the import paths.
For more about vet, see 'godoc vet'.
For more about import paths, see 'go help importpath'.
For more about specifying packages, see 'go help packages'.
To run the vet tool with specific options, run 'go tool vet'.
......
......@@ -3,6 +3,29 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Environment variables that control make.bash:
#
# GOROOT_FINAL: The expected final Go root, baked into binaries.
# The default is the location of the Go tree during the build.
#
# GOHOSTARCH: The architecture for host tools (compilers and
# binaries). Binaries of this type must be executable on the current
# system, so the only common reason to set this is to set
# GOHOSTARCH=386 on an amd64 machine.
#
# GOARCH: The target architecture for installed packages and tools.
#
# GOOS: The target operating system for installed packages and tools.
#
# GCFLAGS: Additional 5g/6g/8g arguments to use when
# building the packages and commands.
#
# LDFLAGS: Additional 5l/6l/8l arguments to use when
# building the packages and commands.
#
# CGO_ENABLED: Setting this to 0 disables the use of cgo
# in the built and installed packages and tools.
set -e
if [ ! -f run.bash ]; then
echo 'make.bash must be run from $GOROOT/src' 1>&2
......@@ -88,12 +111,12 @@ echo
if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
echo "# Building packages and commands for host, $GOHOSTOS/$GOHOSTARCH."
GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
$GOTOOLDIR/go_bootstrap install -v std
$GOTOOLDIR/go_bootstrap install -gcflags "$GCFLAGS" -ldflags "$LDFLAGS" -v std
echo
fi
echo "# Building packages and commands for $GOOS/$GOARCH."
$GOTOOLDIR/go_bootstrap install -v std
$GOTOOLDIR/go_bootstrap install -gcflags "$GCFLAGS" -ldflags "$LDFLAGS" -v std
echo
rm -f $GOTOOLDIR/go_bootstrap
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment