gccgoinstallation.mx raw

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