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. 29// The given arguments are passed directly to the call of the driver. 30func (inst *GccgoInstallation) InitFromDriver(gccgoPath string, args ...string) (err error) { 31 argv := append([]string{"-###", "-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 strings.HasPrefix(line, "Target: "): 48 inst.TargetTriple = line[8:] 49 50 case line[0] == ' ': 51 args := strings.Fields(line) 52 for _, arg := range args[1:] { 53 if strings.HasPrefix(arg, "-L") { 54 inst.LibPaths = append(inst.LibPaths, arg[2:]) 55 } 56 } 57 } 58 } 59 60 argv = append([]string{"-dumpversion"}, args...) 61 stdout, err := exec.Command(gccgoPath, argv...).Output() 62 if err != nil { 63 return 64 } 65 inst.GccVersion = strings.TrimSpace(string(stdout)) 66 67 return 68} 69 70// Return the list of export search paths for this GccgoInstallation. 71func (inst *GccgoInstallation) SearchPaths() (paths []string) { 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. 95func (inst *GccgoInstallation) GetImporter(incpaths []string, initmap map[*types.Package]InitData) Importer { 96 return GetImporter(append(append(incpaths, inst.SearchPaths()...), "."), initmap) 97} 98