[llvm] e635e48 - Reinstate llvm-go to test the go bindings.

Eric Christopher via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 13 17:25:10 PST 2020


Author: Eric Christopher
Date: 2020-02-13T17:24:55-08:00
New Revision: e635e48020adbe1139f2de8d2db0d4875d6d75a8

URL: https://github.com/llvm/llvm-project/commit/e635e48020adbe1139f2de8d2db0d4875d6d75a8
DIFF: https://github.com/llvm/llvm-project/commit/e635e48020adbe1139f2de8d2db0d4875d6d75a8.diff

LOG: Reinstate llvm-go to test the go bindings.

This partially reverts commit 102814b4d36ad004a2e37cd2a1e84bd2c3593d29.

Added: 
    llvm/tools/llvm-go/CMakeLists.txt
    llvm/tools/llvm-go/llvm-go.go

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/tools/llvm-go/CMakeLists.txt b/llvm/tools/llvm-go/CMakeLists.txt
new file mode 100644
index 000000000000..20393f728f8f
--- /dev/null
+++ b/llvm/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/llvm/tools/llvm-go/llvm-go.go b/llvm/tools/llvm-go/llvm-go.go
new file mode 100644
index 000000000000..a0561dd5fd8d
--- /dev/null
+++ b/llvm/tools/llvm-go/llvm-go.go
@@ -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()
+	}
+}


        


More information about the llvm-commits mailing list