1 //===-- llvm-go.go - go tool wrapper for LLVM -----------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This tool lets us build LLVM components within the tree by setting up a
11 // $GOPATH that resembles a tree fetched in the normal way with "go get".
13 //===----------------------------------------------------------------------===//
28 llvmpath, pkgpath string
32 {"bindings/go/llvm", "llvm.org/llvm/bindings/go/llvm"},
33 {"tools/llgo", "llvm.org/llgo"},
36 type compilerFlags struct {
40 var components = []string{
66 func llvmConfig(args ...string) string {
67 configpath := os.Getenv("LLVM_CONFIG")
69 // strip llvm-go, add llvm-config
70 configpath = os.Args[0][:len(os.Args[0])-7] + "llvm-config"
73 cmd := exec.Command(configpath, args...)
74 out, err := cmd.Output()
80 outstr = strings.TrimSuffix(outstr, "\n")
81 return strings.Replace(outstr, "\n", " ", -1)
84 func llvmFlags() compilerFlags {
85 ldflags := llvmConfig(append([]string{"--ldflags", "--libs", "--system-libs"}, components...)...)
86 if runtime.GOOS != "darwin" {
87 // OS X doesn't like -rpath with cgo. See:
88 // https://code.google.com/p/go/issues/detail?id=7293
89 ldflags = "-Wl,-rpath," + llvmConfig("--libdir") + " " + ldflags
92 cpp: llvmConfig("--cppflags"),
98 func addTag(args []string, tag string) []string {
99 args = append([]string{}, args...)
101 for i, a := range args {
102 if strings.HasPrefix(a, "-tags=") {
103 args[i] = a + " " + tag
105 } else if a == "-tags" && i+1 < len(args) {
106 args[i+1] = args[i+1] + " " + tag
111 args = append([]string{args[0], "-tags", tag}, args[1:]...)
116 func printComponents() {
117 fmt.Println(strings.Join(components, " "))
123 fmt.Printf(`// +build !byollvm
125 // This file is generated by llvm-go, do not edit.
136 type (run_build_sh int)
137 `, flags.cpp, flags.cxx, flags.ld)
140 func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags string) {
141 args = addTag(args, "byollvm")
143 srcdir := llvmConfig("--src-root")
145 tmpgopath, err := ioutil.TempDir("", "gopath")
150 for _, p := range packages {
151 path := filepath.Join(tmpgopath, "src", p.pkgpath)
152 err := os.MkdirAll(filepath.Dir(path), os.ModePerm)
157 err = os.Symlink(filepath.Join(srcdir, p.llvmpath), path)
163 newpath := os.Getenv("PATH")
166 bindir := filepath.Join(tmpgopath, "bin")
168 err = os.MkdirAll(bindir, os.ModePerm)
173 err = os.Symlink(llgo, filepath.Join(bindir, "gccgo"))
178 newpathlist := []string{bindir}
179 newpathlist = append(newpathlist, filepath.SplitList(newpath)...)
180 newpath = strings.Join(newpathlist, string(filepath.ListSeparator))
182 args = append([]string{args[0], "-compiler", "gccgo"}, args[1:]...)
185 newgopathlist := []string{tmpgopath}
186 newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...)
187 newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator))
194 "CGO_CPPFLAGS=" + flags.cpp + " " + cppflags,
195 "CGO_CXXFLAGS=" + flags.cxx + " " + cxxflags,
196 "CGO_LDFLAGS=" + flags.ld + " " + ldflags,
197 "GOPATH=" + newgopath,
200 for _, v := range os.Environ() {
201 if !strings.HasPrefix(v, "CC=") &&
202 !strings.HasPrefix(v, "CXX=") &&
203 !strings.HasPrefix(v, "CGO_CPPFLAGS=") &&
204 !strings.HasPrefix(v, "CGO_CXXFLAGS=") &&
205 !strings.HasPrefix(v, "CGO_LDFLAGS=") &&
206 !strings.HasPrefix(v, "GOPATH=") &&
207 !strings.HasPrefix(v, "PATH=") {
208 newenv = append(newenv, v)
212 gocmdpath, err := exec.LookPath(gocmd)
217 proc, err := os.StartProcess(gocmdpath, append([]string{gocmd}, args...),
220 Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
225 ps, err := proc.Wait()
230 os.RemoveAll(tmpgopath)
238 fmt.Println(`Usage: llvm-go subcommand [flags]
240 Available subcommands: build get install run test print-components print-config`)
245 cc := os.Getenv("CC")
246 cxx := os.Getenv("CXX")
247 cppflags := os.Getenv("CGO_CPPFLAGS")
248 cxxflags := os.Getenv("CGO_CXXFLAGS")
249 ldflags := os.Getenv("CGO_LDFLAGS")
258 case strings.HasPrefix(args[0], "cc="):
261 case strings.HasPrefix(args[0], "cxx="):
264 case strings.HasPrefix(args[0], "go="):
267 case strings.HasPrefix(args[0], "llgo="):
270 case strings.HasPrefix(args[0], "cppflags="):
271 cppflags = args[0][9:]
273 case strings.HasPrefix(args[0], "cxxflags="):
274 cxxflags = args[0][9:]
276 case strings.HasPrefix(args[0], "ldflags="):
277 ldflags = args[0][8:]
285 case "build", "get", "install", "run", "test":
286 runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags)
287 case "print-components":