BXL and Dynamic Outputs
Dynamic output
When declaring dynamic outputs within
a BXL script, the dynamic lambda for is created with a bxl_ctx
, which means
that you can do things like run analysis or queries to inspect the build graph
from within the dynamic lambda.
You may declare multiple dynamic outputs within a single BXL script, or declare nested dynamic outputs. Dynamic outputs are run asynchronously after the BXL evaluation.
Limitations
ctx.output
is not available from a dynamic lambda. This means you can’t ensure artifacts or print cached outputs within a dynamic lambda.- Error messages from skipping incompatible targets are only emitted to the console, and not cached in the stderr
build()
is not available from a dynamic lambdabxl_actions
in a dynamic lambda always inherits the execution platform resolution of the root/parent BXL.- The expected usage of
bxl_actions
from within a dynamic lambda is to instantiate it without any named parameters, but theexec_deps
andtoolchains
of the execution platform resolution are accessible, and return the same values as the root/parent BXL
- The expected usage of
- Profiling is not hooked up to dynamic BXL context
Silly example
This is a silly example of creating a dynamic output which reads some
query_params
input, calls some BXL functions like uquery
,
configured_targets
to get the resolved attributes of a target node, and then
writes the attributes to an output file.
def _impl_dynamic_output(ctx):
actions = ctx.bxl_actions().actions
# Declare some input here to read within the lambda
query_params = actions.write_json("query_params", {"rule_type": "apple_bundle", "universe": "fbcode//buck2/tests/..."})
# Dynamic lambda's output artifact
resolved_attrs = actions.declare_output("resolved_attrs")
# Dynamic lambda function to be used in the dynamic_output
def my_deferred(ctx, artifacts, outputs):
# Read the input, then do some BXL things here
params = artifacts[query_params].read_json()
target = ctx.uquery().kind(params["rule_type"], params["universe"])[0]
node = ctx.configured_targets(target.label)
eager_attrs = node.resolved_attrs_eager(ctx)
# Dynamic BXL context's `bxl_actions` does not take in named parameters because it inherits the exec platform resolution from the root/parent BXL. If the root BXL's `bxl_actions` were created with exec deps/toolchains, you can access them using `exec_deps` and `toolchains` attributes here
ctx.bxl_actions().actions.write(outputs[resolved_attrs], str(eager_attrs))
actions.dynamic_output(
dynamic = [query_params],
inputs = [],
outputs = [
resolved_attrs,
],
f = my_deferred,
)
ctx.output.print(ctx.output.ensure(resolved_attrs).abs_path())
dynamic_output_example = bxl_main(
impl = _impl_dynamic_output,
cli_args = {
},
)