From 847764103294b4f61afc50b06bfe19284ac7b7e4 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 25 Mar 2015 17:01:15 +0000 Subject: [PATCH] Remove experimental Go support until we have a solution which fits the 'go' tool conventions better. -- MOS_MIGRATED_REVID=89510837 --- docs/FAQ.md | 18 +- examples/BUILD | 1 - examples/go/BUILD | 22 -- examples/go/README.md | 121 --------- examples/go/fib.go | 11 - examples/go/lib1/BUILD | 29 --- examples/go/lib1/fail_test.go | 9 - examples/go/lib1/lib1.go | 9 - examples/go/lib1/lib1_test.go | 14 - src/test/shell/bazel/bazel_example_test.sh | 25 -- src/test/shell/bazel/test-setup.sh | 4 - src/test/shell/bazel/testenv.sh | 4 - tools/BUILD | 1 - tools/build_rules/go_rules.bzl | 282 --------------------- tools/go/BUILD | 19 -- tools/go/generate_test_main.go | 91 ------- 16 files changed, 5 insertions(+), 655 deletions(-) delete mode 100644 examples/go/BUILD delete mode 100644 examples/go/README.md delete mode 100644 examples/go/fib.go delete mode 100644 examples/go/lib1/BUILD delete mode 100644 examples/go/lib1/fail_test.go delete mode 100644 examples/go/lib1/lib1.go delete mode 100644 examples/go/lib1/lib1_test.go delete mode 100644 tools/build_rules/go_rules.bzl delete mode 100644 tools/go/BUILD delete mode 100644 tools/go/generate_test_main.go diff --git a/docs/FAQ.md b/docs/FAQ.md index a61ce499ec6539..6980bfb0da7f6c 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -385,22 +385,14 @@ Python binaries. What about Go? -------------- -The server code written in Go at Google is also built with Bazel. The -rules that accomplish this are rather complex due to their -interactions with our C++ libraries, and we'd rather not open them up -in their current form. They also predate the conventions of the open -source `go` tool. Indeed, the experience with the Google internal -rules motivated some of the choices in the `go` tool. - If your codebase is 100% Go, the `go` tool has excellent support for building and testing, and Bazel will not bring you much benefit. -For mixed language codebases, you could try the experimental rules at - - - -They mimick the structure of our internal Go rules, and may require -editing some import lines. +The server code written in Go at Google is built with Bazel. However, +the rules that accomplish this are rather complex due to their +interactions with our C++ libraries, and are incompatible with the +conventions of the `go` tool. For this reason, we'd rather not open +them up in their current form. Can I use Bazel for my LISP/Python/Haskell/Scala/Rust project? diff --git a/examples/BUILD b/examples/BUILD index 5551cb2023b277..0e42866a369928 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -5,7 +5,6 @@ filegroup( srcs = [ "//examples/cpp:srcs", "//examples/gen:srcs", - "//examples/go:srcs", "//examples/java-native:srcs", "//examples/java-skylark:srcs", "//examples/objc:srcs", diff --git a/examples/go/BUILD b/examples/go/BUILD deleted file mode 100644 index 3ade6b5321160d..00000000000000 --- a/examples/go/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -# See README.md for instructions on how to use these rules. - -package(default_visibility = ["//visibility:public"]) - -load("/tools/build_rules/go_rules", "go_library", "go_binary") - -go_binary( - name = "fib", - srcs = glob( - ["*.go"], - exclude = ["*_test.go"], - ), - deps = ["//examples/go/lib1"], -) - -filegroup( - name = "srcs", - srcs = [ - "BUILD", - "//examples/go/lib1:srcs", - ] + glob(["**/*.go"]), -) diff --git a/examples/go/README.md b/examples/go/README.md deleted file mode 100644 index 69bcc4c664effa..00000000000000 --- a/examples/go/README.md +++ /dev/null @@ -1,121 +0,0 @@ - -Go rules --------- - -The files here demonstrate how to use the rules for Go supplied under -`//tools/build_rules:go_rules.bzl`. The rules should be considered -experimental. They support: - - * libraries - * binaries - * tests - -They currently do not support: - - * coverage - * race detector - * multiple target configurations - * //+build tags - * C/C++ interoperation (cgo, swig etc.) - - -Testing -------- - -Setup a symlink to the Go installation you wish to use, - - ln -s /usr/lib/golang/ tools/go/go_root - -or - - ln -s $(go env GOROOT) tools/go/go_root - -To build something, run - - bazel build examples/go/... - -To run a test, run - - bazel test --test_arg=--test.v examples/go/lib1:lib1_test - - -Writing BUILD rules -------------------- - -In the bazel model of compiling Go, each directory can hold multiple -packages, rather than just one in the standard "go" tool. Suppose you -have - - dir/f.go: - - package p - func F() {} - -then in the BUILD file could say - - go_library( - name = "q", - srcs = ["f.go"]) - -and you import it with its Bazel name, - - import "dir/p/q" - -this add the declared package name as namespace, i.e., it is -equivalent to - - import p "dir/p/q" - -so you use it as follows - - import "dir/p/q" - main() { - p.F() - } - - -Writing tests -------------- - -For tests, you should create a separate target, - - go_test( - name = "q_test", - srcs = [ "f_test.go" ], - deps = [ ":q" ]) - -if the test code is in the same package as the library under test -(e.g., because you are testing private parts of the library), you should -use the `library` attribute, - - go_test( - name = "q_test", - srcs = [ "f_test.go" ], - library = ":q" ) - -This causes the test and the library under test to be compiled -together. - - -FAQ ---- - -# Why does this not follow the external Go conventions? - -These rules were inspired on Google's internal Go rules, which work -like this. For Bazel, these make more sense, because directories in -Bazel do not correspond to single targets. - - -# Do I have to specify dependencies twice? - -Yes, once in the BUILD file, once in the source file. Bazel does not -examine file contents, so it cannot infer the dependencies. It is -possible to generate the BUILD file from the Go sources through a -separate program, though. - - -Disclaimer ----------- - -These rules are not supported by Google's Go team. diff --git a/examples/go/fib.go b/examples/go/fib.go deleted file mode 100644 index 43d8a499bad12a..00000000000000 --- a/examples/go/fib.go +++ /dev/null @@ -1,11 +0,0 @@ -package main - -import ( - "fmt" - - "examples/go/lib1/lib1" -) - -func main() { - fmt.Println("Fib(5):", lib1.Fib(5)) -} diff --git a/examples/go/lib1/BUILD b/examples/go/lib1/BUILD deleted file mode 100644 index f65620cbfe966a..00000000000000 --- a/examples/go/lib1/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("/tools/build_rules/go_rules", "go_library", "go_binary", "go_test") - -go_library( - name = "lib1", - srcs = glob( - ["*.go"], - exclude = ["*_test.go"], - ), -) - -go_test( - name = "lib1_test", - srcs = [ - "lib1_test.go", - ], - library = ":lib1", -) - -go_test( - name = "fail_test", - srcs = ["fail_test.go"], -) - -filegroup( - name = "srcs", - srcs = ["BUILD"] + glob(["**/*.go"]), -) diff --git a/examples/go/lib1/fail_test.go b/examples/go/lib1/fail_test.go deleted file mode 100644 index 5ef41a3b4d047f..00000000000000 --- a/examples/go/lib1/fail_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package fail - -import ( - "testing" -) - -func TestFail(t *testing.T) { - t.Fatal("I am failing.") -} diff --git a/examples/go/lib1/lib1.go b/examples/go/lib1/lib1.go deleted file mode 100644 index f42494770dddce..00000000000000 --- a/examples/go/lib1/lib1.go +++ /dev/null @@ -1,9 +0,0 @@ -package lib1 - -func Fib(n int) int { - if n < 2 { - return 1 - } - - return Fib(n-1) + Fib(n-2) -} diff --git a/examples/go/lib1/lib1_test.go b/examples/go/lib1/lib1_test.go deleted file mode 100644 index 8eb88a0acaa3b9..00000000000000 --- a/examples/go/lib1/lib1_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package lib1 - -import ( - "testing" -) - -func TestFib(t *testing.T) { - got := Fib(5) - want := 8 - - if got != want { - t.Fatalf("got %d want %d", got, want) - } -} diff --git a/src/test/shell/bazel/bazel_example_test.sh b/src/test/shell/bazel/bazel_example_test.sh index 204e755a15f7ee..998f765535e81f 100755 --- a/src/test/shell/bazel/bazel_example_test.sh +++ b/src/test/shell/bazel/bazel_example_test.sh @@ -112,31 +112,6 @@ function test_python() { expect_log "Fib(5)=8" } -function test_go() { - if [ -e "tools/go/go_root" ]; then - bazel build -s //examples/go/lib1:lib1 \ - || fail "Failed to build //examples/go/lib1:lib1" - bazel clean - bazel build -s //examples/go:fib \ - || fail "Failed to build //examples/go:fib" - [ -x "bazel-bin/examples/go/fib" ] \ - || fail "bazel-bin/examples/go/fib is not executable" - - bazel run //examples/go:fib >$TEST_log \ - || fail "Failed to run //examples/go:fib" - expect_log "Fib(5): 8" - - bazel test //examples/go/lib1:lib1_test \ - || fail "Failed to run //examples/go/lib1:lib1_test" - - bazel test //examples/go/lib1:fail_test \ - && fail "Test //examples/go/lib1:fail_test has succeeded" \ - || true - else - echo "Skipping go test: go_root not set" - fi -} - function test_java_skylark() { local java_pkg=examples/java-skylark/src/main/java/com/example/myproject assert_build ${java_pkg}:hello-lib ./bazel-bin/${java_pkg}/libhello-lib.jar diff --git a/src/test/shell/bazel/test-setup.sh b/src/test/shell/bazel/test-setup.sh index 40fb738caf56e8..5f43ef0b54d346 100755 --- a/src/test/shell/bazel/test-setup.sh +++ b/src/test/shell/bazel/test-setup.sh @@ -115,10 +115,6 @@ function create_new_workspace() { ln -s ${jdk_dir} tools/jdk/jdk fi - if [[ -d ${go_root} ]]; then - ln -s ${go_root} tools/go/go_root - fi - touch WORKSPACE } diff --git a/src/test/shell/bazel/testenv.sh b/src/test/shell/bazel/testenv.sh index 8bb7ea4f574e37..a313159ecb4238 100755 --- a/src/test/shell/bazel/testenv.sh +++ b/src/test/shell/bazel/testenv.sh @@ -52,10 +52,6 @@ protoc_jar="${TEST_SRCDIR}/third_party/protobuf/protobuf-*.jar" junit_jar="${TEST_SRCDIR}/third_party/junit/junit-*.jar" hamcrest_jar="${TEST_SRCDIR}/third_party/hamcrest/hamcrest-*.jar" -# Try to detect go root and fallback with /usr/lib/golang -# The test itselfs is skipped if go_root is unset. -go_root="$(go env GOROOT 2>/dev/null || echo "/usr/lib/golang")" - # This function copy the tools directory from Blaze. function copy_tools_directory() { cp -R ${tools_dir}/* tools diff --git a/tools/BUILD b/tools/BUILD index df3abae3aedb0b..41b4e23d5eb9de 100644 --- a/tools/BUILD +++ b/tools/BUILD @@ -8,7 +8,6 @@ filegroup( name = "srcs", srcs = glob(["**"]) + [ "//tools/jdk:srcs", - "//tools/go:srcs", "//tools/genrule:srcs", "//tools/cpp:srcs", "//tools/objc:srcs", diff --git a/tools/build_rules/go_rules.bzl b/tools/build_rules/go_rules.bzl deleted file mode 100644 index e586671ee96732..00000000000000 --- a/tools/build_rules/go_rules.bzl +++ /dev/null @@ -1,282 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""These are bare-bones Go rules. - -Several issues: - -- Currently hardcoded to 6g from the GC suite. We should be able to - extract the CPU type from ctx.configuration instead. - -- It would be nice to be able to create a full-fledged Go - configuration in Skylark. - -- Almost supports checked in compilers (should use a filegroup under - tools/go instead of symlink). - -- No C++ interop. - -- deps must be populated by hand. - -- no test sharding or test XML. - -""" - -go_filetype = FileType([".go"]) - -# TODO(bazel-team): it would be nice if Bazel had this built-in. -def symlink_tree_commands(dest_dir, artifact_dict): - """Symlink_tree_commands returns a list of commands to create the - dest_dir, and populate it according to the given dict. - - Args: - dest_dir: The destination directory, a string. - artifact_dict: The mapping of exec-path => path in the dest_dir. - - Returns: - A list of commands that will setup the symlink tree. - """ - cmds = [ - "rm -rf " + dest_dir, - "mkdir -p " + dest_dir, - ] - - for item in artifact_dict.items(): - old_path = item[0] - new_path = item[1] - new_dir = new_path[:new_path.rfind('/')] - up = (new_dir.count('/') + 1 + - dest_dir.count('/') + 1) - cmds += [ - "mkdir -p %s/%s" % (dest_dir, new_dir), - "ln -s %s%s %s/%s" % ('../' * up, old_path, dest_dir, new_path), - ] - return cmds - - -def emit_go_compile_action(ctx, sources, deps, out_lib): - """Construct the command line for compiling Go code. - Constructs a symlink tree to accomodate for workspace name. - - Args: - ctx: The skylark Context. - sources: an iterable of source code artifacts (or CTs? or labels?) - deps: an iterable of dependencies. Each dependency d should have an - artifact in d.go_library_object representing an imported library. - out_lib: the artifact (configured target?) that should be produced - """ - - config_strip = len(ctx.configuration.bin_dir.path) + 1 - - out_dir = out_lib.path + ".dir" - out_depth = out_dir.count('/') + 1 - prefix = "" - if ctx.workspace_name: - ctx.workspace_name + "/" - - tree_layout = {} - inputs = [] - for d in deps: - library_artifact_path = d.go_library_object.path[config_strip:] - tree_layout[d.go_library_object.path] = prefix + library_artifact_path - inputs += [d.go_library_object] - - inputs += list(sources) - for s in sources: - tree_layout[s.path] = s.path - - cmds = symlink_tree_commands(out_dir, tree_layout) - args = [ - "cd ", out_dir, "&&", - ('../' * out_depth) + ctx.files.go_root[0].path + "/bin/go", - "tool", "6g", - "-o", ('../' * out_depth) + out_lib.path, "-pack", - - # Import path. - "-I", "."] - - # Set -p to the import path of the library, ie. - # (ctx.label.package + "/" ctx.label.name) for now. - cmds += [ "export GOROOT=$(pwd)/" + ctx.files.go_root[0].path, - ' '.join(args + cmd_helper.template(sources, "%{path}"))] - - ctx.action( - inputs = inputs, - outputs = [out_lib], - mnemonic = "GoCompile", - command = " && ".join(cmds)) - - -def go_library_impl(ctx): - """Implements the go_library() rule.""" - - sources = set(ctx.files.srcs) - deps = ctx.targets.deps - if ctx.targets.library: - sources += ctx.target.library.go_sources - deps += ctx.target.library.direct_deps - - if not sources: - fail("may not be empty", "srcs") - - out_lib = ctx.outputs.lib - emit_go_compile_action(ctx, set(sources), deps, out_lib) - - transitive_libs = set([out_lib]) - for dep in ctx.targets.deps: - transitive_libs += dep.transitive_go_library_object - - return struct( - files = set([out_lib]), - direct_deps = deps, - go_sources = sources, - go_library_object = out_lib, - transitive_go_library_object = transitive_libs) - - -def emit_go_link_action(ctx, transitive_libs, lib, executable): - """Sets up a symlink tree to libraries to link together.""" - out_dir = executable.path + ".dir" - out_depth = out_dir.count('/') + 1 - tree_layout = {} - - config_strip = len(ctx.configuration.bin_dir.path) + 1 - prefix = "" - if ctx.workspace_name: - prefix = ctx.workspace_name + "/" - - for l in transitive_libs: - library_artifact_path = l.path[config_strip:] - tree_layout[l.path] = prefix + library_artifact_path - - tree_layout[lib.path] = prefix + lib.path[config_strip:] - tree_layout[executable.path] = prefix + executable.path[config_strip:] - - cmds = symlink_tree_commands(out_dir, tree_layout) - cmds += [ - "export GOROOT=$(pwd)/" + ctx.files.go_root[0].path, - "cd " + out_dir, - ' '.join([ - ('../' * out_depth) + ctx.files.go_root[0].path + "/bin/go", - "tool", "6l", "-L", ".", - "-o", prefix + executable.path[config_strip:], - prefix + lib.path[config_strip:]])] - - ctx.action( - inputs = list(transitive_libs) + [lib], - outputs = [executable], - command = ' && '.join(cmds), - mnemonic = "GoLink") - - -def go_binary_impl(ctx): - """go_binary_impl emits the link action for a go executable.""" - lib_result = go_library_impl(ctx) - executable = ctx.outputs.executable - lib_out = ctx.outputs.lib - - emit_go_link_action( - ctx, lib_result.transitive_go_library_object, lib_out, executable) - return struct(files = set([executable]) + lib_result.files) - - -def go_test_impl(ctx): - """go_test_impl implements go testing. - - It emits an action to run the test generator, and then compile the - test.""" - - lib_result = go_library_impl(ctx) - main_go = ctx.outputs.main_go - prefix = "" - if ctx.workspace_name: - prefix = ctx.workspace_name + "/" - - go_import = prefix + ctx.label.package + "/" + ctx.label.name - - args = (["--package", go_import, "--output", ctx.outputs.main_go.path] + - cmd_helper.template(lib_result.go_sources, "%{path}")) - ctx.action( - inputs = list(lib_result.go_sources), - executable = ctx.executable.test_generator, - outputs = [main_go], - mnemonic = "GoTestGenTest", - arguments = args) - - emit_go_compile_action( - ctx, set([main_go]), ctx.targets.deps + [lib_result], ctx.outputs.main_lib) - - emit_go_link_action( - ctx, lib_result.transitive_go_library_object, - ctx.outputs.main_lib, ctx.outputs.executable) - - # TODO(bazel-team): the Go tests should do a chdir to the directory - # holding the data files, so open-source go tests continue to work - # without code changes. - runfiles = ctx.runfiles(collect_data = True, files = [ctx.outputs.executable]) - return struct(runfiles=runfiles) - - -go_library_attrs = { - "data": attr.label_list(allow_files=True, cfg=DATA_CFG), - "srcs": attr.label_list(allow_files=go_filetype), - "deps": attr.label_list( - providers=[ - "direct_deps", - "go_library_object", - "transitive_go_library_object", - ]), - "go_root": attr.label( - default=Label("//tools/go:go_root"), - allow_files=True, - cfg=HOST_CFG), - "library": attr.label( - providers=["go_sources"]), - } - -go_library_outputs = { - "lib": "%{name}.a", - } - -go_library = rule( - go_library_impl, - attrs = go_library_attrs, - outputs =go_library_outputs) - -go_binary = rule( - go_binary_impl, - executable = True, - attrs = go_library_attrs + { - "stamp": attr.bool(default=False), - }, - outputs = go_library_outputs) - -go_test = rule( - go_test_impl, - executable = True, - test = True, - attrs = go_library_attrs + { - "test_generator": attr.label( - default=Label("//tools/go:generate_test_main"), - cfg=HOST_CFG, flags=["EXECUTABLE"]), - # TODO(bazel-team): implement support for args and defines_main. - "args": attr.string_list(), - "defines_main": attr.bool(default=False), - "stamp": attr.bool(default=False), - }, - outputs = { - "lib" : "%{name}.a", - "main_lib": "%{name}_main_test.a", - "main_go": "%{name}_main_test.go", -}) diff --git a/tools/go/BUILD b/tools/go/BUILD deleted file mode 100644 index dd9e0d707f4c50..00000000000000 --- a/tools/go/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("/tools/build_rules/go_rules", "go_binary", "go_library") - -# This should be a symlink to a GOROOT holding bin/ and pkg/ -exports_files(srcs = ["go_root"]) - -go_binary( - name = "generate_test_main", - srcs = ["generate_test_main.go"], -) - -filegroup( - name = "srcs", - srcs = [ - "BUILD", - "generate_test_main.go", - ], -) diff --git a/tools/go/generate_test_main.go b/tools/go/generate_test_main.go deleted file mode 100644 index 6316802dde357c..00000000000000 --- a/tools/go/generate_test_main.go +++ /dev/null @@ -1,91 +0,0 @@ -// Bare bones Go testing support for Bazel. - -package main - -import ( - "flag" - "go/ast" - "go/parser" - "go/token" - "log" - "os" - "strings" - "text/template" -) - -// Cases holds template data. -type Cases struct { - Package string - Names []string -} - -func main() { - pkg := flag.String("package", "", "package from which to import test methods.") - out := flag.String("output", "", "output file to write. Defaults to stdout.") - flag.Parse() - - if *pkg == "" { - log.Fatal("must set --package.") - } - - outFile := os.Stdout - if *out != "" { - var err error - outFile, err = os.Create(*out) - if err != nil { - log.Fatalf("os.Create(%q): %v", *out, err) - } - defer outFile.Close() - } - - cases := Cases{ - Package: *pkg, - } - testFileSet := token.NewFileSet() - for _, f := range flag.Args() { - parse, err := parser.ParseFile(testFileSet, f, nil, parser.ParseComments) - if err != nil { - log.Fatalf("ParseFile(%q): %v", f, err) - } - - for _, d := range parse.Decls { - fn, ok := d.(*ast.FuncDecl) - if !ok { - continue - } - if fn.Recv != nil { - continue - } - if !strings.HasPrefix(fn.Name.Name, "Test") { - continue - } - cases.Names = append(cases.Names, fn.Name.Name) - } - } - - tpl := template.Must(template.New("source").Parse(` -package main -import ( - "testing" - - undertest "{{.Package}}" -) - -func everything(pat, str string) (bool, error) { - return true, nil -} - -var tests = []testing.InternalTest{ -{{range .Names}} - {"{{.}}", undertest.{{.}} }, -{{end}} -} - -func main() { - testing.Main(everything, tests, nil, nil) -} -`)) - if err := tpl.Execute(outFile, &cases); err != nil { - log.Fatalf("template.Execute(%v): %v", cases, err) - } -}