github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/tools/go_generics/defs.bzl (about) 1 """Generics support via go_generics. 2 3 A Go template is similar to a go library, except that it has certain types that 4 can be replaced before usage. For example, one could define a templatized List 5 struct, whose elements are of type T, then instantiate that template for 6 T=segment, where "segment" is the concrete type. 7 """ 8 9 TemplateInfo = provider( 10 "Information about a go_generics template.", 11 fields = { 12 "unsafe": "whether the template requires unsafe code", 13 "types": "required types", 14 "opt_types": "optional types", 15 "consts": "required consts", 16 "opt_consts": "optional consts", 17 "deps": "package dependencies", 18 "template": "merged template source file", 19 }, 20 ) 21 22 def _go_template_impl(ctx): 23 srcs = ctx.files.srcs 24 template = ctx.actions.declare_file(ctx.label.name + "_template.go") 25 args = ["-o=%s" % template.path] + [f.path for f in srcs] 26 27 ctx.actions.run( 28 inputs = srcs, 29 outputs = [template], 30 mnemonic = "GoGenericsTemplate", 31 progress_message = "Building Go template %s" % ctx.label, 32 arguments = args, 33 executable = ctx.executable._tool, 34 ) 35 36 return [TemplateInfo( 37 types = ctx.attr.types, 38 opt_types = ctx.attr.opt_types, 39 consts = ctx.attr.consts, 40 opt_consts = ctx.attr.opt_consts, 41 deps = ctx.attr.deps, 42 template = template, 43 )] 44 45 go_template = rule( 46 implementation = _go_template_impl, 47 attrs = { 48 "srcs": attr.label_list(doc = "the list of source files that comprise the template", mandatory = True, allow_files = True), 49 "deps": attr.label_list(doc = "the standard dependency list", allow_files = True, cfg = "target"), 50 "types": attr.string_list(doc = "the list of generic types in the template that are required to be specified"), 51 "opt_types": attr.string_list(doc = "the list of generic types in the template that can but aren't required to be specified"), 52 "consts": attr.string_list(doc = "the list of constants in the template that are required to be specified"), 53 "opt_consts": attr.string_list(doc = "the list of constants in the template that can but aren't required to be specified"), 54 "_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_generics/go_merge")), 55 }, 56 ) 57 58 def _go_template_instance_impl(ctx): 59 info = ctx.attr.template[TemplateInfo] 60 output = ctx.outputs.out 61 62 # Check that all required types are defined. 63 for t in info.types: 64 if t not in ctx.attr.types: 65 fail("Missing value for type %s in %s" % (t, ctx.attr.template.label)) 66 67 # Check that all defined types are expected by the template. 68 for t in ctx.attr.types: 69 if (t not in info.types) and (t not in info.opt_types): 70 fail("Type %s is not a parameter to %s" % (t, ctx.attr.template.label)) 71 72 # Check that all required consts are defined. 73 for t in info.consts: 74 if t not in ctx.attr.consts: 75 fail("Missing value for constant %s in %s" % (t, ctx.attr.template.label)) 76 77 # Check that all defined consts are expected by the template. 78 for t in ctx.attr.consts: 79 if (t not in info.consts) and (t not in info.opt_consts): 80 fail("Const %s is not a parameter to %s" % (t, ctx.attr.template.label)) 81 82 # Build the argument list. 83 args = ["-i=%s" % info.template.path, "-o=%s" % output.path] 84 if ctx.attr.package: 85 args.append("-p=%s" % ctx.attr.package) 86 87 if len(ctx.attr.prefix) > 0: 88 args.append("-prefix=%s" % ctx.attr.prefix) 89 90 if len(ctx.attr.suffix) > 0: 91 args.append("-suffix=%s" % ctx.attr.suffix) 92 93 args += [("-t=%s=%s" % (p[0], p[1])) for p in ctx.attr.types.items()] 94 args += [("-c=%s=%s" % (p[0], p[1])) for p in ctx.attr.consts.items()] 95 args += [("-import=%s=%s" % (p[0], p[1])) for p in ctx.attr.imports.items()] 96 97 if ctx.attr.anon: 98 args.append("-anon") 99 100 ctx.actions.run( 101 inputs = [info.template], 102 outputs = [output], 103 mnemonic = "GoGenericsInstance", 104 progress_message = "Building Go template instance %s" % ctx.label, 105 arguments = args, 106 executable = ctx.executable._tool, 107 ) 108 109 return [DefaultInfo( 110 files = depset([output]), 111 )] 112 113 go_template_instance = rule( 114 implementation = _go_template_instance_impl, 115 attrs = { 116 "template": attr.label(doc = "the label of the template to be instantiated", mandatory = True), 117 "prefix": attr.string(doc = "a prefix to be added to globals in the template"), 118 "suffix": attr.string(doc = "a suffix to be added to globals in the template"), 119 "types": attr.string_dict(doc = "the map from generic type names to concrete ones"), 120 "consts": attr.string_dict(doc = "the map from constant names to their values"), 121 "imports": attr.string_dict(doc = "the map from imports used in types/consts to their import paths"), 122 "anon": attr.bool(doc = "whether anoymous fields should be processed", mandatory = False, default = False), 123 "package": attr.string(doc = "the package for the generated source file", mandatory = False), 124 "out": attr.output(doc = "output file", mandatory = True), 125 "_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_generics")), 126 }, 127 )