facebook / facebook/buck2

How do I carry around dynamic dependencies on e.g. headers?

Open
#352 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
4.4k
Forks
394
PR merge metrics
No merged PRs in 30d

Description

Thanks for the great work. I have a design question for a problem I've been trying to solve. I'm new to buck2 and I'm not a previous Bazel or buck user, so it's been a little rough getting started. If I make any conceptual mistakes, please point them out :)

For context, this is without the prelude -- I would like to keep much simpler rules on hand that don't need to be as flexible and get better at implementing rules.

I have a project made up a bunch of logical groupings of C files, created by a rule `c_inputs` that returns the provider `CInputsInfo`:

```starlark
CInputsInfo = provider(
doc = "Info on a set of C inputs.",
fields = [
"srcs",
"hdrs", # dict mapping { str (header path): source }, globbed from all qualified_inc_paths
"qualified_inc_paths",
]
)
```

Downstream rules consuming `CInputsInfo` might compile the sources into a binary, run a linter on them, and so on.

I want to have a dynamic dependency on the headers consumed by these C files, generated by the compiler (`-M` family of options in gcc/clang). I would like to do the actual dependency generation only once and then get to use the sources many times. I see a couple of general approaches to doing this:

1. `dynamic_outputs`: I implemented this for one use case (`c_objects`), and it works well, but I'm having trouble seeing how I would do this for `c_inputs` because we wouldn't yet have an artifact to bind.

```starlark
def _c_objects_impl(ctx: "context"):
...

for src in ctx.attrs.inputs[CInputsInfo].srcs:
...

def compile_with_header_deps(ctx, artifacts, outputs, dep_file_json=dep_file_json, object=object, src=src):
cmd = cmd_args([compiler, src, flags, inc_flags, "-c", "-o", outputs[object].as_output()])

# for every header in the list, add a hidden dependency on it to the cmd
dep_header_list = artifacts[dep_file_json].read_json()
for header in dep_header_list:
cmd.hidden(ctx.attrs.inputs[CInputsInfo].hdrs[header])

ctx.actions.run(cmd, category = "compile", identifier = str(outputs[object]))

ctx.actions.dynamic_output(dynamic=[dep_file_json], inputs=[src], outputs=[object], f=compile_with_header_deps)
```
2. `dep_file`: Unless I'm mistaken, these can't be used across actions.

Do you have any ideas on how to approach this kind of thing in buck2?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.