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