deps vs. exported_deps for c++?
- Dominant language
- Rust
- Stars
- 4.4k
- Forks
- 394
- PR merge metrics
- No merged PRs in 30d
Description
Semantically I understand the difference, but I'm curious what the thinking is about best practices? Consider the following example. We'll assume for this example that `b/b.h` looks like this:
```
// b.h
#include "a/a.h"
```
```
cxx_library(
name="a",
public_include_directories=["a/include"],
headers=["a/include/a/a.h"],
cxx_library(
name="b",
public_include_directories=["b/include"],
headers=["b/include/b/b.h"],
deps=["//:a"],
# Is this preferable?
# exported_deps=["//:a"]
cxx_library(
name="c",
public_include_directories=["c/include"],
headers=["c/include/c/c.h"],
deps=[
"//:b",
# This is required unless we uncomment the exported dep in b
"//:a",
]
```
So this is more of a philisophical question. If we use `exported_deps`, targets carry their dependencies with them. It makes maintenance a lot easier. Adding a dependency from c to b requires doing exactly that: Add a dependency to b. If we use `deps` instead requires a potentially never-ending cycle of "build / interpret-error-message / add-dependency", which is difficult to scale. Worse though is that if we aren't using `exported_deps`, *removing* the dependency from b to a requires you to remember that you need to also remove it from c. And I don't think buck2 has the ability to warn you about superfluous dependencies (I think this isn't a solvable problem in general).
But I know there's argument for trying to avoid exported_deps, and this methodology is used at scale (I think google internally operates like this?), the thinking being that requireing it to be explicit leads to better code hygiene and more awareness of your dependency chains.
Curious to hear others' thoughts and what your experience has been at scale. My gut tells me you want to be using exported_deps because of the maintenance on large scale projects.
Contributor guide
Assessment
This issue has not been assessed yet.