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
8package gccgoimporter
9
10import (
11	"bufio"
12	"go/types"
13	"os"
14	"os/exec"
15	"path/filepath"
16	"strings"
17)
18
19// Information about a specific installation of gccgo.
20type 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.
33func (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.
74func (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.
98func (inst *GccgoInstallation) GetImporter(incpaths []string, initmap map[*types.Package]InitData) Importer {
99	return GetImporter(append(append(incpaths, inst.SearchPaths()...), "."), initmap)
100}
101