clang-include-graph
provides several simple commands for analyzing and visualizing C++ project include graphs.
Main features include:
- Generates correct (topological) inclusion order of all includes of the project or a single translation unit
- Prints include graph in several formats into stdout:
- Topologically ordered include list
- Tree format
- Include graph cycles list
- Graphviz
- PlantUML
- Handles cyclic include graphs
sudo add-apt-repository ppa:bkryza/clang-include-graph
sudo apt update
sudo apt install clang-include-graph
First make sure that you have the following dependencies installed:
# Ubuntu (clang version will vary depending on Ubuntu version)
apt install git make gcc g++ cmake clang-12 libclang-12-dev libclang-cpp12-dev libboost-graph1.71-dev libboost-filesystem1.71-dev libboost-test1.71-dev libboost-program-options1.71-dev
Then proceed with building the sources:
git clone https://github.com/bkryza/clang-include-graph
cd clang-include-graph
# Please note that top level Makefile is just a convenience wrapper for CMake
make release
release/clang-include-graph --help
# To build using a specific installed version of LLVM use:
LLVM_CONFIG_PATH=/usr/bin/llvm-config-13 make release
export PATH=$PATH:$PWD/release
clang-include-graph
requires an up-to-date
compile_commands.json
file, containing the list of commands used for compiling the source code.
Nowadays, this file can be generated rather easily using multiple methods:
- For CMake projects, simply invoke the
cmake
command ascmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ...
- For Make projects checkout compiledb or Bear
- For Boost-based projects try commands_to_compilation_database
- For SCons, invoke
compilation_db
tool (requires SCons > 4.0.0)
clang-include-graph
provides the following command line options:
❯ release/clang-include-graph -h
clang-include-graph options:
-h [ --help ] Print help message and exit
-V [ --version ] Print program version and exit
-v [ --verbose ] Print verbose information during
processing
-d [ --compilation-database-dir ] arg Path to compilation database directory
(default $PWD)
-u [ --translation-unit ] arg Process a single source file from
compilation database
-r [ --relative-to ] arg Generate paths relative to path (except
for system headers)
-n [ --names-only ] Print only file names
-l [ --relative-only ] Include only files relative to
'relative-to' directory
-s [ --topological-sort ] Print output includes and translation
units in topologicalsort order
-t [ --tree ] Print include graph in tree form
-c [ --cycles ] Print include graph cycles, if any
-g [ --graphviz ] Print include graph in GraphViz format
-p [ --plantuml ] Print include graph in PlantUML format
The examples below assume the following commands were executed before:
cd clang-include-graph
make release
❯ release/clang-include-graph --compilation-database-dir release
/usr/include/boost/config/user.hpp
/usr/include/boost/config/detail/select_compiler_config.hpp
/usr/include/boost/config/compiler/clang.hpp
/usr/include/x86_64-linux-gnu/bits/wordsize.h
/usr/include/x86_64-linux-gnu/bits/timesize.h
/usr/include/features-time64.h
/usr/include/stdc-predef.h
/usr/include/x86_64-linux-gnu/bits/long-double.h
/usr/include/x86_64-linux-gnu/sys/cdefs.h
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
/usr/include/x86_64-linux-gnu/gnu/stubs.h
...
/usr/include/boost/mpl/aux_/unwrap.hpp
/usr/include/boost/utility/value_init.hpp
/usr/include/boost/mpl/for_each.hpp
/usr/include/boost/test/tree/test_case_template.hpp
/usr/include/boost/test/tree/global_fixture.hpp
/usr/include/boost/test/unit_test_suite.hpp
/usr/include/boost/test/unit_test.hpp
/home/bartek/devel/clang-include-graph/tests/test_utils.h
/home/bartek/devel/clang-include-graph/tests/test_tree_printer.cc
/home/bartek/devel/clang-include-graph/tests/test_cycles_printer.cc
/home/bartek/devel/clang-include-graph/tests/test_topological_sort_printer.cc
❯ release/clang-include-graph -d release -u src/main.cc -r . -l --tree
src/main.cc
├── src/config.h
│ └── src/util.h
├── src/include_graph.h
│ └── src/config.h
│ └── src/util.h
├── src/include_graph_cycles_printer.h
│ └── src/include_graph_printer.h
│ ├── src/include_graph.h
│ │ └── src/config.h
│ │ └── src/util.h
│ └── src/path_printer.h
│ └── src/config.h
│ └── src/util.h
├── src/include_graph_graphviz_printer.h
│ └── src/include_graph_printer.h
│ ├── src/include_graph.h
│ │ └── src/config.h
│ │ └── src/util.h
│ └── src/path_printer.h
│ └── src/config.h
│ └── src/util.h
├── src/include_graph_parser.h
│ ├── src/config.h
│ │ └── src/util.h
│ └── src/include_graph.h
│ └── src/config.h
│ └── src/util.h
├── src/include_graph_topological_sort_printer.h
│ └── src/include_graph_printer.h
│ ├── src/include_graph.h
│ │ └── src/config.h
│ │ └── src/util.h
│ └── src/path_printer.h
│ └── src/config.h
│ └── src/util.h
└── src/include_graph_tree_printer.h
└── src/include_graph_printer.h
├── src/include_graph.h
│ └── src/config.h
│ └── src/util.h
└── src/path_printer.h
└── src/config.h
└── src/util.h
❯ release/clang-include-graph --compilation-database-dir release --relative-to src --relative-only --graphviz > /tmp/include.dot
❯ dot -Tpng -o/tmp/include.png /tmp/include.dot
❯ release/clang-include-graph --compilation-database-dir release -u src/util.cc --cycles
[
/usr/include/boost/preprocessor/control/while.hpp
/usr/include/boost/preprocessor/list/fold_left.hpp
]
[
/usr/include/boost/preprocessor/control/while.hpp
/usr/include/boost/preprocessor/list/fold_right.hpp
/usr/include/boost/preprocessor/list/detail/fold_right.hpp
/usr/include/boost/preprocessor/list/fold_left.hpp
]
[
/usr/include/boost/preprocessor/control/while.hpp
/usr/include/boost/preprocessor/list/fold_right.hpp
/usr/include/boost/preprocessor/list/detail/fold_right.hpp
/usr/include/boost/preprocessor/list/reverse.hpp
/usr/include/boost/preprocessor/list/fold_left.hpp
]
[
/usr/include/boost/preprocessor/control/while.hpp
/usr/include/boost/preprocessor/list/fold_right.hpp
]
❯ release/clang-include-graph --compilation-database-dir release -r . -u src/include_graph_tree_printer.cc -p -l
@startuml
file "src/include_graph_tree_printer.h" as F_0
file "src/include_graph_tree_printer.cc" as F_1
file "src/include_graph_printer.h" as F_2
file "src/include_graph.h" as F_3
file "src/config.h" as F_4
file "src/util.h" as F_5
file "src/path_printer.h" as F_6
F_0 --> F_2
F_1 --> F_0
F_2 --> F_3
F_2 --> F_6
F_3 --> F_4
F_4 --> F_5
F_6 --> F_4
@enduml
❯ release/clang-include-graph --compilation-database-dir release --translation-unit src/util.cc | wc -l
572
Copyright 2022-present Bartek Kryza <[email protected]>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.