1*9880d681SAndroid Build Coastguard Worker//===-- llvm-go.go - go tool wrapper for LLVM -----------------------------===// 2*9880d681SAndroid Build Coastguard Worker// 3*9880d681SAndroid Build Coastguard Worker// The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker// 5*9880d681SAndroid Build Coastguard Worker// This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker// License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker// 8*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker// 10*9880d681SAndroid Build Coastguard Worker// This tool lets us build LLVM components within the tree by setting up a 11*9880d681SAndroid Build Coastguard Worker// $GOPATH that resembles a tree fetched in the normal way with "go get". 12*9880d681SAndroid Build Coastguard Worker// 13*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===// 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Workerpackage main 16*9880d681SAndroid Build Coastguard Worker 17*9880d681SAndroid Build Coastguard Workerimport ( 18*9880d681SAndroid Build Coastguard Worker "fmt" 19*9880d681SAndroid Build Coastguard Worker "io/ioutil" 20*9880d681SAndroid Build Coastguard Worker "os" 21*9880d681SAndroid Build Coastguard Worker "os/exec" 22*9880d681SAndroid Build Coastguard Worker "path/filepath" 23*9880d681SAndroid Build Coastguard Worker "runtime" 24*9880d681SAndroid Build Coastguard Worker "strings" 25*9880d681SAndroid Build Coastguard Worker) 26*9880d681SAndroid Build Coastguard Worker 27*9880d681SAndroid Build Coastguard Workerconst ( 28*9880d681SAndroid Build Coastguard Worker linkmodeComponentLibs = "component-libs" 29*9880d681SAndroid Build Coastguard Worker linkmodeDylib = "dylib" 30*9880d681SAndroid Build Coastguard Worker) 31*9880d681SAndroid Build Coastguard Worker 32*9880d681SAndroid Build Coastguard Workertype pkg struct { 33*9880d681SAndroid Build Coastguard Worker llvmpath, pkgpath string 34*9880d681SAndroid Build Coastguard Worker} 35*9880d681SAndroid Build Coastguard Worker 36*9880d681SAndroid Build Coastguard Workervar packages = []pkg{ 37*9880d681SAndroid Build Coastguard Worker {"bindings/go/llvm", "llvm.org/llvm/bindings/go/llvm"}, 38*9880d681SAndroid Build Coastguard Worker {"tools/llgo", "llvm.org/llgo"}, 39*9880d681SAndroid Build Coastguard Worker} 40*9880d681SAndroid Build Coastguard Worker 41*9880d681SAndroid Build Coastguard Workertype compilerFlags struct { 42*9880d681SAndroid Build Coastguard Worker cpp, cxx, ld string 43*9880d681SAndroid Build Coastguard Worker} 44*9880d681SAndroid Build Coastguard Worker 45*9880d681SAndroid Build Coastguard Workervar components = []string{ 46*9880d681SAndroid Build Coastguard Worker "all-targets", 47*9880d681SAndroid Build Coastguard Worker "analysis", 48*9880d681SAndroid Build Coastguard Worker "asmparser", 49*9880d681SAndroid Build Coastguard Worker "asmprinter", 50*9880d681SAndroid Build Coastguard Worker "bitreader", 51*9880d681SAndroid Build Coastguard Worker "bitwriter", 52*9880d681SAndroid Build Coastguard Worker "codegen", 53*9880d681SAndroid Build Coastguard Worker "core", 54*9880d681SAndroid Build Coastguard Worker "debuginfodwarf", 55*9880d681SAndroid Build Coastguard Worker "executionengine", 56*9880d681SAndroid Build Coastguard Worker "instrumentation", 57*9880d681SAndroid Build Coastguard Worker "interpreter", 58*9880d681SAndroid Build Coastguard Worker "ipo", 59*9880d681SAndroid Build Coastguard Worker "irreader", 60*9880d681SAndroid Build Coastguard Worker "linker", 61*9880d681SAndroid Build Coastguard Worker "mc", 62*9880d681SAndroid Build Coastguard Worker "mcjit", 63*9880d681SAndroid Build Coastguard Worker "objcarcopts", 64*9880d681SAndroid Build Coastguard Worker "option", 65*9880d681SAndroid Build Coastguard Worker "profiledata", 66*9880d681SAndroid Build Coastguard Worker "scalaropts", 67*9880d681SAndroid Build Coastguard Worker "support", 68*9880d681SAndroid Build Coastguard Worker "target", 69*9880d681SAndroid Build Coastguard Worker} 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard Workerfunc llvmConfig(args ...string) string { 72*9880d681SAndroid Build Coastguard Worker configpath := os.Getenv("LLVM_CONFIG") 73*9880d681SAndroid Build Coastguard Worker if configpath == "" { 74*9880d681SAndroid Build Coastguard Worker bin, _ := filepath.Split(os.Args[0]) 75*9880d681SAndroid Build Coastguard Worker configpath = filepath.Join(bin, "llvm-config") 76*9880d681SAndroid Build Coastguard Worker } 77*9880d681SAndroid Build Coastguard Worker 78*9880d681SAndroid Build Coastguard Worker cmd := exec.Command(configpath, args...) 79*9880d681SAndroid Build Coastguard Worker cmd.Stderr = os.Stderr 80*9880d681SAndroid Build Coastguard Worker out, err := cmd.Output() 81*9880d681SAndroid Build Coastguard Worker if err != nil { 82*9880d681SAndroid Build Coastguard Worker panic(err.Error()) 83*9880d681SAndroid Build Coastguard Worker } 84*9880d681SAndroid Build Coastguard Worker 85*9880d681SAndroid Build Coastguard Worker outstr := string(out) 86*9880d681SAndroid Build Coastguard Worker outstr = strings.TrimSuffix(outstr, "\n") 87*9880d681SAndroid Build Coastguard Worker outstr = strings.Replace(outstr, "\n", " ", -1) 88*9880d681SAndroid Build Coastguard Worker return outstr 89*9880d681SAndroid Build Coastguard Worker} 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Workerfunc llvmFlags() compilerFlags { 92*9880d681SAndroid Build Coastguard Worker args := append([]string{"--ldflags", "--libs", "--system-libs"}, components...) 93*9880d681SAndroid Build Coastguard Worker ldflags := llvmConfig(args...) 94*9880d681SAndroid Build Coastguard Worker if runtime.GOOS != "darwin" { 95*9880d681SAndroid Build Coastguard Worker // OS X doesn't like -rpath with cgo. See: 96*9880d681SAndroid Build Coastguard Worker // https://code.google.com/p/go/issues/detail?id=7293 97*9880d681SAndroid Build Coastguard Worker ldflags = "-Wl,-rpath," + llvmConfig("--libdir") + " " + ldflags 98*9880d681SAndroid Build Coastguard Worker } 99*9880d681SAndroid Build Coastguard Worker return compilerFlags{ 100*9880d681SAndroid Build Coastguard Worker cpp: llvmConfig("--cppflags"), 101*9880d681SAndroid Build Coastguard Worker cxx: "-std=c++11", 102*9880d681SAndroid Build Coastguard Worker ld: ldflags, 103*9880d681SAndroid Build Coastguard Worker } 104*9880d681SAndroid Build Coastguard Worker} 105*9880d681SAndroid Build Coastguard Worker 106*9880d681SAndroid Build Coastguard Workerfunc addTag(args []string, tag string) []string { 107*9880d681SAndroid Build Coastguard Worker args = append([]string{}, args...) 108*9880d681SAndroid Build Coastguard Worker addedTag := false 109*9880d681SAndroid Build Coastguard Worker for i, a := range args { 110*9880d681SAndroid Build Coastguard Worker if strings.HasPrefix(a, "-tags=") { 111*9880d681SAndroid Build Coastguard Worker args[i] = a + " " + tag 112*9880d681SAndroid Build Coastguard Worker addedTag = true 113*9880d681SAndroid Build Coastguard Worker } else if a == "-tags" && i+1 < len(args) { 114*9880d681SAndroid Build Coastguard Worker args[i+1] = args[i+1] + " " + tag 115*9880d681SAndroid Build Coastguard Worker addedTag = true 116*9880d681SAndroid Build Coastguard Worker } 117*9880d681SAndroid Build Coastguard Worker } 118*9880d681SAndroid Build Coastguard Worker if !addedTag { 119*9880d681SAndroid Build Coastguard Worker args = append([]string{args[0], "-tags", tag}, args[1:]...) 120*9880d681SAndroid Build Coastguard Worker } 121*9880d681SAndroid Build Coastguard Worker return args 122*9880d681SAndroid Build Coastguard Worker} 123*9880d681SAndroid Build Coastguard Worker 124*9880d681SAndroid Build Coastguard Workerfunc printComponents() { 125*9880d681SAndroid Build Coastguard Worker fmt.Println(strings.Join(components, " ")) 126*9880d681SAndroid Build Coastguard Worker} 127*9880d681SAndroid Build Coastguard Worker 128*9880d681SAndroid Build Coastguard Workerfunc printConfig() { 129*9880d681SAndroid Build Coastguard Worker flags := llvmFlags() 130*9880d681SAndroid Build Coastguard Worker 131*9880d681SAndroid Build Coastguard Worker fmt.Printf(`// +build !byollvm 132*9880d681SAndroid Build Coastguard Worker 133*9880d681SAndroid Build Coastguard Worker// This file is generated by llvm-go, do not edit. 134*9880d681SAndroid Build Coastguard Worker 135*9880d681SAndroid Build Coastguard Workerpackage llvm 136*9880d681SAndroid Build Coastguard Worker 137*9880d681SAndroid Build Coastguard Worker/* 138*9880d681SAndroid Build Coastguard Worker#cgo CPPFLAGS: %s 139*9880d681SAndroid Build Coastguard Worker#cgo CXXFLAGS: %s 140*9880d681SAndroid Build Coastguard Worker#cgo LDFLAGS: %s 141*9880d681SAndroid Build Coastguard Worker*/ 142*9880d681SAndroid Build Coastguard Workerimport "C" 143*9880d681SAndroid Build Coastguard Worker 144*9880d681SAndroid Build Coastguard Workertype (run_build_sh int) 145*9880d681SAndroid Build Coastguard Worker`, flags.cpp, flags.cxx, flags.ld) 146*9880d681SAndroid Build Coastguard Worker} 147*9880d681SAndroid Build Coastguard Worker 148*9880d681SAndroid Build Coastguard Workerfunc runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags string) { 149*9880d681SAndroid Build Coastguard Worker args = addTag(args, "byollvm") 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Worker srcdir := llvmConfig("--src-root") 152*9880d681SAndroid Build Coastguard Worker 153*9880d681SAndroid Build Coastguard Worker tmpgopath, err := ioutil.TempDir("", "gopath") 154*9880d681SAndroid Build Coastguard Worker if err != nil { 155*9880d681SAndroid Build Coastguard Worker panic(err.Error()) 156*9880d681SAndroid Build Coastguard Worker } 157*9880d681SAndroid Build Coastguard Worker 158*9880d681SAndroid Build Coastguard Worker for _, p := range packages { 159*9880d681SAndroid Build Coastguard Worker path := filepath.Join(tmpgopath, "src", p.pkgpath) 160*9880d681SAndroid Build Coastguard Worker err := os.MkdirAll(filepath.Dir(path), os.ModePerm) 161*9880d681SAndroid Build Coastguard Worker if err != nil { 162*9880d681SAndroid Build Coastguard Worker panic(err.Error()) 163*9880d681SAndroid Build Coastguard Worker } 164*9880d681SAndroid Build Coastguard Worker 165*9880d681SAndroid Build Coastguard Worker err = os.Symlink(filepath.Join(srcdir, p.llvmpath), path) 166*9880d681SAndroid Build Coastguard Worker if err != nil { 167*9880d681SAndroid Build Coastguard Worker panic(err.Error()) 168*9880d681SAndroid Build Coastguard Worker } 169*9880d681SAndroid Build Coastguard Worker } 170*9880d681SAndroid Build Coastguard Worker 171*9880d681SAndroid Build Coastguard Worker newpath := os.Getenv("PATH") 172*9880d681SAndroid Build Coastguard Worker 173*9880d681SAndroid Build Coastguard Worker newgopathlist := []string{tmpgopath} 174*9880d681SAndroid Build Coastguard Worker newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...) 175*9880d681SAndroid Build Coastguard Worker newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator)) 176*9880d681SAndroid Build Coastguard Worker 177*9880d681SAndroid Build Coastguard Worker flags := llvmFlags() 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker newenv := []string{ 180*9880d681SAndroid Build Coastguard Worker "CC=" + cc, 181*9880d681SAndroid Build Coastguard Worker "CXX=" + cxx, 182*9880d681SAndroid Build Coastguard Worker "CGO_CPPFLAGS=" + flags.cpp + " " + cppflags, 183*9880d681SAndroid Build Coastguard Worker "CGO_CXXFLAGS=" + flags.cxx + " " + cxxflags, 184*9880d681SAndroid Build Coastguard Worker "CGO_LDFLAGS=" + flags.ld + " " + ldflags, 185*9880d681SAndroid Build Coastguard Worker "GOPATH=" + newgopath, 186*9880d681SAndroid Build Coastguard Worker "PATH=" + newpath, 187*9880d681SAndroid Build Coastguard Worker } 188*9880d681SAndroid Build Coastguard Worker if llgo != "" { 189*9880d681SAndroid Build Coastguard Worker newenv = append(newenv, "GCCGO="+llgo) 190*9880d681SAndroid Build Coastguard Worker } 191*9880d681SAndroid Build Coastguard Worker 192*9880d681SAndroid Build Coastguard Worker for _, v := range os.Environ() { 193*9880d681SAndroid Build Coastguard Worker if !strings.HasPrefix(v, "CC=") && 194*9880d681SAndroid Build Coastguard Worker !strings.HasPrefix(v, "CXX=") && 195*9880d681SAndroid Build Coastguard Worker !strings.HasPrefix(v, "CGO_CPPFLAGS=") && 196*9880d681SAndroid Build Coastguard Worker !strings.HasPrefix(v, "CGO_CXXFLAGS=") && 197*9880d681SAndroid Build Coastguard Worker !strings.HasPrefix(v, "CGO_LDFLAGS=") && 198*9880d681SAndroid Build Coastguard Worker !strings.HasPrefix(v, "GCCGO=") && 199*9880d681SAndroid Build Coastguard Worker !strings.HasPrefix(v, "GOPATH=") && 200*9880d681SAndroid Build Coastguard Worker !strings.HasPrefix(v, "PATH=") { 201*9880d681SAndroid Build Coastguard Worker newenv = append(newenv, v) 202*9880d681SAndroid Build Coastguard Worker } 203*9880d681SAndroid Build Coastguard Worker } 204*9880d681SAndroid Build Coastguard Worker 205*9880d681SAndroid Build Coastguard Worker gocmdpath, err := exec.LookPath(gocmd) 206*9880d681SAndroid Build Coastguard Worker if err != nil { 207*9880d681SAndroid Build Coastguard Worker panic(err.Error()) 208*9880d681SAndroid Build Coastguard Worker } 209*9880d681SAndroid Build Coastguard Worker 210*9880d681SAndroid Build Coastguard Worker proc, err := os.StartProcess(gocmdpath, append([]string{gocmd}, args...), 211*9880d681SAndroid Build Coastguard Worker &os.ProcAttr{ 212*9880d681SAndroid Build Coastguard Worker Env: newenv, 213*9880d681SAndroid Build Coastguard Worker Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, 214*9880d681SAndroid Build Coastguard Worker }) 215*9880d681SAndroid Build Coastguard Worker if err != nil { 216*9880d681SAndroid Build Coastguard Worker panic(err.Error()) 217*9880d681SAndroid Build Coastguard Worker } 218*9880d681SAndroid Build Coastguard Worker ps, err := proc.Wait() 219*9880d681SAndroid Build Coastguard Worker if err != nil { 220*9880d681SAndroid Build Coastguard Worker panic(err.Error()) 221*9880d681SAndroid Build Coastguard Worker } 222*9880d681SAndroid Build Coastguard Worker 223*9880d681SAndroid Build Coastguard Worker os.RemoveAll(tmpgopath) 224*9880d681SAndroid Build Coastguard Worker 225*9880d681SAndroid Build Coastguard Worker if !ps.Success() { 226*9880d681SAndroid Build Coastguard Worker os.Exit(1) 227*9880d681SAndroid Build Coastguard Worker } 228*9880d681SAndroid Build Coastguard Worker} 229*9880d681SAndroid Build Coastguard Worker 230*9880d681SAndroid Build Coastguard Workerfunc usage() { 231*9880d681SAndroid Build Coastguard Worker fmt.Println(`Usage: llvm-go subcommand [flags] 232*9880d681SAndroid Build Coastguard Worker 233*9880d681SAndroid Build Coastguard WorkerAvailable subcommands: build get install run test print-components print-config`) 234*9880d681SAndroid Build Coastguard Worker os.Exit(0) 235*9880d681SAndroid Build Coastguard Worker} 236*9880d681SAndroid Build Coastguard Worker 237*9880d681SAndroid Build Coastguard Workerfunc main() { 238*9880d681SAndroid Build Coastguard Worker cc := os.Getenv("CC") 239*9880d681SAndroid Build Coastguard Worker cxx := os.Getenv("CXX") 240*9880d681SAndroid Build Coastguard Worker cppflags := os.Getenv("CGO_CPPFLAGS") 241*9880d681SAndroid Build Coastguard Worker cxxflags := os.Getenv("CGO_CXXFLAGS") 242*9880d681SAndroid Build Coastguard Worker ldflags := os.Getenv("CGO_LDFLAGS") 243*9880d681SAndroid Build Coastguard Worker gocmd := "go" 244*9880d681SAndroid Build Coastguard Worker llgo := "" 245*9880d681SAndroid Build Coastguard Worker 246*9880d681SAndroid Build Coastguard Worker flags := []struct { 247*9880d681SAndroid Build Coastguard Worker name string 248*9880d681SAndroid Build Coastguard Worker dest *string 249*9880d681SAndroid Build Coastguard Worker }{ 250*9880d681SAndroid Build Coastguard Worker {"cc", &cc}, 251*9880d681SAndroid Build Coastguard Worker {"cxx", &cxx}, 252*9880d681SAndroid Build Coastguard Worker {"go", &gocmd}, 253*9880d681SAndroid Build Coastguard Worker {"llgo", &llgo}, 254*9880d681SAndroid Build Coastguard Worker {"cppflags", &cppflags}, 255*9880d681SAndroid Build Coastguard Worker {"ldflags", &ldflags}, 256*9880d681SAndroid Build Coastguard Worker } 257*9880d681SAndroid Build Coastguard Worker 258*9880d681SAndroid Build Coastguard Worker args := os.Args[1:] 259*9880d681SAndroid Build Coastguard WorkerLOOP: 260*9880d681SAndroid Build Coastguard Worker for { 261*9880d681SAndroid Build Coastguard Worker if len(args) == 0 { 262*9880d681SAndroid Build Coastguard Worker usage() 263*9880d681SAndroid Build Coastguard Worker } 264*9880d681SAndroid Build Coastguard Worker for _, flag := range flags { 265*9880d681SAndroid Build Coastguard Worker if strings.HasPrefix(args[0], flag.name+"=") { 266*9880d681SAndroid Build Coastguard Worker *flag.dest = args[0][len(flag.name)+1:] 267*9880d681SAndroid Build Coastguard Worker args = args[1:] 268*9880d681SAndroid Build Coastguard Worker continue LOOP 269*9880d681SAndroid Build Coastguard Worker } 270*9880d681SAndroid Build Coastguard Worker } 271*9880d681SAndroid Build Coastguard Worker break 272*9880d681SAndroid Build Coastguard Worker } 273*9880d681SAndroid Build Coastguard Worker 274*9880d681SAndroid Build Coastguard Worker switch args[0] { 275*9880d681SAndroid Build Coastguard Worker case "build", "get", "install", "run", "test": 276*9880d681SAndroid Build Coastguard Worker runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags) 277*9880d681SAndroid Build Coastguard Worker case "print-components": 278*9880d681SAndroid Build Coastguard Worker printComponents() 279*9880d681SAndroid Build Coastguard Worker case "print-config": 280*9880d681SAndroid Build Coastguard Worker printConfig() 281*9880d681SAndroid Build Coastguard Worker default: 282*9880d681SAndroid Build Coastguard Worker usage() 283*9880d681SAndroid Build Coastguard Worker } 284*9880d681SAndroid Build Coastguard Worker} 285