Commit ca8a055f authored by Andrew Gerrand's avatar Andrew Gerrand

goinstall: support GOPATH; building and installing outside the Go tree

For example, with GOPATH set like so
        GOPATH=/home/adg/gocode
And after creating some subdirectories
        mkdir /home/adg/gocode/{bin,pkg,src}

I can use goinstall to install the github.com/nf/goto web server,
which depends on the github.com/nf/stat package, with
        goinstall github.com/nf/goto

This downloads and installs all dependencies (that aren't already
installed) like so
        /home/adg/gocode/bin/goto
        /home/adg/gocode/pkg/darwin_amd64/github.com/nf/stat.a
        /home/adg/gocode/src/github.com/nf/goto/...
        /home/adg/gocode/src/github.com/nf/stat/...

R=rsc, niemeyer
CC=golang-dev
https://golang.org/cl/4438043
parent 50e65ab3
...@@ -6,6 +6,10 @@ ifeq ($(GOOS),windows) ...@@ -6,6 +6,10 @@ ifeq ($(GOOS),windows)
TARG:=$(TARG).exe TARG:=$(TARG).exe
endif endif
ifeq ($(TARGDIR),)
TARGDIR:=$(QUOTED_GOBIN)
endif
all: $(TARG) all: $(TARG)
include $(QUOTED_GOROOT)/src/Make.common include $(QUOTED_GOROOT)/src/Make.common
...@@ -13,20 +17,20 @@ include $(QUOTED_GOROOT)/src/Make.common ...@@ -13,20 +17,20 @@ include $(QUOTED_GOROOT)/src/Make.common
PREREQ+=$(patsubst %,%.make,$(DEPS)) PREREQ+=$(patsubst %,%.make,$(DEPS))
$(TARG): _go_.$O $(TARG): _go_.$O
$(LD) -o $@ _go_.$O $(LD) $(LDIMPORTS) -o $@ _go_.$O
_go_.$O: $(GOFILES) $(PREREQ) _go_.$O: $(GOFILES) $(PREREQ)
$(GC) -o $@ $(GOFILES) $(GC) $(GCIMPORTS) -o $@ $(GOFILES)
install: $(QUOTED_GOBIN)/$(TARG) install: $(TARGDIR)/$(TARG)
$(QUOTED_GOBIN)/$(TARG): $(TARG) $(TARGDIR)/$(TARG): $(TARG)
cp -f $(TARG) $(QUOTED_GOBIN) cp -f $(TARG) $(TARGDIR)
CLEANFILES+=$(TARG) _test _testmain.go CLEANFILES+=$(TARG) _test _testmain.go
nuke: clean nuke: clean
rm -f $(QUOTED_GOBIN)/$(TARG) rm -f $(TARGDIR)/$(TARG)
# for gotest # for gotest
testpackage: _test/main.a testpackage: _test/main.a
...@@ -40,7 +44,7 @@ _test/main.a: _gotest_.$O ...@@ -40,7 +44,7 @@ _test/main.a: _gotest_.$O
gopack grc $@ _gotest_.$O gopack grc $@ _gotest_.$O
_gotest_.$O: $(GOFILES) $(GOTESTFILES) _gotest_.$O: $(GOFILES) $(GOTESTFILES)
$(GC) -o $@ $(GOFILES) $(GOTESTFILES) $(GC) $(GCIMPORTS) -o $@ $(GOFILES) $(GOTESTFILES)
importpath: importpath:
echo main echo main
...@@ -31,7 +31,11 @@ endif ...@@ -31,7 +31,11 @@ endif
pkgdir=$(QUOTED_GOROOT)/pkg/$(GOOS)_$(GOARCH) pkgdir=$(QUOTED_GOROOT)/pkg/$(GOOS)_$(GOARCH)
INSTALLFILES+=$(pkgdir)/$(TARG).a ifeq ($(TARGDIR),)
TARGDIR:=$(pkgdir)
endif
INSTALLFILES+=$(TARGDIR)/$(TARG).a
# The rest of the cgo rules are below, but these variable updates # The rest of the cgo rules are below, but these variable updates
# must be done here so they apply to the main rules. # must be done here so they apply to the main rules.
...@@ -46,7 +50,7 @@ GOFILES+=$(patsubst %.swig,_obj/%.go,$(patsubst %.swigcxx,%.swig,$(SWIGFILES))) ...@@ -46,7 +50,7 @@ GOFILES+=$(patsubst %.swig,_obj/%.go,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
OFILES+=$(patsubst %.swig,_obj/%_gc.$O,$(patsubst %.swigcxx,%.swig,$(SWIGFILES))) OFILES+=$(patsubst %.swig,_obj/%_gc.$O,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
SWIG_PREFIX=$(subst /,-,$(TARG)) SWIG_PREFIX=$(subst /,-,$(TARG))
SWIG_SOS+=$(patsubst %.swig,_obj/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES))) SWIG_SOS+=$(patsubst %.swig,_obj/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
INSTALLFILES+=$(patsubst %.swig,$(pkgdir)/swig/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES))) INSTALLFILES+=$(patsubst %.swig,$(TARGDIR)/swig/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
endif endif
PREREQ+=$(patsubst %,%.make,$(DEPS)) PREREQ+=$(patsubst %,%.make,$(DEPS))
...@@ -67,22 +71,22 @@ bench: ...@@ -67,22 +71,22 @@ bench:
gotest -test.bench=. -test.run="Do not run tests" gotest -test.bench=. -test.run="Do not run tests"
nuke: clean nuke: clean
rm -f $(pkgdir)/$(TARG).a rm -f $(TARGDIR)/$(TARG).a
testpackage-clean: testpackage-clean:
rm -f _test/$(TARG).a rm -f _test/$(TARG).a
install: $(INSTALLFILES) install: $(INSTALLFILES)
$(pkgdir)/$(TARG).a: _obj/$(TARG).a $(TARGDIR)/$(TARG).a: _obj/$(TARG).a
@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(pkgdir)/$(dir) @test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(TARGDIR)/$(dir)
cp _obj/$(TARG).a "$@" cp _obj/$(TARG).a "$@"
_go_.$O: $(GOFILES) $(PREREQ) _go_.$O: $(GOFILES) $(PREREQ)
$(GC) -o $@ $(GOFILES) $(GC) $(GCIMPORTS) -o $@ $(GOFILES)
_gotest_.$O: $(GOFILES) $(GOTESTFILES) $(PREREQ) _gotest_.$O: $(GOFILES) $(GOTESTFILES) $(PREREQ)
$(GC) -o $@ $(GOFILES) $(GOTESTFILES) $(GC) $(GCIMPORTS) -o $@ $(GOFILES) $(GOTESTFILES)
_obj/$(TARG).a: _go_.$O $(OFILES) _obj/$(TARG).a: _go_.$O $(OFILES)
@mkdir -p _obj/$(dir) @mkdir -p _obj/$(dir)
...@@ -222,13 +226,13 @@ _obj/$(SWIG_PREFIX)-%.so: _obj/%_wrap.o ...@@ -222,13 +226,13 @@ _obj/$(SWIG_PREFIX)-%.so: _obj/%_wrap.o
_obj/$(SWIG_PREFIX)-%.so: _obj/%_wrapcxx.o _obj/$(SWIG_PREFIX)-%.so: _obj/%_wrapcxx.o
$(HOST_CXX) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(SWIG_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS)) $(_SWIG_LDFLAGS_$(GOOS)) $(HOST_CXX) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(SWIG_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS)) $(_SWIG_LDFLAGS_$(GOOS))
$(pkgdir)/swig/$(SWIG_PREFIX)-%.so: _obj/$(SWIG_PREFIX)-%.so $(TARGDIR)/swig/$(SWIG_PREFIX)-%.so: _obj/$(SWIG_PREFIX)-%.so
@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(pkgdir)/swig @test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(TARGDIR)/swig
cp $< "$@" cp $< "$@"
all: $(SWIG_SOS) all: $(SWIG_SOS)
SWIG_RPATH=-r $(pkgdir)/swig SWIG_RPATH=-r $(TARGDIR)/swig
endif endif
......
...@@ -10,6 +10,7 @@ GOFILES=\ ...@@ -10,6 +10,7 @@ GOFILES=\
main.go\ main.go\
make.go\ make.go\
parse.go\ parse.go\
path.go\
syslist.go\ syslist.go\
CLEANFILES+=syslist.go CLEANFILES+=syslist.go
......
...@@ -37,15 +37,15 @@ var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z ...@@ -37,15 +37,15 @@ var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z
var launchpad = regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`) var launchpad = regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`)
// download checks out or updates pkg from the remote server. // download checks out or updates pkg from the remote server.
func download(pkg string) (string, os.Error) { func download(pkg, srcDir string) os.Error {
if strings.Contains(pkg, "..") { if strings.Contains(pkg, "..") {
return "", os.ErrorString("invalid path (contains ..)") return os.ErrorString("invalid path (contains ..)")
} }
if m := bitbucket.FindStringSubmatch(pkg); m != nil { if m := bitbucket.FindStringSubmatch(pkg); m != nil {
if err := vcsCheckout(&hg, m[1], "http://"+m[1], m[1]); err != nil { if err := vcsCheckout(&hg, srcDir, m[1], "http://"+m[1], m[1]); err != nil {
return "", err return err
} }
return root + pkg, nil return nil
} }
if m := googlecode.FindStringSubmatch(pkg); m != nil { if m := googlecode.FindStringSubmatch(pkg); m != nil {
var v *vcs var v *vcs
...@@ -58,29 +58,29 @@ func download(pkg string) (string, os.Error) { ...@@ -58,29 +58,29 @@ func download(pkg string) (string, os.Error) {
// regexp only allows hg, svn to get through // regexp only allows hg, svn to get through
panic("missing case in download: " + pkg) panic("missing case in download: " + pkg)
} }
if err := vcsCheckout(v, m[1], "https://"+m[1], m[1]); err != nil { if err := vcsCheckout(v, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
return "", err return err
} }
return root + pkg, nil return nil
} }
if m := github.FindStringSubmatch(pkg); m != nil { if m := github.FindStringSubmatch(pkg); m != nil {
if strings.HasSuffix(m[1], ".git") { if strings.HasSuffix(m[1], ".git") {
return "", os.ErrorString("repository " + pkg + " should not have .git suffix") return os.ErrorString("repository " + pkg + " should not have .git suffix")
} }
if err := vcsCheckout(&git, m[1], "http://"+m[1]+".git", m[1]); err != nil { if err := vcsCheckout(&git, srcDir, m[1], "http://"+m[1]+".git", m[1]); err != nil {
return "", err return err
} }
return root + pkg, nil return nil
} }
if m := launchpad.FindStringSubmatch(pkg); m != nil { if m := launchpad.FindStringSubmatch(pkg); m != nil {
// Either lp.net/<project>[/<series>[/<path>]] // Either lp.net/<project>[/<series>[/<path>]]
// or lp.net/~<user or team>/<project>/<branch>[/<path>] // or lp.net/~<user or team>/<project>/<branch>[/<path>]
if err := vcsCheckout(&bzr, m[1], "https://"+m[1], m[1]); err != nil { if err := vcsCheckout(&bzr, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
return "", err return err
} }
return root + pkg, nil return nil
} }
return "", os.ErrorString("unknown repository: " + pkg) return os.ErrorString("unknown repository: " + pkg)
} }
// a vcs represents a version control system // a vcs represents a version control system
...@@ -172,8 +172,8 @@ func (v *vcs) updateRepo(dst string) os.Error { ...@@ -172,8 +172,8 @@ func (v *vcs) updateRepo(dst string) os.Error {
// exists and -u was specified on the command line) // exists and -u was specified on the command line)
// the repository at tag/branch "release". If there is no // the repository at tag/branch "release". If there is no
// such tag or branch, it falls back to the repository tip. // such tag or branch, it falls back to the repository tip.
func vcsCheckout(vcs *vcs, pkgprefix, repo, dashpath string) os.Error { func vcsCheckout(vcs *vcs, srcDir, pkgprefix, repo, dashpath string) os.Error {
dst := filepath.Join(root, filepath.FromSlash(pkgprefix)) dst := filepath.Join(srcDir, filepath.FromSlash(pkgprefix))
dir, err := os.Stat(filepath.Join(dst, vcs.metadir)) dir, err := os.Stat(filepath.Join(dst, vcs.metadir))
if err == nil && !dir.IsDirectory() { if err == nil && !dir.IsDirectory() {
return os.ErrorString("not a directory: " + dst) return os.ErrorString("not a directory: " + dst)
......
...@@ -150,6 +150,7 @@ func install(pkg, parent string) { ...@@ -150,6 +150,7 @@ func install(pkg, parent string) {
// Check whether package is local or remote. // Check whether package is local or remote.
// If remote, download or update it. // If remote, download or update it.
var dir string var dir string
proot := gopath[0] // default to GOROOT
local := false local := false
if strings.HasPrefix(pkg, "http://") { if strings.HasPrefix(pkg, "http://") {
fmt.Fprintf(os.Stderr, "%s: %s: 'http://' used in remote path, try '%s'\n", argv0, pkg, pkg[7:]) fmt.Fprintf(os.Stderr, "%s: %s: 'http://' used in remote path, try '%s'\n", argv0, pkg, pkg[7:])
...@@ -163,8 +164,9 @@ func install(pkg, parent string) { ...@@ -163,8 +164,9 @@ func install(pkg, parent string) {
dir = filepath.Join(root, filepath.FromSlash(pkg)) dir = filepath.Join(root, filepath.FromSlash(pkg))
local = true local = true
} else { } else {
var err os.Error proot = findPkgroot(pkg)
dir, err = download(pkg) err := download(pkg, proot.srcDir())
dir = filepath.Join(proot.srcDir(), pkg)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err) fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
errors = true errors = true
...@@ -196,7 +198,7 @@ func install(pkg, parent string) { ...@@ -196,7 +198,7 @@ func install(pkg, parent string) {
// Install this package. // Install this package.
if !errors { if !errors {
isCmd := dirInfo.pkgName == "main" isCmd := dirInfo.pkgName == "main"
if err := domake(dir, pkg, local, isCmd); err != nil { if err := domake(dir, pkg, proot, local, isCmd); err != nil {
fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err) fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err)
errors = true errors = true
} else if !local && *logPkgs { } else if !local && *logPkgs {
......
...@@ -18,7 +18,7 @@ import ( ...@@ -18,7 +18,7 @@ import (
// For non-local packages or packages without Makefiles, // For non-local packages or packages without Makefiles,
// domake generates a standard Makefile and passes it // domake generates a standard Makefile and passes it
// to make on standard input. // to make on standard input.
func domake(dir, pkg string, local, isCmd bool) (err os.Error) { func domake(dir, pkg string, root *pkgroot, local, isCmd bool) (err os.Error) {
needMakefile := true needMakefile := true
if local { if local {
_, err := os.Stat(dir + "/Makefile") _, err := os.Stat(dir + "/Makefile")
...@@ -29,7 +29,7 @@ func domake(dir, pkg string, local, isCmd bool) (err os.Error) { ...@@ -29,7 +29,7 @@ func domake(dir, pkg string, local, isCmd bool) (err os.Error) {
cmd := []string{"gomake"} cmd := []string{"gomake"}
var makefile []byte var makefile []byte
if needMakefile { if needMakefile {
if makefile, err = makeMakefile(dir, pkg, isCmd); err != nil { if makefile, err = makeMakefile(dir, pkg, root, isCmd); err != nil {
return err return err
} }
cmd = append(cmd, "-f-") cmd = append(cmd, "-f-")
...@@ -44,8 +44,12 @@ func domake(dir, pkg string, local, isCmd bool) (err os.Error) { ...@@ -44,8 +44,12 @@ func domake(dir, pkg string, local, isCmd bool) (err os.Error) {
// makeMakefile computes the standard Makefile for the directory dir // makeMakefile computes the standard Makefile for the directory dir
// installing as package pkg. It includes all *.go files in the directory // installing as package pkg. It includes all *.go files in the directory
// except those in package main and those ending in _test.go. // except those in package main and those ending in _test.go.
func makeMakefile(dir, pkg string, isCmd bool) ([]byte, os.Error) { func makeMakefile(dir, pkg string, root *pkgroot, isCmd bool) ([]byte, os.Error) {
if !safeName(pkg) {
return nil, os.ErrorString("unsafe name: " + pkg)
}
targ := pkg targ := pkg
targDir := root.pkgDir()
if isCmd { if isCmd {
// use the last part of the package name only // use the last part of the package name only
_, targ = filepath.Split(pkg) _, targ = filepath.Split(pkg)
...@@ -57,9 +61,7 @@ func makeMakefile(dir, pkg string, isCmd bool) ([]byte, os.Error) { ...@@ -57,9 +61,7 @@ func makeMakefile(dir, pkg string, isCmd bool) ([]byte, os.Error) {
} }
_, targ = filepath.Split(d) _, targ = filepath.Split(d)
} }
} targDir = root.binDir()
if !safeName(targ) {
return nil, os.ErrorString("unsafe name: " + pkg)
} }
dirInfo, err := scanDir(dir, isCmd) dirInfo, err := scanDir(dir, isCmd)
if err != nil { if err != nil {
...@@ -108,7 +110,7 @@ func makeMakefile(dir, pkg string, isCmd bool) ([]byte, os.Error) { ...@@ -108,7 +110,7 @@ func makeMakefile(dir, pkg string, isCmd bool) ([]byte, os.Error) {
} }
var buf bytes.Buffer var buf bytes.Buffer
md := makedata{targ, "pkg", goFiles, oFiles, cgoFiles, cgoOFiles} md := makedata{targ, targDir, "pkg", goFiles, oFiles, cgoFiles, cgoOFiles, imports}
if isCmd { if isCmd {
md.Type = "cmd" md.Type = "cmd"
} }
...@@ -121,7 +123,7 @@ func makeMakefile(dir, pkg string, isCmd bool) ([]byte, os.Error) { ...@@ -121,7 +123,7 @@ func makeMakefile(dir, pkg string, isCmd bool) ([]byte, os.Error) {
var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz") var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
func safeName(s string) bool { func safeName(s string) bool {
if len(s) == 0 { if s == "" {
return false return false
} }
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
...@@ -135,17 +137,20 @@ func safeName(s string) bool { ...@@ -135,17 +137,20 @@ func safeName(s string) bool {
// makedata is the data type for the makefileTemplate. // makedata is the data type for the makefileTemplate.
type makedata struct { type makedata struct {
Targ string // build target Targ string // build target
TargDir string // build target directory
Type string // build type: "pkg" or "cmd" Type string // build type: "pkg" or "cmd"
GoFiles []string // list of non-cgo .go files GoFiles []string // list of non-cgo .go files
OFiles []string // list of .$O files OFiles []string // list of .$O files
CgoFiles []string // list of cgo .go files CgoFiles []string // list of cgo .go files
CgoOFiles []string // list of cgo .o files, without extension CgoOFiles []string // list of cgo .o files, without extension
Imports []string // gc/ld import paths
} }
var makefileTemplate = template.MustParse(` var makefileTemplate = template.MustParse(`
include $(GOROOT)/src/Make.inc include $(GOROOT)/src/Make.inc
TARG={Targ} TARG={Targ}
TARGDIR={TargDir}
{.section GoFiles} {.section GoFiles}
GOFILES=\ GOFILES=\
...@@ -175,6 +180,9 @@ CGO_OFILES=\ ...@@ -175,6 +180,9 @@ CGO_OFILES=\
{.end} {.end}
{.end} {.end}
GCIMPORTS={.repeated section Imports}-I "{@}" {.end}
LDIMPORTS={.repeated section Imports}-L "{@}" {.end}
include $(GOROOT)/src/Make.{Type} include $(GOROOT)/src/Make.{Type}
`, `,
nil) nil)
...@@ -88,6 +88,9 @@ func scanDir(dir string, allowMain bool) (info *dirInfo, err os.Error) { ...@@ -88,6 +88,9 @@ func scanDir(dir string, allowMain bool) (info *dirInfo, err os.Error) {
if s == "main" && !allowMain { if s == "main" && !allowMain {
continue continue
} }
if s == "documentation" {
continue
}
if pkgName == "" { if pkgName == "" {
pkgName = s pkgName = s
} else if pkgName != s { } else if pkgName != s {
......
// 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 main
import (
"log"
"os"
"path/filepath"
"runtime"
)
var (
gopath []*pkgroot
imports []string
defaultRoot *pkgroot // default root for remote packages
)
// set up gopath: parse and validate GOROOT and GOPATH variables
func init() {
p, err := newPkgroot(root)
if err != nil {
log.Fatalf("Invalid GOROOT %q: %v", root, err)
}
p.goroot = true
gopath = []*pkgroot{p}
for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
if p == "" {
continue
}
r, err := newPkgroot(p)
if err != nil {
log.Printf("Invalid GOPATH %q: %v", p, err)
continue
}
gopath = append(gopath, r)
imports = append(imports, r.pkgDir())
// select first GOPATH entry as default
if defaultRoot == nil {
defaultRoot = r
}
}
// use GOROOT if no valid GOPATH specified
if defaultRoot == nil {
defaultRoot = gopath[0]
}
}
type pkgroot struct {
path string
goroot bool // TODO(adg): remove this once Go tree re-organized
}
func newPkgroot(p string) (*pkgroot, os.Error) {
if !filepath.IsAbs(p) {
return nil, os.NewError("must be absolute")
}
ep, err := filepath.EvalSymlinks(p)
if err != nil {
return nil, err
}
return &pkgroot{path: ep}, nil
}
func (r *pkgroot) srcDir() string {
if r.goroot {
return filepath.Join(r.path, "src", "pkg")
}
return filepath.Join(r.path, "src")
}
func (r *pkgroot) pkgDir() string {
goos, goarch := runtime.GOOS, runtime.GOARCH
if e := os.Getenv("GOOS"); e != "" {
goos = e
}
if e := os.Getenv("GOARCH"); e != "" {
goarch = e
}
return filepath.Join(r.path, "pkg", goos+"_"+goarch)
}
func (r *pkgroot) binDir() string {
return filepath.Join(r.path, "bin")
}
func (r *pkgroot) hasSrcDir(name string) bool {
fi, err := os.Stat(filepath.Join(r.srcDir(), name))
if err != nil {
return false
}
return fi.IsDirectory()
}
func (r *pkgroot) hasPkg(name string) bool {
fi, err := os.Stat(filepath.Join(r.pkgDir(), name+".a"))
if err != nil {
return false
}
return fi.IsRegular()
// TODO(adg): check object version is consistent
}
// findPkgroot searches each of the gopath roots
// for the source code for the given import path.
func findPkgroot(importPath string) *pkgroot {
for _, r := range gopath {
if r.hasSrcDir(importPath) {
return r
}
}
return defaultRoot
}
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