[llvm] r220462 - Add llvm-go tool.

Peter Collingbourne peter at pcc.me.uk
Wed Oct 22 19:33:23 PDT 2014


Author: pcc
Date: Wed Oct 22 21:33:23 2014
New Revision: 220462

URL: http://llvm.org/viewvc/llvm-project?rev=220462&view=rev
Log:
Add llvm-go tool.

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".

It is intended that components such as the Go frontend will be built in-tree
using this tool.

Differential Revision: http://reviews.llvm.org/D5902

Added:
    llvm/trunk/tools/llvm-go/
    llvm/trunk/tools/llvm-go/CMakeLists.txt
    llvm/trunk/tools/llvm-go/Makefile
    llvm/trunk/tools/llvm-go/llvm-go.go
Modified:
    llvm/trunk/bindings/go/build.sh
    llvm/trunk/cmake/config-ix.cmake
    llvm/trunk/test/Bindings/Go/go.test
    llvm/trunk/test/CMakeLists.txt
    llvm/trunk/test/lit.cfg
    llvm/trunk/tools/CMakeLists.txt
    llvm/trunk/tools/Makefile

Modified: llvm/trunk/bindings/go/build.sh
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/bindings/go/build.sh?rev=220462&r1=220461&r2=220462&view=diff
==============================================================================
--- llvm/trunk/bindings/go/build.sh (original)
+++ llvm/trunk/bindings/go/build.sh Wed Oct 22 21:33:23 2014
@@ -1,36 +1,5 @@
 #!/bin/sh -xe
 
-llvm_components="\
-all-targets \
-analysis \
-asmparser \
-asmprinter \
-bitreader \
-bitwriter \
-codegen \
-core \
-debuginfo \
-executionengine \
-instrumentation \
-interpreter \
-ipo \
-irreader \
-linker \
-mc \
-mcjit \
-objcarcopts \
-option \
-profiledata \
-scalaropts \
-support \
-target \
-"
-
-if [ "$1" = "--print-components" ] ; then
-  echo $llvm_components
-  exit 0
-fi
-
 gollvmdir=$(dirname "$0")/llvm
 
 workdir=$gollvmdir/workdir
@@ -41,12 +10,14 @@ mkdir -p $llvm_builddir
 
 cmake_flags="../../../../.. $@"
 llvm_config="$llvm_builddir/bin/llvm-config"
+llvm_go="$llvm_builddir/bin/llvm-go"
 
 if test -n "`which ninja`" ; then
   # If Ninja is available, we can speed up the build by building only the
   # required subset of LLVM.
   (cd $llvm_builddir && cmake -G Ninja $cmake_flags)
-  ninja -C $llvm_builddir llvm-config
+  ninja -C $llvm_builddir llvm-config llvm-go
+  llvm_components="$($llvm_go print-components)"
   llvm_buildtargets="$($llvm_config --libs $llvm_components | sed -e 's/-l//g')"
   ninja -C $llvm_builddir $llvm_buildtargets FileCheck
 else
@@ -54,14 +25,7 @@ else
   make -C $llvm_builddir -j4
 fi
 
+$llvm_go print-config > $gollvmdir/llvm_config.go
+
 llvm_version="$($llvm_config --version)"
-llvm_cflags="$($llvm_config --cppflags)"
-llvm_ldflags="$($llvm_config --ldflags) $($llvm_config --libs $llvm_components) $($llvm_config --system-libs)"
-if [ $(uname) != "Darwin" ]; then
-  # OS X doesn't like -rpath with cgo. See:
-  # https://code.google.com/p/go/issues/detail?id=7293
-  llvm_ldflags="-Wl,-rpath,$($llvm_config --libdir) $llvm_ldflags"
-fi
-sed -e "s#@LLVM_CFLAGS@#$llvm_cflags#g; s#@LLVM_LDFLAGS@#$llvm_ldflags#g" $gollvmdir/llvm_config.go.in > \
-  $gollvmdir/llvm_config.go
 printf "package llvm\n\nconst Version = \"%s\"\n" "$llvm_version" > $gollvmdir/version.go

Modified: llvm/trunk/cmake/config-ix.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/config-ix.cmake?rev=220462&r1=220461&r2=220462&view=diff
==============================================================================
--- llvm/trunk/cmake/config-ix.cmake (original)
+++ llvm/trunk/cmake/config-ix.cmake Wed Oct 22 21:33:23 2014
@@ -493,16 +493,20 @@ else()
 endif()
 
 set(LLVM_BINDINGS "")
-find_program(GO_EXECUTABLE NAMES go DOC "go executable")
-if(GO_EXECUTABLE STREQUAL "GO_EXECUTABLE-NOTFOUND")
+if(WIN32)
   message(STATUS "Go bindings disabled.")
 else()
-  execute_process(COMMAND ${GO_EXECUTABLE} run ${CMAKE_SOURCE_DIR}/bindings/go/conftest.go
-                  RESULT_VARIABLE GO_CONFTEST)
-  if(GO_CONFTEST STREQUAL "0")
-    set(LLVM_BINDINGS "${LLVM_BINDINGS} go")
-    message(STATUS "Go bindings enabled.")
+  find_program(GO_EXECUTABLE NAMES go DOC "go executable")
+  if(GO_EXECUTABLE STREQUAL "GO_EXECUTABLE-NOTFOUND")
+    message(STATUS "Go bindings disabled.")
   else()
-    message(STATUS "Go bindings disabled, need at least Go 1.2.")
+    execute_process(COMMAND ${GO_EXECUTABLE} run ${CMAKE_SOURCE_DIR}/bindings/go/conftest.go
+                    RESULT_VARIABLE GO_CONFTEST)
+    if(GO_CONFTEST STREQUAL "0")
+      set(LLVM_BINDINGS "${LLVM_BINDINGS} go")
+      message(STATUS "Go bindings enabled.")
+    else()
+      message(STATUS "Go bindings disabled, need at least Go 1.2.")
+    endif()
   endif()
 endif()

Modified: llvm/trunk/test/Bindings/Go/go.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bindings/Go/go.test?rev=220462&r1=220461&r2=220462&view=diff
==============================================================================
--- llvm/trunk/test/Bindings/Go/go.test (original)
+++ llvm/trunk/test/Bindings/Go/go.test Wed Oct 22 21:33:23 2014
@@ -1,8 +1,3 @@
-; RUN: cd %S/../../../bindings/go/llvm && \
-; RUN: env CGO_CPPFLAGS="$(llvm-config --cppflags)" \
-; RUN:     CGO_CXXFLAGS=-std=c++11 \
-; RUN:     CGO_LDFLAGS="$(llvm-config --ldflags --libs --system-libs \
-; RUN:                                $(../build.sh --print-components)) $CGO_LDFLAGS" \
-; RUN:     %go test -tags byollvm .
+; RUN: llvm-go test llvm.org/llvm/bindings/go/llvm
 
 ; REQUIRES: shell

Modified: llvm/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CMakeLists.txt?rev=220462&r1=220461&r2=220462&view=diff
==============================================================================
--- llvm/trunk/test/CMakeLists.txt (original)
+++ llvm/trunk/test/CMakeLists.txt Wed Oct 22 21:33:23 2014
@@ -30,8 +30,9 @@ set(LLVM_TEST_DEPENDS
           llvm-cov
           llvm-diff
           llvm-dis
-          llvm-extract
           llvm-dwarfdump
+          llvm-extract
+          llvm-go
           llvm-link
           llvm-lto
           llvm-mc

Modified: llvm/trunk/test/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/lit.cfg?rev=220462&r1=220461&r2=220462&view=diff
==============================================================================
--- llvm/trunk/test/lit.cfg (original)
+++ llvm/trunk/test/lit.cfg Wed Oct 22 21:33:23 2014
@@ -200,6 +200,7 @@ for pattern in [r"\bbugpoint\b(?!-)",
                 r"\bllvm-dis\b",
                 r"\bllvm-dwarfdump\b",
                 r"\bllvm-extract\b",
+                r"\bllvm-go\b",
                 r"\bllvm-link\b",
                 r"\bllvm-lto\b",
                 r"\bllvm-mc\b",

Modified: llvm/trunk/tools/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/CMakeLists.txt?rev=220462&r1=220461&r2=220462&view=diff
==============================================================================
--- llvm/trunk/tools/CMakeLists.txt (original)
+++ llvm/trunk/tools/CMakeLists.txt Wed Oct 22 21:33:23 2014
@@ -52,6 +52,8 @@ add_llvm_tool_subdirectory(llvm-c-test)
 add_llvm_tool_subdirectory(obj2yaml)
 add_llvm_tool_subdirectory(yaml2obj)
 
+add_llvm_tool_subdirectory(llvm-go)
+
 if(NOT CYGWIN AND LLVM_ENABLE_PIC)
   add_llvm_tool_subdirectory(lto)
   add_llvm_tool_subdirectory(llvm-lto)

Modified: llvm/trunk/tools/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=220462&r1=220461&r2=220462&view=diff
==============================================================================
--- llvm/trunk/tools/Makefile (original)
+++ llvm/trunk/tools/Makefile Wed Oct 22 21:33:23 2014
@@ -74,4 +74,8 @@ ifneq ($(ENABLE_SHARED),1)
   endif
 endif
 
+ifneq (,$(filter go,$(BINDINGS_TO_BUILD)))
+  PARALLEL_DIRS += llvm-go
+endif
+
 include $(LEVEL)/Makefile.common

Added: llvm/trunk/tools/llvm-go/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-go/CMakeLists.txt?rev=220462&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-go/CMakeLists.txt (added)
+++ llvm/trunk/tools/llvm-go/CMakeLists.txt Wed Oct 22 21:33:23 2014
@@ -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()

Added: llvm/trunk/tools/llvm-go/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-go/Makefile?rev=220462&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-go/Makefile (added)
+++ llvm/trunk/tools/llvm-go/Makefile Wed Oct 22 21:33:23 2014
@@ -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 $@ $<

Added: llvm/trunk/tools/llvm-go/llvm-go.go
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-go/llvm-go.go?rev=220462&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-go/llvm-go.go (added)
+++ llvm/trunk/tools/llvm-go/llvm-go.go Wed Oct 22 21:33:23 2014
@@ -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()
+	}
+}





More information about the llvm-commits mailing list