[uselistorder] Insert blank line, NFC
[oota-llvm.git] / tools / llvm-go / llvm-go.go
index 47f948150f056e91c66128303c245db58f852f16..ed79ca67b89d3743e1fbc4a18986b7f2c3722071 100644 (file)
@@ -24,12 +24,18 @@ import (
        "strings"
 )
 
+const (
+       linkmodeComponentLibs = "component-libs"
+       linkmodeDylib         = "dylib"
+)
+
 type pkg struct {
        llvmpath, pkgpath string
 }
 
 var packages = []pkg{
        {"bindings/go/llvm", "llvm.org/llvm/bindings/go/llvm"},
+       {"tools/llgo", "llvm.org/llgo"},
 }
 
 type compilerFlags struct {
@@ -45,7 +51,7 @@ var components = []string{
        "bitwriter",
        "codegen",
        "core",
-       "debuginfo",
+       "debuginfodwarf",
        "executionengine",
        "instrumentation",
        "interpreter",
@@ -65,11 +71,12 @@ var components = []string{
 func llvmConfig(args ...string) string {
        configpath := os.Getenv("LLVM_CONFIG")
        if configpath == "" {
-               // strip llvm-go, add llvm-config
-               configpath = os.Args[0][:len(os.Args[0])-7] + "llvm-config"
+               bin, _ := filepath.Split(os.Args[0])
+               configpath = filepath.Join(bin, "llvm-config")
        }
 
        cmd := exec.Command(configpath, args...)
+       cmd.Stderr = os.Stderr
        out, err := cmd.Output()
        if err != nil {
                panic(err.Error())
@@ -77,11 +84,21 @@ func llvmConfig(args ...string) string {
 
        outstr := string(out)
        outstr = strings.TrimSuffix(outstr, "\n")
-       return strings.Replace(outstr, "\n", " ", -1)
+       outstr = strings.Replace(outstr, "\n", " ", -1)
+       return outstr
 }
 
-func llvmFlags() compilerFlags {
-       ldflags := llvmConfig(append([]string{"--ldflags", "--libs", "--system-libs"}, components...)...)
+func llvmFlags(linkmode string) compilerFlags {
+       ldflags := llvmConfig("--ldflags")
+       switch linkmode {
+       case linkmodeComponentLibs:
+               ldflags += " " + llvmConfig(append([]string{"--libs"}, components...)...)
+       case linkmodeDylib:
+               ldflags += " -lLLVM"
+       default:
+               panic("invalid linkmode: " + linkmode)
+       }
+       ldflags += " " + llvmConfig("--system-libs")
        if runtime.GOOS != "darwin" {
                // OS X doesn't like -rpath with cgo. See:
                // https://code.google.com/p/go/issues/detail?id=7293
@@ -116,8 +133,8 @@ func printComponents() {
        fmt.Println(strings.Join(components, " "))
 }
 
-func printConfig() {
-       flags := llvmFlags()
+func printConfig(linkmode string) {
+       flags := llvmFlags(linkmode)
 
        fmt.Printf(`// +build !byollvm
 
@@ -136,7 +153,7 @@ type (run_build_sh int)
 `, flags.cpp, flags.cxx, flags.ld)
 }
 
-func runGoWithLLVMEnv(args []string, cc, cxx, cppflags, cxxflags, ldflags string) {
+func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags, linkmode string) {
        args = addTag(args, "byollvm")
 
        srcdir := llvmConfig("--src-root")
@@ -159,11 +176,13 @@ func runGoWithLLVMEnv(args []string, cc, cxx, cppflags, cxxflags, ldflags string
                }
        }
 
+       newpath := os.Getenv("PATH")
+
        newgopathlist := []string{tmpgopath}
        newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...)
        newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator))
 
-       flags := llvmFlags()
+       flags := llvmFlags(linkmode)
 
        newenv := []string{
                "CC=" + cc,
@@ -172,24 +191,31 @@ func runGoWithLLVMEnv(args []string, cc, cxx, cppflags, cxxflags, ldflags string
                "CGO_CXXFLAGS=" + flags.cxx + " " + cxxflags,
                "CGO_LDFLAGS=" + flags.ld + " " + ldflags,
                "GOPATH=" + newgopath,
+               "PATH=" + newpath,
        }
+       if llgo != "" {
+               newenv = append(newenv, "GCCGO="+llgo)
+       }
+
        for _, v := range os.Environ() {
                if !strings.HasPrefix(v, "CC=") &&
                        !strings.HasPrefix(v, "CXX=") &&
                        !strings.HasPrefix(v, "CGO_CPPFLAGS=") &&
                        !strings.HasPrefix(v, "CGO_CXXFLAGS=") &&
                        !strings.HasPrefix(v, "CGO_LDFLAGS=") &&
-                       !strings.HasPrefix(v, "GOPATH=") {
+                       !strings.HasPrefix(v, "GCCGO=") &&
+                       !strings.HasPrefix(v, "GOPATH=") &&
+                       !strings.HasPrefix(v, "PATH=") {
                        newenv = append(newenv, v)
                }
        }
 
-       gocmdpath, err := exec.LookPath("go")
+       gocmdpath, err := exec.LookPath(gocmd)
        if err != nil {
                panic(err.Error())
        }
 
-       proc, err := os.StartProcess(gocmdpath, append([]string{"go"}, args...),
+       proc, err := os.StartProcess(gocmdpath, append([]string{gocmd}, args...),
                &os.ProcAttr{
                        Env:   newenv,
                        Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
@@ -222,39 +248,46 @@ func main() {
        cppflags := os.Getenv("CGO_CPPFLAGS")
        cxxflags := os.Getenv("CGO_CXXFLAGS")
        ldflags := os.Getenv("CGO_LDFLAGS")
+       gocmd := "go"
+       llgo := ""
+       linkmode := linkmodeComponentLibs
+
+       flags := []struct {
+               name string
+               dest *string
+       }{
+               {"cc", &cc},
+               {"cxx", &cxx},
+               {"go", &gocmd},
+               {"llgo", &llgo},
+               {"cppflags", &cppflags},
+               {"ldflags", &ldflags},
+               {"linkmode", &linkmode},
+       }
 
        args := os.Args[1:]
-       DONE: for {
-               switch {
-               case len(args) == 0:
+LOOP:
+       for {
+               if len(args) == 0 {
                        usage()
-               case strings.HasPrefix(args[0], "cc="):
-                       cc = args[0][3:]
-                       args = args[1:]
-               case strings.HasPrefix(args[0], "cxx="):
-                       cxx = args[0][4:]
-                       args = args[1:]
-               case strings.HasPrefix(args[0], "cppflags="):
-                       cppflags = args[0][9:]
-                       args = args[1:]
-               case strings.HasPrefix(args[0], "cxxflags="):
-                       cxxflags = args[0][9:]
-                       args = args[1:]
-               case strings.HasPrefix(args[0], "ldflags="):
-                       ldflags = args[0][8:]
-                       args = args[1:]
-               default:
-                       break DONE
                }
+               for _, flag := range flags {
+                       if strings.HasPrefix(args[0], flag.name+"=") {
+                               *flag.dest = args[0][len(flag.name)+1:]
+                               args = args[1:]
+                               continue LOOP
+                       }
+               }
+               break
        }
 
        switch args[0] {
        case "build", "get", "install", "run", "test":
-               runGoWithLLVMEnv(args, cc, cxx, cppflags, cxxflags, ldflags)
+               runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags, linkmode)
        case "print-components":
                printComponents()
        case "print-config":
-               printConfig()
+               printConfig(linkmode)
        default:
                usage()
        }