llvm.org GIT mirror llvm / bdc3a5b
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220462 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 4 years ago
10 changed file(s) with 316 addition(s) and 59 deletion(s). Raw diff Collapse all Expand all
0 #!/bin/sh -xe
1
2 llvm_components="\
3 all-targets \
4 analysis \
5 asmparser \
6 asmprinter \
7 bitreader \
8 bitwriter \
9 codegen \
10 core \
11 debuginfo \
12 executionengine \
13 instrumentation \
14 interpreter \
15 ipo \
16 irreader \
17 linker \
18 mc \
19 mcjit \
20 objcarcopts \
21 option \
22 profiledata \
23 scalaropts \
24 support \
25 target \
26 "
27
28 if [ "$1" = "--print-components" ] ; then
29 echo $llvm_components
30 exit 0
31 fi
321
332 gollvmdir=$(dirname "$0")/llvm
343
409
4110 cmake_flags="../../../../.. $@"
4211 llvm_config="$llvm_builddir/bin/llvm-config"
12 llvm_go="$llvm_builddir/bin/llvm-go"
4313
4414 if test -n "`which ninja`" ; then
4515 # If Ninja is available, we can speed up the build by building only the
4616 # required subset of LLVM.
4717 (cd $llvm_builddir && cmake -G Ninja $cmake_flags)
48 ninja -C $llvm_builddir llvm-config
18 ninja -C $llvm_builddir llvm-config llvm-go
19 llvm_components="$($llvm_go print-components)"
4920 llvm_buildtargets="$($llvm_config --libs $llvm_components | sed -e 's/-l//g')"
5021 ninja -C $llvm_builddir $llvm_buildtargets FileCheck
5122 else
5324 make -C $llvm_builddir -j4
5425 fi
5526
27 $llvm_go print-config > $gollvmdir/llvm_config.go
28
5629 llvm_version="$($llvm_config --version)"
57 llvm_cflags="$($llvm_config --cppflags)"
58 llvm_ldflags="$($llvm_config --ldflags) $($llvm_config --libs $llvm_components) $($llvm_config --system-libs)"
59 if [ $(uname) != "Darwin" ]; then
60 # OS X doesn't like -rpath with cgo. See:
61 # https://code.google.com/p/go/issues/detail?id=7293
62 llvm_ldflags="-Wl,-rpath,$($llvm_config --libdir) $llvm_ldflags"
63 fi
64 sed -e "s#@LLVM_CFLAGS@#$llvm_cflags#g; s#@LLVM_LDFLAGS@#$llvm_ldflags#g" $gollvmdir/llvm_config.go.in > \
65 $gollvmdir/llvm_config.go
6630 printf "package llvm\n\nconst Version = \"%s\"\n" "$llvm_version" > $gollvmdir/version.go
492492 endif()
493493
494494 set(LLVM_BINDINGS "")
495 find_program(GO_EXECUTABLE NAMES go DOC "go executable")
496 if(GO_EXECUTABLE STREQUAL "GO_EXECUTABLE-NOTFOUND")
495 if(WIN32)
497496 message(STATUS "Go bindings disabled.")
498497 else()
499 execute_process(COMMAND ${GO_EXECUTABLE} run ${CMAKE_SOURCE_DIR}/bindings/go/conftest.go
500 RESULT_VARIABLE GO_CONFTEST)
501 if(GO_CONFTEST STREQUAL "0")
502 set(LLVM_BINDINGS "${LLVM_BINDINGS} go")
503 message(STATUS "Go bindings enabled.")
504 else()
505 message(STATUS "Go bindings disabled, need at least Go 1.2.")
506 endif()
507 endif()
498 find_program(GO_EXECUTABLE NAMES go DOC "go executable")
499 if(GO_EXECUTABLE STREQUAL "GO_EXECUTABLE-NOTFOUND")
500 message(STATUS "Go bindings disabled.")
501 else()
502 execute_process(COMMAND ${GO_EXECUTABLE} run ${CMAKE_SOURCE_DIR}/bindings/go/conftest.go
503 RESULT_VARIABLE GO_CONFTEST)
504 if(GO_CONFTEST STREQUAL "0")
505 set(LLVM_BINDINGS "${LLVM_BINDINGS} go")
506 message(STATUS "Go bindings enabled.")
507 else()
508 message(STATUS "Go bindings disabled, need at least Go 1.2.")
509 endif()
510 endif()
511 endif()
None ; RUN: cd %S/../../../bindings/go/llvm && \
1 ; RUN: env CGO_CPPFLAGS="$(llvm-config --cppflags)" \
2 ; RUN: CGO_CXXFLAGS=-std=c++11 \
3 ; RUN: CGO_LDFLAGS="$(llvm-config --ldflags --libs --system-libs \
4 ; RUN: $(../build.sh --print-components)) $CGO_LDFLAGS" \
5 ; RUN: %go test -tags byollvm .
0 ; RUN: llvm-go test llvm.org/llvm/bindings/go/llvm
61
72 ; REQUIRES: shell
2929 llvm-cov
3030 llvm-diff
3131 llvm-dis
32 llvm-dwarfdump
3233 llvm-extract
33 llvm-dwarfdump
34 llvm-go
3435 llvm-link
3536 llvm-lto
3637 llvm-mc
199199 r"\bllvm-dis\b",
200200 r"\bllvm-dwarfdump\b",
201201 r"\bllvm-extract\b",
202 r"\bllvm-go\b",
202203 r"\bllvm-link\b",
203204 r"\bllvm-lto\b",
204205 r"\bllvm-mc\b",
5151 add_llvm_tool_subdirectory(obj2yaml)
5252 add_llvm_tool_subdirectory(yaml2obj)
5353
54 add_llvm_tool_subdirectory(llvm-go)
55
5456 if(NOT CYGWIN AND LLVM_ENABLE_PIC)
5557 add_llvm_tool_subdirectory(lto)
5658 add_llvm_tool_subdirectory(llvm-lto)
7373 endif
7474 endif
7575
76 ifneq (,$(filter go,$(BINDINGS_TO_BUILD)))
77 PARALLEL_DIRS += llvm-go
78 endif
79
7680 include $(LEVEL)/Makefile.common
0 if(LLVM_BINDINGS MATCHES "go")
1 set(binpath ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX})
2 add_custom_command(OUTPUT ${binpath}
3 COMMAND ${GO_EXECUTABLE} build -o ${binpath} llvm-go.go
4 DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/llvm-go.go
5 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
6 COMMENT "Building Go executable llvm-go")
7 add_custom_target(llvm-go ALL DEPENDS ${binpath})
8 endif()
0 ##===- tools/llvm-go/Makefile ------------------------------*- Makefile -*-===##
1 #
2 # The LLVM Compiler Infrastructure
3 #
4 # This file is distributed under the University of Illinois Open Source
5 # License. See LICENSE.TXT for details.
6 #
7 ##===----------------------------------------------------------------------===##
8
9 LEVEL := ../..
10 include $(LEVEL)/Makefile.common
11
12 all:: $(ToolDir)/llvm-go$(EXEEXT)
13
14 $(ToolDir)/llvm-go$(EXEEXT): $(PROJ_SRC_DIR)/llvm-go.go
15 $(GO) build -o $@ $<
0 //===-- llvm-go.go - go tool wrapper for LLVM -----------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tool lets us build LLVM components within the tree by setting up a
10 // $GOPATH that resembles a tree fetched in the normal way with "go get".
11 //
12 //===----------------------------------------------------------------------===//
13
14 package main
15
16 import (
17 "fmt"
18 "io/ioutil"
19 "os"
20 "os/exec"
21 "path/filepath"
22 "runtime"
23 "strings"
24 )
25
26 type pkg struct {
27 llvmpath, pkgpath string
28 }
29
30 var packages = []pkg{
31 {"bindings/go/llvm", "llvm.org/llvm/bindings/go/llvm"},
32 }
33
34 type compilerFlags struct {
35 cpp, cxx, ld string
36 }
37
38 var components = []string{
39 "all-targets",
40 "analysis",
41 "asmparser",
42 "asmprinter",
43 "bitreader",
44 "bitwriter",
45 "codegen",
46 "core",
47 "debuginfo",
48 "executionengine",
49 "instrumentation",
50 "interpreter",
51 "ipo",
52 "irreader",
53 "linker",
54 "mc",
55 "mcjit",
56 "objcarcopts",
57 "option",
58 "profiledata",
59 "scalaropts",
60 "support",
61 "target",
62 }
63
64 func llvmConfig(args ...string) string {
65 configpath := os.Getenv("LLVM_CONFIG")
66 if configpath == "" {
67 // strip llvm-go, add llvm-config
68 configpath = os.Args[0][:len(os.Args[0])-7] + "llvm-config"
69 }
70
71 cmd := exec.Command(configpath, args...)
72 out, err := cmd.Output()
73 if err != nil {
74 panic(err.Error())
75 }
76
77 outstr := string(out)
78 outstr = strings.TrimSuffix(outstr, "\n")
79 return strings.Replace(outstr, "\n", " ", -1)
80 }
81
82 func llvmFlags() compilerFlags {
83 ldflags := llvmConfig(append([]string{"--ldflags", "--libs", "--system-libs"}, components...)...)
84 if runtime.GOOS != "darwin" {
85 // OS X doesn't like -rpath with cgo. See:
86 // https://code.google.com/p/go/issues/detail?id=7293
87 ldflags = "-Wl,-rpath," + llvmConfig("--libdir") + " " + ldflags
88 }
89 return compilerFlags{
90 cpp: llvmConfig("--cppflags"),
91 cxx: "-std=c++11",
92 ld: ldflags,
93 }
94 }
95
96 func addTag(args []string, tag string) []string {
97 args = append([]string{}, args...)
98 addedTag := false
99 for i, a := range args {
100 if strings.HasPrefix(a, "-tags=") {
101 args[i] = a + " " + tag
102 addedTag = true
103 } else if a == "-tags" && i+1 < len(args) {
104 args[i+1] = args[i+1] + " " + tag
105 addedTag = true
106 }
107 }
108 if !addedTag {
109 args = append([]string{args[0], "-tags", tag}, args[1:]...)
110 }
111 return args
112 }
113
114 func printComponents() {
115 fmt.Println(strings.Join(components, " "))
116 }
117
118 func printConfig() {
119 flags := llvmFlags()
120
121 fmt.Printf(`// +build !byollvm
122
123 // This file is generated by llvm-go, do not edit.
124
125 package llvm
126
127 /*
128 #cgo CPPFLAGS: %s
129 #cgo CXXFLAGS: %s
130 #cgo LDFLAGS: %s
131 */
132 import "C"
133
134 type (run_build_sh int)
135 `, flags.cpp, flags.cxx, flags.ld)
136 }
137
138 func runGoWithLLVMEnv(args []string, cc, cxx, cppflags, cxxflags, ldflags string) {
139 args = addTag(args, "byollvm")
140
141 srcdir := llvmConfig("--src-root")
142
143 tmpgopath, err := ioutil.TempDir("", "gopath")
144 if err != nil {
145 panic(err.Error())
146 }
147
148 for _, p := range packages {
149 path := filepath.Join(tmpgopath, "src", p.pkgpath)
150 err := os.MkdirAll(filepath.Dir(path), os.ModePerm)
151 if err != nil {
152 panic(err.Error())
153 }
154
155 err = os.Symlink(filepath.Join(srcdir, p.llvmpath), path)
156 if err != nil {
157 panic(err.Error())
158 }
159 }
160
161 newgopathlist := []string{tmpgopath}
162 newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...)
163 newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator))
164
165 flags := llvmFlags()
166
167 newenv := []string{
168 "CC=" + cc,
169 "CXX=" + cxx,
170 "CGO_CPPFLAGS=" + flags.cpp + " " + cppflags,
171 "CGO_CXXFLAGS=" + flags.cxx + " " + cxxflags,
172 "CGO_LDFLAGS=" + flags.ld + " " + ldflags,
173 "GOPATH=" + newgopath,
174 }
175 for _, v := range os.Environ() {
176 if !strings.HasPrefix(v, "CC=") &&
177 !strings.HasPrefix(v, "CXX=") &&
178 !strings.HasPrefix(v, "CGO_CPPFLAGS=") &&
179 !strings.HasPrefix(v, "CGO_CXXFLAGS=") &&
180 !strings.HasPrefix(v, "CGO_LDFLAGS=") &&
181 !strings.HasPrefix(v, "GOPATH=") {
182 newenv = append(newenv, v)
183 }
184 }
185
186 gocmdpath, err := exec.LookPath("go")
187 if err != nil {
188 panic(err.Error())
189 }
190
191 proc, err := os.StartProcess(gocmdpath, append([]string{"go"}, args...),
192 &os.ProcAttr{
193 Env: newenv,
194 Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
195 })
196 if err != nil {
197 panic(err.Error())
198 }
199 ps, err := proc.Wait()
200 if err != nil {
201 panic(err.Error())
202 }
203
204 os.RemoveAll(tmpgopath)
205
206 if !ps.Success() {
207 os.Exit(1)
208 }
209 }
210
211 func usage() {
212 fmt.Println(`Usage: llvm-go subcommand [flags]
213
214 Available subcommands: build get install run test print-components print-config`)
215 os.Exit(0)
216 }
217
218 func main() {
219 cc := os.Getenv("CC")
220 cxx := os.Getenv("CXX")
221 cppflags := os.Getenv("CGO_CPPFLAGS")
222 cxxflags := os.Getenv("CGO_CXXFLAGS")
223 ldflags := os.Getenv("CGO_LDFLAGS")
224
225 args := os.Args[1:]
226 DONE: for {
227 switch {
228 case len(args) == 0:
229 usage()
230 case strings.HasPrefix(args[0], "cc="):
231 cc = args[0][3:]
232 args = args[1:]
233 case strings.HasPrefix(args[0], "cxx="):
234 cxx = args[0][4:]
235 args = args[1:]
236 case strings.HasPrefix(args[0], "cppflags="):
237 cppflags = args[0][9:]
238 args = args[1:]
239 case strings.HasPrefix(args[0], "cxxflags="):
240 cxxflags = args[0][9:]
241 args = args[1:]
242 case strings.HasPrefix(args[0], "ldflags="):
243 ldflags = args[0][8:]
244 args = args[1:]
245 default:
246 break DONE
247 }
248 }
249
250 switch args[0] {
251 case "build", "get", "install", "run", "test":
252 runGoWithLLVMEnv(args, cc, cxx, cppflags, cxxflags, ldflags)
253 case "print-components":
254 printComponents()
255 case "print-config":
256 printConfig()
257 default:
258 usage()
259 }
260 }