2018-04-27 17:37:02 +00:00
|
|
|
def _go_template_impl(ctx):
|
2018-05-03 20:43:20 +00:00
|
|
|
input = ctx.files.srcs
|
|
|
|
output = ctx.outputs.out
|
|
|
|
|
|
|
|
args = ["-o=%s" % output.path] + [f.path for f in input]
|
|
|
|
|
|
|
|
ctx.actions.run(
|
|
|
|
inputs = input,
|
|
|
|
outputs = [output],
|
|
|
|
mnemonic = "GoGenericsTemplate",
|
|
|
|
progress_message = "Building Go template %s" % ctx.label,
|
|
|
|
arguments = args,
|
|
|
|
executable = ctx.executable._tool,
|
|
|
|
)
|
|
|
|
|
|
|
|
return struct(
|
|
|
|
types = ctx.attr.types,
|
|
|
|
opt_types = ctx.attr.opt_types,
|
|
|
|
consts = ctx.attr.consts,
|
|
|
|
opt_consts = ctx.attr.opt_consts,
|
|
|
|
deps = ctx.attr.deps,
|
|
|
|
file = output,
|
|
|
|
)
|
2018-04-27 17:37:02 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
Generates a Go template from a set of Go files.
|
|
|
|
|
|
|
|
A Go template is similar to a go library, except that it has certain types that
|
|
|
|
can be replaced before usage. For example, one could define a templatized List
|
|
|
|
struct, whose elements are of type T, then instantiate that template for
|
|
|
|
T=segment, where "segment" is the concrete type.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
name: the name of the template.
|
|
|
|
srcs: the list of source files that comprise the template.
|
|
|
|
types: the list of generic types in the template that are required to be specified.
|
|
|
|
opt_types: the list of generic types in the template that can but aren't required to be specified.
|
|
|
|
consts: the list of constants in the template that are required to be specified.
|
|
|
|
opt_consts: the list of constants in the template that can but aren't required to be specified.
|
|
|
|
deps: the list of dependencies.
|
|
|
|
"""
|
|
|
|
go_template = rule(
|
2018-05-03 20:43:20 +00:00
|
|
|
implementation = _go_template_impl,
|
2018-04-27 17:37:02 +00:00
|
|
|
attrs = {
|
2018-05-03 20:43:20 +00:00
|
|
|
"srcs": attr.label_list(mandatory = True, allow_files = True),
|
2018-04-27 17:37:02 +00:00
|
|
|
"deps": attr.label_list(allow_files = True),
|
|
|
|
"types": attr.string_list(),
|
|
|
|
"opt_types": attr.string_list(),
|
|
|
|
"consts": attr.string_list(),
|
|
|
|
"opt_consts": attr.string_list(),
|
2018-12-28 15:24:56 +00:00
|
|
|
"_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_generics/go_merge")),
|
2018-04-27 17:37:02 +00:00
|
|
|
},
|
|
|
|
outputs = {
|
|
|
|
"out": "%{name}_template.go",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
def _go_template_instance_impl(ctx):
|
2018-05-03 20:43:20 +00:00
|
|
|
template = ctx.attr.template
|
|
|
|
output = ctx.outputs.out
|
|
|
|
|
|
|
|
# Check that all required types are defined.
|
|
|
|
for t in template.types:
|
|
|
|
if t not in ctx.attr.types:
|
|
|
|
fail("Missing value for type %s in %s" % (t, ctx.attr.template.label))
|
|
|
|
|
2018-05-29 21:23:17 +00:00
|
|
|
# Check that all defined types are expected by the template.
|
2018-05-03 20:43:20 +00:00
|
|
|
for t in ctx.attr.types:
|
|
|
|
if (t not in template.types) and (t not in template.opt_types):
|
|
|
|
fail("Type %s it not a parameter to %s" % (t, ctx.attr.template.label))
|
|
|
|
|
2018-05-29 21:23:17 +00:00
|
|
|
# Check that all required consts are defined.
|
2018-05-03 20:43:20 +00:00
|
|
|
for t in template.consts:
|
|
|
|
if t not in ctx.attr.consts:
|
|
|
|
fail("Missing value for constant %s in %s" % (t, ctx.attr.template.label))
|
|
|
|
|
2018-05-29 21:23:17 +00:00
|
|
|
# Check that all defined consts are expected by the template.
|
2018-05-03 20:43:20 +00:00
|
|
|
for t in ctx.attr.consts:
|
|
|
|
if (t not in template.consts) and (t not in template.opt_consts):
|
|
|
|
fail("Const %s it not a parameter to %s" % (t, ctx.attr.template.label))
|
|
|
|
|
2018-05-29 21:23:17 +00:00
|
|
|
# Build the argument list.
|
2018-05-03 20:43:20 +00:00
|
|
|
args = ["-i=%s" % template.file.path, "-o=%s" % output.path]
|
|
|
|
args += ["-p=%s" % ctx.attr.package]
|
|
|
|
|
|
|
|
if len(ctx.attr.prefix) > 0:
|
|
|
|
args += ["-prefix=%s" % ctx.attr.prefix]
|
|
|
|
|
|
|
|
if len(ctx.attr.suffix) > 0:
|
|
|
|
args += ["-suffix=%s" % ctx.attr.suffix]
|
|
|
|
|
|
|
|
args += [("-t=%s=%s" % (p[0], p[1])) for p in ctx.attr.types.items()]
|
|
|
|
args += [("-c=%s=%s" % (p[0], p[1])) for p in ctx.attr.consts.items()]
|
|
|
|
args += [("-import=%s=%s" % (p[0], p[1])) for p in ctx.attr.imports.items()]
|
|
|
|
|
|
|
|
ctx.actions.run(
|
|
|
|
inputs = [template.file],
|
|
|
|
outputs = [output],
|
|
|
|
mnemonic = "GoGenericsInstance",
|
|
|
|
progress_message = "Building Go template instance %s" % ctx.label,
|
|
|
|
arguments = args,
|
|
|
|
executable = ctx.executable._tool,
|
|
|
|
)
|
|
|
|
|
|
|
|
# TODO: How can we get the dependencies out?
|
|
|
|
return struct(
|
|
|
|
files = depset([output]),
|
|
|
|
)
|
2018-04-27 17:37:02 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
Instantiates a Go template by replacing all generic types with concrete ones.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
name: the name of the template instance.
|
|
|
|
template: the label of the template to be instatiated.
|
|
|
|
prefix: a prefix to be added to globals in the template.
|
|
|
|
suffix: a suffix to be added to global in the template.
|
|
|
|
types: the map from generic type names to concrete ones.
|
|
|
|
consts: the map from constant names to their values.
|
|
|
|
imports: the map from imports used in types/consts to their import paths.
|
|
|
|
package: the name of the package the instantiated template will be compiled into.
|
|
|
|
"""
|
|
|
|
go_template_instance = rule(
|
2018-05-03 20:43:20 +00:00
|
|
|
implementation = _go_template_instance_impl,
|
2018-04-27 17:37:02 +00:00
|
|
|
attrs = {
|
2018-05-03 20:43:20 +00:00
|
|
|
"template": attr.label(mandatory = True, providers = ["types"]),
|
2018-04-27 17:37:02 +00:00
|
|
|
"prefix": attr.string(),
|
|
|
|
"suffix": attr.string(),
|
|
|
|
"types": attr.string_dict(),
|
|
|
|
"consts": attr.string_dict(),
|
|
|
|
"imports": attr.string_dict(),
|
|
|
|
"package": attr.string(mandatory = True),
|
|
|
|
"out": attr.output(mandatory = True),
|
2018-05-03 20:43:20 +00:00
|
|
|
"_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_generics")),
|
2018-04-27 17:37:02 +00:00
|
|
|
},
|
|
|
|
)
|