Add go_sdk rule and GoSDK provider (#1606)
go_sdk is a new rule that gathers information about an SDK and returns
a GoSDK provider which will get wired into the toolchain.
package_list is a new rule that generates a list of importable
packages from the sources in the SDK (previously, we invoked go list,
which is slower).
diff --git a/go/def.bzl b/go/def.bzl
index 24c5cc5..b0c82e3 100644
--- a/go/def.bzl
+++ b/go/def.bzl
@@ -23,6 +23,7 @@
_GoLibrary = "GoLibrary",
_GoPath = "GoPath",
_GoSource = "GoSource",
+ _GoSDK = "GoSDK",
)
load(
"@io_bazel_rules_go//go/private:repositories.bzl",
@@ -36,6 +37,10 @@
"go_local_sdk",
)
load(
+ "@io_bazel_rules_go//go/private:rules/sdk.bzl",
+ "go_sdk",
+)
+load(
"@io_bazel_rules_go//go/private:go_toolchain.bzl",
"go_toolchain",
)
@@ -89,6 +94,9 @@
GoArchiveData = _GoArchiveData
"""See go/providers.rst#GoArchiveData for full documentation."""
+GoSDK = _GoSDK
+"""See go/providers.rst#GoSDK for full documentation."""
+
go_library = _go_library_macro
"""See go/core.rst#go_library for full documentation."""
diff --git a/go/private/providers.bzl b/go/private/providers.bzl
index 15e01fc..9a5a3a3 100644
--- a/go/private/providers.bzl
+++ b/go/private/providers.bzl
@@ -48,6 +48,27 @@
GoPath = provider()
+GoSDK = provider(
+ doc = "Contains information about the Go SDK used in the toolchain",
+ fields = {
+ "goos": "The host OS the SDK was built for.",
+ "goarch": "The host architecture the SDK was built for.",
+ "root_file": "A file in the SDK root directory",
+ "libs": ("List of pre-compiled .a files for the standard library " +
+ "built for the execution platform."),
+ "headers": ("List of .h files from pkg/include that may be included " +
+ "in assembly sources."),
+ "srcs": ("List of source files for importable packages in the " +
+ "standard library. Internal, vendored, and tool packages " +
+ "may not be included."),
+ "package_list": ("A file containing a list of importable packages " +
+ "in the standard library."),
+ "tools": ("List of executable files from pkg/tool " +
+ "built for the execution platform."),
+ "go": "The go binary file",
+ },
+)
+
GoStdLib = provider()
GoBuilders = provider()
diff --git a/go/private/rules/sdk.bzl b/go/private/rules/sdk.bzl
new file mode 100644
index 0000000..3995080
--- /dev/null
+++ b/go/private/rules/sdk.bzl
@@ -0,0 +1,124 @@
+# Copyright 2014 The Bazel Authors. 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.
+
+load(
+ "@io_bazel_rules_go//go/private:providers.bzl",
+ "GoSDK",
+)
+
+def _go_sdk_impl(ctx):
+ return [GoSDK(
+ goos = ctx.attr.goos,
+ goarch = ctx.attr.goarch,
+ root_file = ctx.file.root_file,
+ package_list = ctx.file.package_list,
+ libs = ctx.files.libs,
+ headers = ctx.files.headers,
+ srcs = ctx.files.srcs,
+ tools = ctx.files.tools,
+ go = ctx.file.go,
+ )]
+
+go_sdk = rule(
+ _go_sdk_impl,
+ attrs = {
+ "goos": attr.string(
+ mandatory = True,
+ doc = "The host OS the SDK was built for",
+ ),
+ "goarch": attr.string(
+ mandatory = True,
+ doc = "The host architecture the SDK was built for",
+ ),
+ "root_file": attr.label(
+ mandatory = True,
+ allow_single_file = True,
+ doc = "A file in the SDK root directory. Used to determine GOROOT.",
+ ),
+ "package_list": attr.label(
+ mandatory = True,
+ allow_single_file = True,
+ doc = ("A text file containing a list of packages in the " +
+ "standard library that may be imported."),
+ ),
+ "libs": attr.label_list(
+ allow_files = [".a"],
+ doc = ("Pre-compiled .a files for the standard library, " +
+ "built for the execution platform"),
+ ),
+ "headers": attr.label_list(
+ allow_files = [".h"],
+ doc = (".h files from pkg/include that may be included in " +
+ "assembly sources"),
+ ),
+ "srcs": attr.label_list(
+ allow_files = True,
+ doc = "Source files for packages in the standard library",
+ ),
+ "tools": attr.label_list(
+ allow_files = True,
+ cfg = "host",
+ doc = ("List of executable files from pkg/tool " +
+ "built for the execution platform"),
+ ),
+ "go": attr.label(
+ mandatory = True,
+ allow_single_file = True,
+ executable = True,
+ cfg = "host",
+ doc = "The go binary",
+ ),
+ },
+ doc = ("Collects information about a Go SDK. The SDK must have a normal " +
+ "GOROOT directory structure."),
+ provides = [GoSDK],
+)
+
+def _package_list_impl(ctx):
+ packages = {}
+ src_dir = ctx.file.root_file.dirname + "/src/"
+ for src in ctx.files.srcs:
+ pkg_src_dir = src.dirname
+ if not pkg_src_dir.startswith(src_dir):
+ continue
+ pkg_name = pkg_src_dir[len(src_dir):]
+ if any([prefix in pkg_name for prefix in ("vendor/", "cmd/")]):
+ continue
+ packages[pkg_name] = None
+ content = "\n".join(sorted(packages.keys())) + "\n"
+ ctx.actions.write(ctx.outputs.out, content)
+ return [DefaultInfo(files = depset([ctx.outputs.out]))]
+
+package_list = rule(
+ _package_list_impl,
+ attrs = {
+ "srcs": attr.label_list(
+ allow_files = True,
+ doc = "Source files for packages in the standard library",
+ ),
+ "root_file": attr.label(
+ mandatory = True,
+ allow_single_file = True,
+ doc = "A file in the SDK root directory. Used to determine GOROOT.",
+ ),
+ "out": attr.output(
+ mandatory = True,
+ doc = "File to write. Must be 'packages.txt'.",
+ # Gazelle depends on this file directly. It has to be an output
+ # attribute because Bazel has no other way of knowing what rule
+ # produces this file.
+ # TODO(jayconrod): Update Gazelle and simplify this.
+ ),
+ },
+)