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 linkmodeComponentLibs = "component-libs"
29 linkmodeDylib = "dylib"
33 llvmpath, pkgpath string
37 {"bindings/go/llvm", "llvm.org/llvm/bindings/go/llvm"},
38 {"tools/llgo", "llvm.org/llgo"},
41 type compilerFlags struct {
45 var components = []string{
71 func llvmConfig(args ...string) string {
72 configpath := os.Getenv("LLVM_CONFIG")
74 bin, _ := filepath.Split(os.Args[0])
75 configpath = filepath.Join(bin, "llvm-config")
78 cmd := exec.Command(configpath, args...)
79 cmd.Stderr = os.Stderr
80 out, err := cmd.Output()
86 outstr = strings.TrimSuffix(outstr, "\n")
87 outstr = strings.Replace(outstr, "\n", " ", -1)
91 func llvmFlags() compilerFlags {
92 ldflags := llvmConfig("--ldflags", "--libs", "--system-libs")
93 if runtime.GOOS != "darwin" {
94 // OS X doesn't like -rpath with cgo. See:
95 // https://code.google.com/p/go/issues/detail?id=7293
96 ldflags = "-Wl,-rpath," + llvmConfig("--libdir") + " " + ldflags
99 cpp: llvmConfig("--cppflags"),
105 func addTag(args []string, tag string) []string {
106 args = append([]string{}, args...)
108 for i, a := range args {
109 if strings.HasPrefix(a, "-tags=") {
110 args[i] = a + " " + tag
112 } else if a == "-tags" && i+1 < len(args) {
113 args[i+1] = args[i+1] + " " + tag
118 args = append([]string{args[0], "-tags", tag}, args[1:]...)
123 func printComponents() {
124 fmt.Println(strings.Join(components, " "))
130 fmt.Printf(`// +build !byollvm
132 // This file is generated by llvm-go, do not edit.
143 type (run_build_sh int)
144 `, flags.cpp, flags.cxx, flags.ld)
147 func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags string) {
148 args = addTag(args, "byollvm")
150 srcdir := llvmConfig("--src-root")
152 tmpgopath, err := ioutil.TempDir("", "gopath")
157 for _, p := range packages {
158 path := filepath.Join(tmpgopath, "src", p.pkgpath)
159 err := os.MkdirAll(filepath.Dir(path), os.ModePerm)
164 err = os.Symlink(filepath.Join(srcdir, p.llvmpath), path)
170 newpath := os.Getenv("PATH")
172 newgopathlist := []string{tmpgopath}
173 newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...)
174 newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator))
181 "CGO_CPPFLAGS=" + flags.cpp + " " + cppflags,
182 "CGO_CXXFLAGS=" + flags.cxx + " " + cxxflags,
183 "CGO_LDFLAGS=" + flags.ld + " " + ldflags,
184 "GOPATH=" + newgopath,
188 newenv = append(newenv, "GCCGO="+llgo)
191 for _, v := range os.Environ() {
192 if !strings.HasPrefix(v, "CC=") &&
193 !strings.HasPrefix(v, "CXX=") &&
194 !strings.HasPrefix(v, "CGO_CPPFLAGS=") &&
195 !strings.HasPrefix(v, "CGO_CXXFLAGS=") &&
196 !strings.HasPrefix(v, "CGO_LDFLAGS=") &&
197 !strings.HasPrefix(v, "GCCGO=") &&
198 !strings.HasPrefix(v, "GOPATH=") &&
199 !strings.HasPrefix(v, "PATH=") {
200 newenv = append(newenv, v)
204 gocmdpath, err := exec.LookPath(gocmd)
209 proc, err := os.StartProcess(gocmdpath, append([]string{gocmd}, args...),
212 Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
217 ps, err := proc.Wait()
222 os.RemoveAll(tmpgopath)
230 fmt.Println(`Usage: llvm-go subcommand [flags]
232 Available subcommands: build get install run test print-components print-config`)
237 cc := os.Getenv("CC")
238 cxx := os.Getenv("CXX")
239 cppflags := os.Getenv("CGO_CPPFLAGS")
240 cxxflags := os.Getenv("CGO_CXXFLAGS")
241 ldflags := os.Getenv("CGO_LDFLAGS")
253 {"cppflags", &cppflags},
254 {"ldflags", &ldflags},
263 for _, flag := range flags {
264 if strings.HasPrefix(args[0], flag.name+"=") {
265 *flag.dest = args[0][len(flag.name)+1:]
274 case "build", "get", "install", "run", "test":
275 runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags)
276 case "print-components":