• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15load(
16    "//go/private:providers.bzl",
17    "GoSDK",
18)
19
20def _go_sdk_impl(ctx):
21    package_list = ctx.file.package_list
22    if package_list == None:
23        package_list = ctx.actions.declare_file("packages.txt")
24        _build_package_list(ctx, ctx.files.srcs, ctx.file.root_file, package_list)
25    return [GoSDK(
26        goos = ctx.attr.goos,
27        goarch = ctx.attr.goarch,
28        experiments = ctx.attr.experiments,
29        root_file = ctx.file.root_file,
30        package_list = package_list,
31        libs = ctx.files.libs,
32        headers = ctx.files.headers,
33        srcs = ctx.files.srcs,
34        tools = ctx.files.tools,
35        go = ctx.executable.go,
36        version = ctx.attr.version,
37    )]
38
39go_sdk = rule(
40    _go_sdk_impl,
41    attrs = {
42        "goos": attr.string(
43            mandatory = True,
44            doc = "The host OS the SDK was built for",
45        ),
46        "goarch": attr.string(
47            mandatory = True,
48            doc = "The host architecture the SDK was built for",
49        ),
50        "experiments": attr.string_list(
51            mandatory = False,
52            doc = "Go experiments to enable via GOEXPERIMENT",
53        ),
54        "root_file": attr.label(
55            mandatory = True,
56            allow_single_file = True,
57            doc = "A file in the SDK root directory. Used to determine GOROOT.",
58        ),
59        "package_list": attr.label(
60            allow_single_file = True,
61            doc = ("A text file containing a list of packages in the " +
62                   "standard library that may be imported."),
63        ),
64        "libs": attr.label_list(
65            # allow_files is not set to [".a"] because that wouldn't allow
66            # for zero files to be present, as is the case in Go 1.20+.
67            # See also https://github.com/bazelbuild/bazel/issues/7516
68            allow_files = True,
69            doc = ("Pre-compiled .a files for the standard library, " +
70                   "built for the execution platform"),
71        ),
72        "headers": attr.label_list(
73            allow_files = [".h"],
74            doc = (".h files from pkg/include that may be included in " +
75                   "assembly sources"),
76        ),
77        "srcs": attr.label_list(
78            allow_files = True,
79            doc = "Source files for packages in the standard library",
80        ),
81        "tools": attr.label_list(
82            allow_files = True,
83            cfg = "exec",
84            doc = ("List of executable files in the SDK built for " +
85                   "the execution platform, excluding the go binary"),
86        ),
87        "go": attr.label(
88            mandatory = True,
89            allow_single_file = True,
90            executable = True,
91            cfg = "exec",
92            doc = "The go binary",
93        ),
94        "version": attr.string(
95            doc = "The version of the Go SDK.",
96        ),
97    },
98    doc = ("Collects information about a Go SDK. The SDK must have a normal " +
99           "GOROOT directory structure."),
100    provides = [GoSDK],
101)
102
103def _package_list_impl(ctx):
104    _build_package_list(ctx, ctx.files.srcs, ctx.file.root_file, ctx.outputs.out)
105    return [DefaultInfo(files = depset([ctx.outputs.out]))]
106
107package_list = rule(
108    _package_list_impl,
109    attrs = {
110        "srcs": attr.label_list(
111            allow_files = True,
112            doc = "Source files for packages in the standard library",
113        ),
114        "root_file": attr.label(
115            mandatory = True,
116            allow_single_file = True,
117            doc = "A file in the SDK root directory. Used to determine GOROOT.",
118        ),
119        "out": attr.output(
120            mandatory = True,
121            doc = "File to write. Must be 'packages.txt'.",
122            # Gazelle depends on this file directly. It has to be an output
123            # attribute because Bazel has no other way of knowing what rule
124            # produces this file.
125            # TODO(jayconrod): Update Gazelle and simplify this.
126        ),
127    },
128)
129
130def _build_package_list(ctx, srcs, root_file, out):
131    packages = {}
132    src_dir = root_file.dirname + "/src/"
133    for src in srcs:
134        pkg_src_dir = src.dirname
135        if not pkg_src_dir.startswith(src_dir):
136            continue
137        pkg_name = pkg_src_dir[len(src_dir):]
138        packages[pkg_name] = None
139    content = "\n".join(sorted(packages.keys())) + "\n"
140    ctx.actions.write(out, content)
141