-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
deps vs. exported_deps for c++? #335
Comments
My recommendation has been that if you are exposing something from your dependencies in a way that your dependents are going to need it, then you should export that dependency. I think trying to avoid exported_deps entirely would be too painful for the small value it gives you. I could see that calculus being different if you had a system that could automatically keep your deps up-to-date based on the contents of the sources. |
Do you think buck2 could gain the ability to report unneeded dependencies? It seems possible in limited scenarios. For example, if the only thing a dependency exports is public include directories, and buck2's internal dependency analysis determines that no file from that path is ever loaded, it could warn (or even error) that there is an unnecessary dependency. From here, there may be opt-in ways to take this further. For example, maybe there could be something like Just thinking out loud though, it might trigger too infrequently to be worth the development effort. |
Another kind of warning / error that might be useful. If B has an exported_dep of A, and C has a dep of B, then C doesn't need to explicitly specify a dep on A to make it work, even if C directly (not just transitively) relies on A. Is there any way to detect this during analysis and require that C explicitly specify the dep? Example:
And here are a, b, c, and d source files:
In theory, I think buck2 has enough information to be able to enforce this. But I tested this out, and if I run |
It's quite easy for BXL to traverse the set of targets and introspect them. It would be entirely feasible to implement a sort of linter atop that. |
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: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 usedeps
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 usingexported_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.
The text was updated successfully, but these errors were encountered: