- Depend on what you use (DWYU)
- Getting started
- Applying automatic fixes
- Assumptions of use
- Supported Platforms
- Known limitations
- Troubleshooting
- Alternatives to DWYU
- Versioning
- Contributing
- License
DWYU is a Bazel aspect for C++ projects making sure the headers your Bazel targets are using are aligned with their dependency lists.
DWYUs enforces the design principle:
A cc_* target X shall depend directly on the targets providing the header files which are included in the source code of X.
The main features are:
- Finding include statements which are not available through a direct dependency, aka preventing to rely on transitive dependencies for includes.
- Finding unused dependencies.
- Given one uses
implementation_deps, making sure one distinguishes properly between public and private dependencies forcc_librarytargets. This has to be explicitly enabled. See the aspect documentation for further details.
More information about the idea behind DWYU and the implementation of the project is available in the docs.
Choose a release from the release page and follow the instructions.
To use a specific commit, put the following into your MODULE.bazel file
bazel_dep(name = "depend_on_what_you_use")
git_override(
module_name = "depend_on_what_you_use",
commit = <commit_you_are_interested_in>,
remote = "https://github.com/martis42/depend_on_what_you_use",
)The DWYU aspect is created in your project by a factory function offering various options to configure the aspect. Various illustrations for configuring and using the DWYU aspect can be seen in the examples.
Example .bzl file creating a DWYU aspect with default configuration:
load("@depend_on_what_you_use//dwyu/cc:defs.bzl", "dwyu_cc_aspect_factory")
your_dwyu_aspect = dwyu_cc_aspect_factory()Assuming you created the DWYU aspect in file //:aspect.bzl, execute it on a target pattern:
bazel build --aspects=//:aspect.bzl%your_dwyu_aspect --output_groups=dwyu <target_pattern>
If no problem is found, the command will return successfully without further output.
If a problem is detected, the build command will fail with an error and a description of the problem will be printed in the terminal.
For example:
================================================================================
DWYU analyzing: '<analyzed_target>'
Result: Failure
Unused dependencies in 'deps' (none of their headers are referenced):
Dependency='//some/target/with_an_unused:dependency'
===============================================================================
Hint: Using --keep_going allows you to see all existing errors at once instead of the analysis aborting on the first detected issue.
You can invoke the aspect from within a rule. This can be useful to make the execution part of a bazel build on dedicated targets without having to manually execute the longish aspect build command.
The Bazel documentation for invoking an aspect from within a rule can be found here.
This is demonstrated in the rule_using_dwyu example.
Warning
Please note that the tool cannot guarantee that your build is not being broken by the changes. Always make sure your project is still valid after the changes and review the performed changes.
Note
This tool is executing Bazel commands.
If one needs to configure bazel commands with custom options in your workspace, please have a look at the --bazel-args and --bazel-startup-args options of this tool.
DWYU offers a tool to automatically fix some detected problems. The general workflow is the following:
- Execute DWYU on your workspace. DWYU will create report files containing information about discovered problems in the Bazel output directory.
- Execute
bazel run @depend_on_what_you_use//dwyu/apply_fixes:apply_fixes -- <your_options>. The tool discovers the report files generated in the previous step and gathers the problems for which a fix is available. Then, buildozer is utilized to adapt the BUILD files in your workspace.
We recommend:
- Execute the DWYU analysis build with
--keep_goingto generate the DWYU reports to find all issues at once. - Pipe the terminal output from executing DWYU into a file.
Then, provide this log file to
@depend_on_what_you_use//dwyu/apply_fixes:apply_fixesvia the--dwyu-log-fileoption. This is the fastest and most robust option to make the DWYU reports available to theapply_fixestool.
The apply_fixes tool requires you to explicitly choose which kind or errors you want to be fixed.
You can see the full command line interface and more information about the script behavior and limitations by executing:
bazel run @depend_on_what_you_use//dwyu/apply_fixes:apply_fixes -- --help
If you are not using --dwyu-log-file, the apply_fixes tool searches by itself for the DWYU reports in the output base, which can be slow for large workspaces.
Unfortunately, the tool cannot promise perfect results due to various constraints:
- If alias targets are involved, this cannot be processed properly. Alias targets are resolved to their actual target before the DWYU aspect is running. Thus, the DWYU report file contains the actual targets in its report and buildozer is not able to modify the BUILD files containing the alias name.
- Buildozer is working on the plain BUILD files as a user would see them in the editor. Meaning without alias resolution or macro expansion. Consequently, buildozer cannot work on targets which are generated inside a macro or whose name is constructed.
- Adding missing direct dependencies is based on a heuristic and not guaranteed to find the correct dependency.
DWYU assumes the code under inspection compiles with the Bazel configuration used to execute DWYU (e.g. setting --config=foo).
There is no guarantee DWYU will do something meaningful for non compilable code.
There shall not be multiple header files in the dependency tree of a target matching an include statement. Even if analyzing the code works initially, it might break at any time if the ordering of paths in the analysis changes.
Linux is fully supported.
All tests and quality checks run on GitHub Ubuntu workers.
Macos and Windows are supported on a best effort basis.
All our integration tests run on GitHub Macos and Windows workers.
Bugs we can reproduce via the CI workers with reasonable effort will be fixed.
| Tool | Constraints |
|---|---|
| C++ | Minimum required C++ standard is C++11. |
| Bazel | Minimum required version is 7.6.0. We test all supported major versions and the rolling release. |
| Tool | Constraints |
|---|---|
| Python | Integration tests check 3.10. |
| Bazel | No known constraint. Integration tests check the Bazel version defined in .bazelversion. |
DWYU has some limitations. You find the details about those in these docs.
When encountering problems while using DWYU, you find common problems and suggested solutions in these docs.
To make sure no headers from transitive are used you can use Layering check with Clang, which is natively supported by Bazel. An example for a CC toolchain supporting this feature is https://github.com/bazel-contrib/toolchains_llvm. The main benefit of this approach is it being directly integrated into Bazel without need of further tooling like DWYU.
Still, there are reasons to consider using DWYU instead of or in addition to layering_check:
- DWYU does not require a full compilation, it only executes the preprocessing step.
- DWYU is able to analyze header only libraries.
- DWYU is not limited to LLVM based toolchains (
layering_checkis based on LLVM's implementation of modules). - DWYU detects unused dependencies.
- DWYU allows optimizing the usage of implementation_deps.
- DWYU offers automatic fixes for detected issues.
Gazelle is a tool automatically creating BUILD files for your code.
rules_cc does not offer a standard Gazelle plugin for C/C++.
However, another party open sourced gazelle_cc to provide Gazelle support for C/C++.
Automatically generating correct BUILD files based on your source code is a more efficient approach compared to executing DWYU regularly to make sure no error was introduced.
A reason for using DWYU instead of gazelle_cc can be if your project uses conditional include statements based on custom conditions.
According to their documentation, gazelle_cc is only supporting <os> and <arch> based conditional includes.
This project uses semantic versioning.
The following things specifically are not considered breaking changes:
- The report files DWYU generates to facilitate running automatic fixes are considered an implementation detail.
- Raising the minimum required version for a dependency or Bazel.
See Contributing.
Copyright © 2022-present, Martin Medler.
This project licensed under the MIT license.
This projects references several other projects which each have individual licenses. See the content of third_party and MODULE.bazel for all references to other projects.