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
5package gccgoimporter
6
7import (
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.
17type 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.
29func (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.
68func (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.
92func (inst *GccgoInstallation) GetImporter(incpaths []string, initmap map[*types.Package]InitData) Importer {
93	return GetImporter(append(append(incpaths, inst.SearchPaths()...), "."), initmap)
94}
95