mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Reinstate llvm-go to test the go bindings.
This partially reverts commit 102814b4d36ad004a2e37cd2a1e84bd2c3593d29.
This commit is contained in:
parent
e81ba0b0a3
commit
814e0e4df6
9
tools/llvm-go/CMakeLists.txt
Normal file
9
tools/llvm-go/CMakeLists.txt
Normal file
@ -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()
|
311
tools/llvm-go/llvm-go.go
Normal file
311
tools/llvm-go/llvm-go.go
Normal file
@ -0,0 +1,311 @@
|
||||
//===-- llvm-go.go - go tool wrapper for LLVM -----------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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"
|
||||
)
|
||||
|
||||
const (
|
||||
linkmodeComponentLibs = "component-libs"
|
||||
linkmodeDylib = "dylib"
|
||||
)
|
||||
|
||||
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",
|
||||
"coroutines",
|
||||
"debuginfodwarf",
|
||||
"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 == "" {
|
||||
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())
|
||||
}
|
||||
|
||||
outstr := string(out)
|
||||
outstr = strings.TrimSuffix(outstr, "\n")
|
||||
outstr = strings.Replace(outstr, "\n", " ", -1)
|
||||
return outstr
|
||||
}
|
||||
|
||||
func llvmFlags() compilerFlags {
|
||||
args := append([]string{"--ldflags", "--libs", "--system-libs"}, components...)
|
||||
ldflags := llvmConfig(args...)
|
||||
stdLibOption := ""
|
||||
if strings.Contains(llvmConfig("--cxxflags"), "-stdlib=libc++") {
|
||||
// If libc++ is used to build LLVM libraries, -stdlib=libc++ is
|
||||
// needed to resolve dependent symbols
|
||||
stdLibOption = "-stdlib=libc++"
|
||||
}
|
||||
if runtime.GOOS != "darwin" {
|
||||
// OS X doesn't like -rpath with cgo. See:
|
||||
// https://github.com/golang/go/issues/7293
|
||||
ldflags = "-Wl,-rpath," + llvmConfig("--libdir") + " " + ldflags
|
||||
}
|
||||
return compilerFlags{
|
||||
cpp: llvmConfig("--cppflags"),
|
||||
cxx: "-std=c++14" + " " + stdLibOption,
|
||||
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, gocmd, llgo, cppflags, cxxflags, ldflags string, packages []pkg) {
|
||||
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())
|
||||
}
|
||||
|
||||
abspath := p.llvmpath
|
||||
if !filepath.IsAbs(abspath) {
|
||||
abspath = filepath.Join(srcdir, abspath)
|
||||
}
|
||||
|
||||
err = os.Symlink(abspath, path)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
newpath := os.Getenv("PATH")
|
||||
|
||||
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,
|
||||
"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, "GCCGO=") &&
|
||||
!strings.HasPrefix(v, "GOPATH=") &&
|
||||
!strings.HasPrefix(v, "PATH=") {
|
||||
newenv = append(newenv, v)
|
||||
}
|
||||
}
|
||||
|
||||
gocmdpath, err := exec.LookPath(gocmd)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
proc, err := os.StartProcess(gocmdpath, append([]string{gocmd}, 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")
|
||||
gocmd := "go"
|
||||
llgo := ""
|
||||
packagesString := ""
|
||||
|
||||
flags := []struct {
|
||||
name string
|
||||
dest *string
|
||||
}{
|
||||
{"cc", &cc},
|
||||
{"cxx", &cxx},
|
||||
{"go", &gocmd},
|
||||
{"llgo", &llgo},
|
||||
{"cppflags", &cppflags},
|
||||
{"ldflags", &ldflags},
|
||||
{"packages", &packagesString},
|
||||
}
|
||||
|
||||
args := os.Args[1:]
|
||||
LOOP:
|
||||
for {
|
||||
if len(args) == 0 {
|
||||
usage()
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
packages := packages
|
||||
if packagesString != "" {
|
||||
for _, field := range strings.Fields(packagesString) {
|
||||
pos := strings.IndexRune(field, '=')
|
||||
if pos == -1 {
|
||||
fmt.Fprintf(os.Stderr, "invalid packages value %q, expected 'pkgpath=llvmpath [pkgpath=llvmpath ...]'\n", packagesString)
|
||||
os.Exit(1)
|
||||
}
|
||||
packages = append(packages, pkg{
|
||||
pkgpath: field[:pos],
|
||||
llvmpath: field[pos+1:],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
switch args[0] {
|
||||
case "build", "get", "install", "run", "test":
|
||||
runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags, packages)
|
||||
case "print-components":
|
||||
printComponents()
|
||||
case "print-config":
|
||||
printConfig()
|
||||
default:
|
||||
usage()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user