...
Run Format

Source file src/go/build/gc.go

Documentation: go/build

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build gc
     6  
     7  package build
     8  
     9  import (
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"runtime"
    14  	"strings"
    15  	"sync"
    16  )
    17  
    18  // getToolDir returns the default value of ToolDir.
    19  func getToolDir() string {
    20  	return filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
    21  }
    22  
    23  // isStandardPackage is not used for the gc toolchain.
    24  // However, this function may be called when using `go build -compiler=gccgo`.
    25  func isStandardPackage(path string) bool {
    26  	return gccgoSearch.isStandard(path)
    27  }
    28  
    29  // gccgoSearch holds the gccgo search directories.
    30  type gccgoDirs struct {
    31  	once sync.Once
    32  	dirs []string
    33  }
    34  
    35  // gccgoSearch is used to check whether a gccgo package exists in the
    36  // standard library.
    37  var gccgoSearch gccgoDirs
    38  
    39  // init finds the gccgo search directories. If this fails it leaves dirs == nil.
    40  func (gd *gccgoDirs) init() {
    41  	gccgo := os.Getenv("GCCGO")
    42  	if gccgo == "" {
    43  		gccgo = "gccgo"
    44  	}
    45  	bin, err := exec.LookPath(gccgo)
    46  	if err != nil {
    47  		return
    48  	}
    49  
    50  	allDirs, err := exec.Command(bin, "-print-search-dirs").Output()
    51  	if err != nil {
    52  		return
    53  	}
    54  	versionB, err := exec.Command(bin, "-dumpversion").Output()
    55  	if err != nil {
    56  		return
    57  	}
    58  	version := strings.TrimSpace(string(versionB))
    59  	machineB, err := exec.Command(bin, "-dumpmachine").Output()
    60  	if err != nil {
    61  		return
    62  	}
    63  	machine := strings.TrimSpace(string(machineB))
    64  
    65  	dirsEntries := strings.Split(string(allDirs), "\n")
    66  	const prefix = "libraries: ="
    67  	var dirs []string
    68  	for _, dirEntry := range dirsEntries {
    69  		if strings.HasPrefix(dirEntry, prefix) {
    70  			dirs = filepath.SplitList(strings.TrimPrefix(dirEntry, prefix))
    71  			break
    72  		}
    73  	}
    74  	if len(dirs) == 0 {
    75  		return
    76  	}
    77  
    78  	var lastDirs []string
    79  	for _, dir := range dirs {
    80  		goDir := filepath.Join(dir, "go", version)
    81  		if fi, err := os.Stat(goDir); err == nil && fi.IsDir() {
    82  			gd.dirs = append(gd.dirs, goDir)
    83  			goDir = filepath.Join(goDir, machine)
    84  			if fi, err = os.Stat(goDir); err == nil && fi.IsDir() {
    85  				gd.dirs = append(gd.dirs, goDir)
    86  			}
    87  		}
    88  		if fi, err := os.Stat(dir); err == nil && fi.IsDir() {
    89  			lastDirs = append(lastDirs, dir)
    90  		}
    91  	}
    92  	gd.dirs = append(gd.dirs, lastDirs...)
    93  }
    94  
    95  // isStandard returns whether path is a standard library for gccgo.
    96  func (gd *gccgoDirs) isStandard(path string) bool {
    97  	// Quick check: if the first path component has a '.', it's not
    98  	// in the standard library. This skips most GOPATH directories.
    99  	i := strings.Index(path, "/")
   100  	if i < 0 {
   101  		i = len(path)
   102  	}
   103  	if strings.Contains(path[:i], ".") {
   104  		return false
   105  	}
   106  
   107  	if path == "unsafe" {
   108  		// Special case.
   109  		return true
   110  	}
   111  
   112  	gd.once.Do(gd.init)
   113  	if gd.dirs == nil {
   114  		// We couldn't find the gccgo search directories.
   115  		// Best guess, since the first component did not contain
   116  		// '.', is that this is a standard library package.
   117  		return true
   118  	}
   119  
   120  	for _, dir := range gd.dirs {
   121  		full := filepath.Join(dir, path)
   122  		pkgdir, pkg := filepath.Split(full)
   123  		for _, p := range [...]string{
   124  			full,
   125  			full + ".gox",
   126  			pkgdir + "lib" + pkg + ".so",
   127  			pkgdir + "lib" + pkg + ".a",
   128  			full + ".o",
   129  		} {
   130  			if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
   131  				return true
   132  			}
   133  		}
   134  	}
   135  
   136  	return false
   137  }
   138  

View as plain text