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