Design: Symbolic Macros #19921
Replies: 7 comments 9 replies
-
Feature request: I often use a macro to permit users to supply an "attribute" that accepts multiple types. The polymorphism makes a nicer developer experience: for example you can provide a label of a file, or give a list of strings or a dictionary that the macro automatically serializes with a |
Beta Was this translation helpful? Give feedback.
-
Side comment: can we get |
Beta Was this translation helpful? Give feedback.
-
This might be a scope increase / different problem, but one challenge I've seen is that macros as they exist today always "leak" their internal state. For example: def my_binary(name):
native.genrule(
name = "%s_genrule" % name,
outs = ["%s.sh" % name],
# ...
)
native.sh_binary(
name = name,
srcs = ["%s.sh" % name],
deps = ["//some:deps"],
) my_binary(name = "bin")
sh_binary(
name = "other_bin",
srcs = ["bin.sh"],
deps = ["//other:deps"],
) In this example, a user is calling Personally I have a habit of accepting Related concern, what about passing through # //pkg/BUILD
load(“//lib:my_macros.bzl”, “my_validated_binary”)
my_validated_binary(
name = "foo",
testonly = True, # Can this implicitly mark `:main` and `:check` targets `testonly`?
) If a submacro target is explicitly given a def _my_validated_binary_impl(name, srcs, deps, create_test, test_runner):
my_binary(
name = "main",
# No `testonly` set, defaults to `my_validated_binary`'s `testonly` value.
)
my_validation_test(
name = "check",
testonly = True, # Always `testonly = True`.
) Feel free to call this out of scope or not the problem at hand, but just a few thoughts of how we can solve some related macro problems with this approach. |
Beta Was this translation helpful? Give feedback.
-
This might be too specific at this stage of feedback but I'll point out that symbolic macro implementation function in the example my_validated_binary = macro(
# Syntax aligns with `rule`, makes sense.
attrs = {
"srcs": attr.label_list(selectable=True),
"deps": attr.label_list(selectable=True),
"create_test": attr.bool(selectable=False),
"test_runner": attr.label(
selectable=False, default="//lib:default_runner"),
},
# ...
)
# How is this order defined? Is it the source order of the `attrs` dictionary? What about when using tricks like
# `dict.update` or `**` expansion?
def _impl(name, srcs, deps, create_test, test_runner):
# ... Similar, what happens when I define a keyword value with a default? def _impl(name, srcs, deps, create_test, test_runner = Label("//lib:default_runner")):
# ... That could be an error, but I think the fact that there's two reasonable-looking approaches to setting a default is inherently a design smell. Since we're trying to follow existing def _impl(loading_ctx):
my_binary(name = “main”, srcs = loading_ctx.attr.srcs, deps = loading_ctx.attr.deps)
if loading_ctx.attr.create_test:
if loading_ctx.attr.test_runner in BANNED_RUNNERS:
fail(“Please avoid banned test runners”)
my_validation_test(name = “check”, srcs = loading_ctx.attr.srcs, deps = loading_ctx.attr.deps,
test_runner = loading_ctx.attr.test_runner) It doesn't look great, and I do wish we could use arguments in |
Beta Was this translation helpful? Give feedback.
-
Macros and queries (and maybe visibility): If the visibility separates public from private targets within a macro, possible future extension is a query operator, that would only display public targets of a macro - to reduce the complexity of the results. (proposal by @murali42) |
Beta Was this translation helpful? Give feedback.
-
@dgp1130 FWIW I completely agree with macros and leaking their internal rules. There is an internal proposal around that (e.g. supporting things like //visibility:macro_internal). There are several nuances though
All that said... coming up with a solution for visibility could be done later? |
Beta Was this translation helpful? Give feedback.
-
FWIW, I think we should add
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Status update, Oct 2024: This is implemented and will be released with Bazel 8.0.
Symbolic Macros are a proposed new feature to make macros easier to write and less brittle. I wrote a 2-page* doc summarizing their main properties. A formal design review will come in the future, after we are further along in the prototype.
* (If you don't count the appendix)
Beta Was this translation helpful? Give feedback.
All reactions