// Copyright 2018 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 ( "os" "path/filepath" "runtime" ) // Copies of functions from src/cmd/go/internal/cfg/cfg.go for // finding the GOROOT. // Keep them in sync until support is moved to a common place, if ever. func findGOROOT() string { if env := os.Getenv("GOROOT"); env != "" { return filepath.Clean(env) } def := filepath.Clean(runtime.GOROOT()) if runtime.Compiler == "gccgo" { // gccgo has no real GOROOT, and it certainly doesn't // depend on the executable's location. return def } exe, err := os.Executable() if err == nil { exe, err = filepath.Abs(exe) if err == nil { if dir := filepath.Join(exe, "../.."); isGOROOT(dir) { // If def (runtime.GOROOT()) and dir are the same // directory, prefer the spelling used in def. if isSameDir(def, dir) { return def } return dir } exe, err = filepath.EvalSymlinks(exe) if err == nil { if dir := filepath.Join(exe, "../.."); isGOROOT(dir) { if isSameDir(def, dir) { return def } return dir } } } } return def } // isGOROOT reports whether path looks like a GOROOT. // // It does this by looking for the path/pkg/tool directory, // which is necessary for useful operation of the cmd/go tool, // and is not typically present in a GOPATH. func isGOROOT(path string) bool { stat, err := os.Stat(filepath.Join(path, "pkg", "tool")) if err != nil { return false } return stat.IsDir() } // isSameDir reports whether dir1 and dir2 are the same directory. func isSameDir(dir1, dir2 string) bool { if dir1 == dir2 { return true } info1, err1 := os.Stat(dir1) info2, err2 := os.Stat(dir2) return err1 == nil && err2 == nil && os.SameFile(info1, info2) }