When is my BXL script cached?
The entire BXL script is represented as a single node on the DICE graph (Buck2’s internal dependency graph). When the script’s input changes, the entire node is invalidated and needs to be recomputed. For example, if a BXL function calls uquery, then uses the result to do a cquery and then a build, if Buck2 detects that any of the recorded calls to uquery, cquery, and build changes, then the entire BXL script will be reran. The computations themselves (uquery, cquery, and build) will still be incrementally evaluated via DICE, so we are not rerunning every computation entirely within the BXL.
When the BXL script creates artifacts and ensures them, those artifacts are cached separately in an action outside of the BXL execution. This means that the artifacts produced by BXL are cached separately from the BXL script itself, much like the computations within a BXL.
During 2023, there is a plan to add finer grain incrementality to make better use of DICE’s existing incrementality support.
What’s the difference between
ctx.output.print()writes items to stdout by buck2 even when the script is cached. Items written to the output stream are considered to be the results of a BXL script, which will be displayed to stdout by buck2 even when the script is cached.
print()is offered by Starlark via the stdlib. This prints anything you want but won’t be provided to stdout at the end of a BXL script. These can be used to print to stderr. NOTE:
print()statements don't show up if the script has been cached.
What do I need to know about ensured artifacts
ensured_artifact prints out the relative or absolute path via
ctx.output.print(), depending on if called with
but will print out
<ensured artifact bound to <some path>> via
This is intentional because when the ensured artifact is created within BXL, it has not been materialized yet. It will be materialized after the BXL script finishes executing, and Buck2 core performs some additional actions after the BXL script.
This is a safeguard to prevent people from misusing the artifact path and passing it into an action without the artifact having been materialized or passing an absolute path into RE, which can actually mess up RE and render the action not shareable across users. In addition, it makes these actions separately cacheable from the BXL execution.
What is the difference between dynamic outputs and anon targets?
Dynamic outputs are meant for
dynamic dependencies. The context
type is a
bxl_ctx. Dynamic outputs are ran asynchronously outside of the BXL
Anon targets are meant for sharing work betwen multiple BXLs. The context type
is a normal rule analysis
context. Anon targets are
await-ed inline with
your BXL function.
Can I mutate types returned by BXL APIs?
The data types produced by BXL API calls are always immutable.
What is run synchronously vs asynchronously?
Starlark itself is run synchronously. However, certain BXL APIs are evaluated asynchronously.
If you pass in multiple inputs to builds, queries, or analyses, the execution of these API calls will be blocking, but the inputs themselves will be evaluated in parallel within the execution.
Ensuring artifacts, dynamic outputs, anon targets, and resolving promises will happen after the Starlark script is executed.