diff options
author | Stephen Hines <srhines@google.com> | 2014-12-01 14:51:49 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-12-02 16:08:10 -0800 |
commit | 37ed9c199ca639565f6ce88105f9e39e898d82d0 (patch) | |
tree | 8fb36d3910e3ee4c4e1b7422f4f017108efc52f5 /tools/llvm-go | |
parent | d2327b22152ced7bc46dc629fc908959e8a52d03 (diff) | |
download | external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.zip external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.gz external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.bz2 |
Update aosp/master LLVM for rebase to r222494.
Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d
Diffstat (limited to 'tools/llvm-go')
-rw-r--r-- | tools/llvm-go/CMakeLists.txt | 9 | ||||
-rw-r--r-- | tools/llvm-go/Makefile | 16 | ||||
-rw-r--r-- | tools/llvm-go/llvm-go.go | 261 |
3 files changed, 286 insertions, 0 deletions
diff --git a/tools/llvm-go/CMakeLists.txt b/tools/llvm-go/CMakeLists.txt new file mode 100644 index 0000000..20393f7 --- /dev/null +++ b/tools/llvm-go/CMakeLists.txt @@ -0,0 +1,9 @@ +if(LLVM_BINDINGS MATCHES "go") + set(binpath ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX}) + add_custom_command(OUTPUT ${binpath} + COMMAND ${GO_EXECUTABLE} build -o ${binpath} llvm-go.go + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/llvm-go.go + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Building Go executable llvm-go") + add_custom_target(llvm-go ALL DEPENDS ${binpath}) +endif() diff --git a/tools/llvm-go/Makefile b/tools/llvm-go/Makefile new file mode 100644 index 0000000..4465b2a --- /dev/null +++ b/tools/llvm-go/Makefile @@ -0,0 +1,16 @@ +##===- tools/llvm-go/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../.. +include $(LEVEL)/Makefile.common + +all:: $(ToolDir)/llvm-go$(EXEEXT) + +$(ToolDir)/llvm-go$(EXEEXT): $(PROJ_SRC_DIR)/llvm-go.go + $(GO) build -o $@ $< diff --git a/tools/llvm-go/llvm-go.go b/tools/llvm-go/llvm-go.go new file mode 100644 index 0000000..47f9481 --- /dev/null +++ b/tools/llvm-go/llvm-go.go @@ -0,0 +1,261 @@ +//===-- llvm-go.go - go tool wrapper for LLVM -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tool lets us build LLVM components within the tree by setting up a +// $GOPATH that resembles a tree fetched in the normal way with "go get". +// +//===----------------------------------------------------------------------===// + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" +) + +type pkg struct { + llvmpath, pkgpath string +} + +var packages = []pkg{ + {"bindings/go/llvm", "llvm.org/llvm/bindings/go/llvm"}, +} + +type compilerFlags struct { + cpp, cxx, ld string +} + +var components = []string{ + "all-targets", + "analysis", + "asmparser", + "asmprinter", + "bitreader", + "bitwriter", + "codegen", + "core", + "debuginfo", + "executionengine", + "instrumentation", + "interpreter", + "ipo", + "irreader", + "linker", + "mc", + "mcjit", + "objcarcopts", + "option", + "profiledata", + "scalaropts", + "support", + "target", +} + +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" + } + + cmd := exec.Command(configpath, args...) + out, err := cmd.Output() + if err != nil { + panic(err.Error()) + } + + outstr := string(out) + outstr = strings.TrimSuffix(outstr, "\n") + return strings.Replace(outstr, "\n", " ", -1) +} + +func llvmFlags() compilerFlags { + ldflags := llvmConfig(append([]string{"--ldflags", "--libs", "--system-libs"}, components...)...) + if runtime.GOOS != "darwin" { + // OS X doesn't like -rpath with cgo. See: + // https://code.google.com/p/go/issues/detail?id=7293 + ldflags = "-Wl,-rpath," + llvmConfig("--libdir") + " " + ldflags + } + return compilerFlags{ + cpp: llvmConfig("--cppflags"), + cxx: "-std=c++11", + ld: ldflags, + } +} + +func addTag(args []string, tag string) []string { + args = append([]string{}, args...) + addedTag := false + for i, a := range args { + if strings.HasPrefix(a, "-tags=") { + args[i] = a + " " + tag + addedTag = true + } else if a == "-tags" && i+1 < len(args) { + args[i+1] = args[i+1] + " " + tag + addedTag = true + } + } + if !addedTag { + args = append([]string{args[0], "-tags", tag}, args[1:]...) + } + return args +} + +func printComponents() { + fmt.Println(strings.Join(components, " ")) +} + +func printConfig() { + flags := llvmFlags() + + fmt.Printf(`// +build !byollvm + +// This file is generated by llvm-go, do not edit. + +package llvm + +/* +#cgo CPPFLAGS: %s +#cgo CXXFLAGS: %s +#cgo LDFLAGS: %s +*/ +import "C" + +type (run_build_sh int) +`, flags.cpp, flags.cxx, flags.ld) +} + +func runGoWithLLVMEnv(args []string, cc, cxx, cppflags, cxxflags, ldflags string) { + args = addTag(args, "byollvm") + + srcdir := llvmConfig("--src-root") + + tmpgopath, err := ioutil.TempDir("", "gopath") + if err != nil { + panic(err.Error()) + } + + for _, p := range packages { + path := filepath.Join(tmpgopath, "src", p.pkgpath) + err := os.MkdirAll(filepath.Dir(path), os.ModePerm) + if err != nil { + panic(err.Error()) + } + + err = os.Symlink(filepath.Join(srcdir, p.llvmpath), path) + if err != nil { + panic(err.Error()) + } + } + + newgopathlist := []string{tmpgopath} + newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...) + newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator)) + + flags := llvmFlags() + + newenv := []string{ + "CC=" + cc, + "CXX=" + cxx, + "CGO_CPPFLAGS=" + flags.cpp + " " + cppflags, + "CGO_CXXFLAGS=" + flags.cxx + " " + cxxflags, + "CGO_LDFLAGS=" + flags.ld + " " + ldflags, + "GOPATH=" + newgopath, + } + 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=") { + newenv = append(newenv, v) + } + } + + gocmdpath, err := exec.LookPath("go") + if err != nil { + panic(err.Error()) + } + + proc, err := os.StartProcess(gocmdpath, append([]string{"go"}, args...), + &os.ProcAttr{ + Env: newenv, + Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, + }) + if err != nil { + panic(err.Error()) + } + ps, err := proc.Wait() + if err != nil { + panic(err.Error()) + } + + os.RemoveAll(tmpgopath) + + if !ps.Success() { + os.Exit(1) + } +} + +func usage() { + fmt.Println(`Usage: llvm-go subcommand [flags] + +Available subcommands: build get install run test print-components print-config`) + os.Exit(0) +} + +func main() { + cc := os.Getenv("CC") + cxx := os.Getenv("CXX") + cppflags := os.Getenv("CGO_CPPFLAGS") + cxxflags := os.Getenv("CGO_CXXFLAGS") + ldflags := os.Getenv("CGO_LDFLAGS") + + args := os.Args[1:] + DONE: for { + switch { + case 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 + } + } + + switch args[0] { + case "build", "get", "install", "run", "test": + runGoWithLLVMEnv(args, cc, cxx, cppflags, cxxflags, ldflags) + case "print-components": + printComponents() + case "print-config": + printConfig() + default: + usage() + } +} |