github.com/bazelbuild/rules_go@v0.47.2-0.20240515105122-e7ddb9ea474e/go/private/rules/sdk.bzl (about) 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 15 load( 16 "//go/private:providers.bzl", 17 "GoSDK", 18 ) 19 20 def _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 39 go_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 103 def _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 107 package_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 130 def _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)