github.com/v2fly/tools@v0.100.0/go/internal/gccgoimporter/gccgoinstallation.go (about)

     1  // Copyright 2013 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  // Except for this comment, this file is a verbatim copy of the file
     6  // with the same name in $GOROOT/src/go/internal/gccgoimporter.
     7  
     8  package gccgoimporter
     9  
    10  import (
    11  	"bufio"
    12  	"go/types"
    13  	exec "golang.org/x/sys/execabs"
    14  	"os"
    15  	"path/filepath"
    16  	"strings"
    17  )
    18  
    19  // Information about a specific installation of gccgo.
    20  type GccgoInstallation struct {
    21  	// Version of gcc (e.g. 4.8.0).
    22  	GccVersion string
    23  
    24  	// Target triple (e.g. x86_64-unknown-linux-gnu).
    25  	TargetTriple string
    26  
    27  	// Built-in library paths used by this installation.
    28  	LibPaths []string
    29  }
    30  
    31  // Ask the driver at the given path for information for this GccgoInstallation.
    32  // The given arguments are passed directly to the call of the driver.
    33  func (inst *GccgoInstallation) InitFromDriver(gccgoPath string, args ...string) (err error) {
    34  	argv := append([]string{"-###", "-S", "-x", "go", "-"}, args...)
    35  	cmd := exec.Command(gccgoPath, argv...)
    36  	stderr, err := cmd.StderrPipe()
    37  	if err != nil {
    38  		return
    39  	}
    40  
    41  	err = cmd.Start()
    42  	if err != nil {
    43  		return
    44  	}
    45  
    46  	scanner := bufio.NewScanner(stderr)
    47  	for scanner.Scan() {
    48  		line := scanner.Text()
    49  		switch {
    50  		case strings.HasPrefix(line, "Target: "):
    51  			inst.TargetTriple = line[8:]
    52  
    53  		case line[0] == ' ':
    54  			args := strings.Fields(line)
    55  			for _, arg := range args[1:] {
    56  				if strings.HasPrefix(arg, "-L") {
    57  					inst.LibPaths = append(inst.LibPaths, arg[2:])
    58  				}
    59  			}
    60  		}
    61  	}
    62  
    63  	argv = append([]string{"-dumpversion"}, args...)
    64  	stdout, err := exec.Command(gccgoPath, argv...).Output()
    65  	if err != nil {
    66  		return
    67  	}
    68  	inst.GccVersion = strings.TrimSpace(string(stdout))
    69  
    70  	return
    71  }
    72  
    73  // Return the list of export search paths for this GccgoInstallation.
    74  func (inst *GccgoInstallation) SearchPaths() (paths []string) {
    75  	for _, lpath := range inst.LibPaths {
    76  		spath := filepath.Join(lpath, "go", inst.GccVersion)
    77  		fi, err := os.Stat(spath)
    78  		if err != nil || !fi.IsDir() {
    79  			continue
    80  		}
    81  		paths = append(paths, spath)
    82  
    83  		spath = filepath.Join(spath, inst.TargetTriple)
    84  		fi, err = os.Stat(spath)
    85  		if err != nil || !fi.IsDir() {
    86  			continue
    87  		}
    88  		paths = append(paths, spath)
    89  	}
    90  
    91  	paths = append(paths, inst.LibPaths...)
    92  
    93  	return
    94  }
    95  
    96  // Return an importer that searches incpaths followed by the gcc installation's
    97  // built-in search paths and the current directory.
    98  func (inst *GccgoInstallation) GetImporter(incpaths []string, initmap map[*types.Package]InitData) Importer {
    99  	return GetImporter(append(append(incpaths, inst.SearchPaths()...), "."), initmap)
   100  }