github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/tools/defs.bzl (about) 1 """Wrappers for common build rules. 2 3 These wrappers apply common BUILD configurations (e.g., proto_library 4 automagically creating cc_ and go_ proto targets) and act as a single point of 5 change for Google-internal and bazel-compatible rules. 6 """ 7 8 load("//tools/go_stateify:defs.bzl", "go_stateify") 9 load("//tools/go_marshal:defs.bzl", "go_marshal", "marshal_deps", "marshal_test_deps") 10 load("//tools/nogo:defs.bzl", "nogo_test") 11 load("//tools/bazeldefs:defs.bzl", _arch_genrule = "arch_genrule", _build_test = "build_test", _bzl_library = "bzl_library", _coreutil = "coreutil", _default_installer = "default_installer", _default_net_util = "default_net_util", _more_shards = "more_shards", _most_shards = "most_shards", _proto_library = "proto_library", _select_arch = "select_arch", _select_system = "select_system", _short_path = "short_path", _version = "version") 12 load("//tools/bazeldefs:cc.bzl", _cc_binary = "cc_binary", _cc_flags_supplier = "cc_flags_supplier", _cc_grpc_library = "cc_grpc_library", _cc_library = "cc_library", _cc_proto_library = "cc_proto_library", _cc_test = "cc_test", _cc_toolchain = "cc_toolchain", _gbenchmark = "gbenchmark", _grpcpp = "grpcpp", _gtest = "gtest", _vdso_linker_option = "vdso_linker_option") 13 load("//tools/bazeldefs:go.bzl", _bazel_worker_proto = "bazel_worker_proto", _gazelle = "gazelle", _go_binary = "go_binary", _go_embed_data = "go_embed_data", _go_grpc_and_proto_libraries = "go_grpc_and_proto_libraries", _go_library = "go_library", _go_path = "go_path", _go_proto_library = "go_proto_library", _go_rule = "go_rule", _go_test = "go_test", _select_goarch = "select_goarch", _select_goos = "select_goos") 14 load("//tools/bazeldefs:pkg.bzl", _pkg_deb = "pkg_deb", _pkg_tar = "pkg_tar") 15 load("//tools/bazeldefs:platforms.bzl", _default_platform = "default_platform", _platforms = "platforms") 16 load("//tools/bazeldefs:tags.bzl", "go_suffixes") 17 18 # Core rules. 19 arch_genrule = _arch_genrule 20 build_test = _build_test 21 bzl_library = _bzl_library 22 default_installer = _default_installer 23 default_net_util = _default_net_util 24 select_arch = _select_arch 25 select_system = _select_system 26 short_path = _short_path 27 coreutil = _coreutil 28 more_shards = _more_shards 29 most_shards = _most_shards 30 version = _version 31 32 # C++ rules. 33 cc_binary = _cc_binary 34 cc_flags_supplier = _cc_flags_supplier 35 cc_grpc_library = _cc_grpc_library 36 cc_library = _cc_library 37 cc_test = _cc_test 38 cc_toolchain = _cc_toolchain 39 gbenchmark = _gbenchmark 40 gtest = _gtest 41 grpcpp = _grpcpp 42 vdso_linker_option = _vdso_linker_option 43 44 # Go rules. 45 gazelle = _gazelle 46 go_path = _go_path 47 select_goos = _select_goos 48 select_goarch = _select_goarch 49 go_embed_data = _go_embed_data 50 go_proto_library = _go_proto_library 51 bazel_worker_proto = _bazel_worker_proto 52 53 # Packaging rules. 54 pkg_deb = _pkg_deb 55 pkg_tar = _pkg_tar 56 57 # Platform options. 58 default_platform = _default_platform 59 platforms = _platforms 60 61 def _go_add_tags(ctx): 62 """ Adds tags to the given source file. """ 63 output = ctx.outputs.out 64 runner = ctx.actions.declare_file(ctx.label.name + ".sh") 65 lines = ["#!/bin/bash"] 66 lines += ["echo '// +build %s' >> %s" % (tag, output.path) for tag in ctx.attr.go_tags] 67 lines.append("echo '' >> %s" % output.path) 68 lines += ["cat %s >> %s" % (f.path, output.path) for f in ctx.files.src] 69 lines.append("") 70 ctx.actions.write(runner, "\n".join(lines), is_executable = True) 71 ctx.actions.run( 72 inputs = ctx.files.src, 73 outputs = [output], 74 executable = runner, 75 ) 76 return [DefaultInfo( 77 files = depset([output]), 78 )] 79 80 go_add_tags = _go_rule( 81 rule, 82 implementation = _go_add_tags, 83 attrs = { 84 "go_tags": attr.string_list(doc = "Go build tags to be added.", mandatory = True), 85 "src": attr.label(doc = "Source file.", allow_single_file = True, mandatory = True), 86 "out": attr.output(doc = "Output file.", mandatory = True), 87 }, 88 ) 89 90 def go_binary(name, nogo = True, pure = False, static = False, x_defs = None, **kwargs): 91 """Wraps the standard go_binary. 92 93 Args: 94 name: the rule name. 95 nogo: enable nogo analysis. 96 pure: build a pure Go (no CGo) binary. 97 static: build a static binary. 98 x_defs: additional linker definitions. 99 **kwargs: standard go_binary arguments. 100 """ 101 _go_binary( 102 name = name, 103 pure = pure, 104 static = static, 105 x_defs = x_defs, 106 **kwargs 107 ) 108 if nogo: 109 # Note that the nogo rule applies only for go_library and go_test 110 # targets, therefore we construct a library from the binary sources. 111 # This is done because the binary may not be in a form that objdump 112 # supports (i.e. a pure Go binary). 113 _go_library( 114 name = name + "_nogo_library", 115 srcs = kwargs.get("srcs", []), 116 deps = kwargs.get("deps", []), 117 testonly = 1, 118 ) 119 nogo_test( 120 name = name + "_nogo", 121 config = "//:nogo_config", 122 srcs = kwargs.get("srcs", []), 123 deps = [":" + name + "_nogo_library"], 124 tags = ["nogo"], 125 ) 126 127 def calculate_sets(srcs): 128 """Calculates special Go sets for templates. 129 130 Args: 131 srcs: the full set of Go sources. 132 133 Returns: 134 A dictionary of the form: 135 136 "": [src1.go, src2.go] 137 "suffix": [src3suffix.go, src4suffix.go] 138 139 Note that suffix will typically start with '_'. 140 """ 141 result = dict() 142 for file in srcs: 143 if not file.endswith(".go"): 144 continue 145 target = "" 146 for suffix in go_suffixes: 147 if file.endswith(suffix + ".go"): 148 target = suffix 149 if not target in result: 150 result[target] = [file] 151 else: 152 result[target].append(file) 153 return result 154 155 def go_imports(name, src, out): 156 """Simplify a single Go source file by eliminating unused imports.""" 157 native.genrule( 158 name = name, 159 srcs = [src], 160 outs = [out], 161 tools = ["@org_golang_x_tools//cmd/goimports:goimports"], 162 cmd = ("$(location @org_golang_x_tools//cmd/goimports:goimports) $(SRCS) > $@"), 163 ) 164 165 def go_library(name, srcs, deps = [], imports = [], stateify = True, marshal = False, marshal_debug = False, nogo = True, **kwargs): 166 """Wraps the standard go_library and does stateification and marshalling. 167 168 The recommended way is to use this rule with mostly identical configuration as the native 169 go_library rule. 170 171 These definitions provide additional flags (stateify, marshal) that can be used 172 with the generators to automatically supplement the library code. 173 174 load("//tools:defs.bzl", "go_library") 175 176 go_library( 177 name = "foo", 178 srcs = ["foo.go"], 179 ) 180 181 Args: 182 name: the rule name. 183 srcs: the library sources. 184 deps: the library dependencies. 185 imports: imports required for stateify. 186 stateify: whether statify is enabled (default: true). 187 marshal: whether marshal is enabled (default: false). 188 marshal_debug: whether the gomarshal tools emits debugging output (default: false). 189 nogo: enable nogo analysis. 190 **kwargs: standard go_library arguments. 191 """ 192 all_srcs = srcs 193 all_deps = deps 194 dirname, _, _ = native.package_name().rpartition("/") 195 full_pkg = dirname + "/" + name 196 if stateify: 197 # Only do stateification for non-state packages without manual autogen. 198 # First, we need to segregate the input files via the special suffixes, 199 # and calculate the final output set. 200 state_sets = calculate_sets(srcs) 201 for (suffix, src_subset) in state_sets.items(): 202 go_stateify( 203 name = name + suffix + "_state_autogen_with_imports", 204 srcs = src_subset, 205 imports = imports, 206 package = full_pkg, 207 out = name + suffix + "_state_autogen_with_imports.go", 208 ) 209 go_imports( 210 name = name + suffix + "_state_autogen", 211 src = name + suffix + "_state_autogen_with_imports.go", 212 out = name + suffix + "_state_autogen.go", 213 ) 214 all_srcs = all_srcs + [ 215 name + suffix + "_state_autogen.go" 216 for suffix in state_sets.keys() 217 ] 218 219 if "//pkg/state" not in all_deps: 220 all_deps = all_deps + ["//pkg/state"] 221 222 if marshal: 223 # See above. 224 marshal_sets = calculate_sets(srcs) 225 for (suffix, src_subset) in marshal_sets.items(): 226 go_marshal( 227 name = name + suffix + "_abi_autogen", 228 srcs = src_subset, 229 debug = select({ 230 "//tools/go_marshal:marshal_config_verbose": True, 231 "//conditions:default": marshal_debug, 232 }), 233 imports = imports, 234 package = name, 235 ) 236 extra_deps = [ 237 dep 238 for dep in marshal_deps 239 if not dep in all_deps 240 ] 241 all_deps = all_deps + extra_deps 242 all_srcs = all_srcs + [ 243 name + suffix + "_abi_autogen_unsafe.go" 244 for suffix in marshal_sets.keys() 245 ] 246 247 _go_library( 248 name = name, 249 srcs = all_srcs, 250 deps = all_deps, 251 **kwargs 252 ) 253 if nogo: 254 nogo_test( 255 name = name + "_nogo", 256 config = "//:nogo_config", 257 srcs = all_srcs, 258 deps = [":" + name], 259 tags = ["nogo"], 260 ) 261 262 if marshal: 263 # Ignore importpath for go_test. 264 kwargs.pop("importpath", None) 265 266 # See above. 267 marshal_sets = calculate_sets(srcs) 268 for (suffix, _) in marshal_sets.items(): 269 _go_test( 270 name = name + suffix + "_abi_autogen_test", 271 srcs = [ 272 name + suffix + "_abi_autogen_test.go", 273 name + suffix + "_abi_autogen_unconditional_test.go", 274 ], 275 library = ":" + name, 276 deps = marshal_test_deps, 277 **kwargs 278 ) 279 280 def go_test(name, nogo = True, **kwargs): 281 """Wraps the standard go_test. 282 283 Args: 284 name: the rule name. 285 nogo: enable nogo analysis. 286 **kwargs: standard go_test arguments. 287 """ 288 _go_test( 289 name = name, 290 **kwargs 291 ) 292 if nogo: 293 nogo_test( 294 name = name + "_nogo", 295 config = "//:nogo_config", 296 srcs = kwargs.get("srcs", []), 297 deps = [":" + name], 298 tags = ["nogo"], 299 ) 300 301 def proto_library(name, srcs, deps = None, has_services = 0, **kwargs): 302 """Wraps the standard proto_library. 303 304 Given a proto_library named "foo", this produces up to five different 305 targets: 306 - foo_proto: proto_library rule. 307 - foo_go_proto: go_proto_library rule. 308 - foo_cc_proto: cc_proto_library rule. 309 - foo_go_grpc_proto: go_grpc_library rule. 310 - foo_cc_grpc_proto: cc_grpc_library rule. 311 312 Args: 313 name: the name to which _proto, _go_proto, etc, will be appended. 314 srcs: the proto sources. 315 deps: for the proto library and the go_proto_library. 316 has_services: 1 to build gRPC code, otherwise 0. 317 **kwargs: standard proto_library arguments. 318 """ 319 _proto_library( 320 name = name + "_proto", 321 srcs = srcs, 322 deps = deps, 323 has_services = has_services, 324 **kwargs 325 ) 326 if has_services: 327 _go_grpc_and_proto_libraries( 328 name = name, 329 deps = deps, 330 **kwargs 331 ) 332 else: 333 _go_proto_library( 334 name = name, 335 deps = deps, 336 **kwargs 337 ) 338 _cc_proto_library( 339 name = name + "_cc_proto", 340 deps = [":" + name + "_proto"], 341 **kwargs 342 ) 343 if has_services: 344 _cc_grpc_library( 345 name = name + "_cc_grpc_proto", 346 srcs = [":" + name + "_proto"], 347 deps = [":" + name + "_cc_proto"], 348 **kwargs 349 )