Skip to content

Commit 47219d4

Browse files
committed
sw_arch_doc: replace cinclude2dot with new python alternative. benefits:
- finer-grained control over the set of input directories - output is more deterministic (deduplicated and sorted)
1 parent 45cc940 commit 47219d4

File tree

10 files changed

+650
-461
lines changed

10 files changed

+650
-461
lines changed

build_app.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ else
4444
MYAPP_EXTRA_CONF=""
4545
# adding this next line here (rather than in run_all_tests.sh), because we think
4646
# of the graph-generation as more of a "build" step than a "test":
47-
$DIR/sw_arch_doc/generate_graph.sh ${DIR}/src/ ${DIR}/
47+
$DIR/sw_arch_doc/generate_graph.sh -s ${DIR}/src/ -f ${DIR}/ -x $DIR/sw_arch_doc/excludes.txt
4848

4949
# Next step done here (rather than inside generate_graph.sh) because the
5050
# graph script does not need to be "git aware".

build_cmake_app.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ else
5858
MYAPP_EXTRA_CONF=()
5959
# adding this next line here (rather than in run_all_tests.sh), because we think
6060
# of the graph-generation as more of a "build" step than a "test":
61-
$DIR/sw_arch_doc/generate_graph.sh ${DIR}/src/ ${DIR}/
61+
$DIR/sw_arch_doc/generate_graph.sh -s ${DIR}/src/ -f ${DIR}/ -x $DIR/sw_arch_doc/excludes.txt
6262

6363
# Next step done here (rather than inside generate_graph.sh) because the
6464
# graph script does not need to be "git aware".

cookiecutter/cookiecutter.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"email": "[email protected]",
88
"year": "2021",
99
"_copy_without_render": [
10-
"*third_party"
10+
"*third_party",
11+
"sw_arch_doc"
1112
]
1213
}

sw_arch_doc/README.md

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,24 @@
22

33
### What is this?
44

5-
This is a wrapper script that simplifies usage of `cinclude2dot`.
5+
This folder has scripts for C/C++ dependency graphing.
66

7-
Credit for `cinclude2dot` belongs to https://www.flourish.org/cinclude2dot/
7+
These scripts use the [Graphviz](https://graphviz.org/) `dot` tool to produce an
8+
SVG image visualizing the header-include graph of a C/C++ codebase.
9+
10+
You can apply these scripts to your entire C/C++ codebase, or you can visualize
11+
any subset of your code, bounding the input to specific subdirectories of your
12+
codebase.
13+
14+
Original inspiration taken from https://www.flourish.org/cinclude2dot/, but here
15+
we use a novel implementation in python, with different cli options and slightly
16+
different output (though the output of both is in the `dot` graphviz language).
817

918
You can copy this `sw_arch_doc` folder into any project (or just copy it
10-
somewhere on your system) and run the script against any folder of C/C++ source
11-
files you like.
19+
somewhere on your system) and run the script against any folder or set of
20+
folders of C/C++ source files you like.
1221

13-
When choosing which folder of source files to diagram, we recommend not
22+
When choosing which folder(s) of source files to diagram, we recommend not
1423
attempting to diagram more than ~100 files at a time, or the diagram will be
1524
very dense and hard to read.
1625

@@ -24,13 +33,18 @@ apply added styling to your graph(s).
2433
**TL;DR**
2534

2635
```
27-
generate_graph.sh ${PATH_TO_SOURCES} ${PATH_TO_HEADERS}
36+
./generate_graph.sh -s ${SOURCE_PATH_1} ${SOURCE_PATH_2} -x ${TEXT_FILE_WITH_YOUR_EXCLUDES}
2837
```
2938

3039
The generated diagram will be: `all_src.svg`
3140

3241
**Required:** `dot` (from the graphviz package) must be installed on your sytem.
3342

43+
For detailed help, run:
44+
```
45+
./generate_graph.sh --help
46+
```
47+
3448
If you prefer to alter the appearance of the graph by using different (or
3549
additional) graph attributes, edit the file `dot_head.part` with the
3650
[graphviz attributes](https://graphviz.org/doc/info/attrs.html) that you
@@ -45,22 +59,22 @@ your preferred graph attributes.
4559
#### Exclusions
4660

4761
Many projects have header files such as `defs.h` or `utils.h`, and it is usually
48-
desireable to exclude these headers from the generated diagram.
62+
desirable to exclude these headers from the generated diagram.
4963

50-
That is the goal of the lines near the bottom of `generate_graph.sh` that look as follows:
64+
For any/all header(s) you wish to ignore and exclude from the visualization,
65+
list the *stem* of the header name in a file such as `excludes.txt`, listing one
66+
*stem* name per line. Pass your `excludes.txt` to the script like so:
5167

5268
```
53-
"${THESED}" -i "/\"\bcli_options\b\"/d" ${ARCH_DOC_DIR}/all_src.dot
54-
"${THESED}" -i "/\"\blogging_tags\b\"/d" ${ARCH_DOC_DIR}/all_src.dot
55-
"${THESED}" -i "/\"\bresource_helper\b\"/d" ${ARCH_DOC_DIR}/all_src.dot
69+
./generate_graph.sh -s ${SOURCE_PATH_1} ${SOURCE_PATH_2} -x excludes.txt
5670
```
5771

58-
Add more lines as needed for your project.
72+
See the example `excludes.txt` in this folder.
5973

6074
For example, to remove `defs.h` from the diagram, you would add the following line:
6175

6276
```
63-
"${THESED}" -i "/\"\bdefs\b\"/d" ${ARCH_DOC_DIR}/all_src.dot
77+
defs
6478
```
6579

6680
### My diagram looks like a tangle of spaghetti. Now what?
@@ -69,9 +83,9 @@ There are several reasons that can cause you to end up with spaghetti.
6983

7084
First, we recommend not attempting to diagram more than ~100 files at a
7185
time. This means you should make sure that the number of C/C++ source files
72-
residing under whatever directory you chose as the `${PATH_TO_SOURCES}` argument
73-
does not exceed 100 total source files. When counting files under
74-
`${PATH_TO_SOURCES}`, any files in nested subdirectories count, too!
86+
residing under whatever directory or directories you chose as the `-s` (or
87+
long-name `--src-dir`) argument does not exceed 100 total source files. When
88+
counting files under `--src-dir`, any files in nested subdirectories count, too!
7589

7690
Second, please recall the advice above regarding explicit exclusions for common
7791
files such as `defs.h`. If your generated diagram is large, you can usually spot
@@ -91,6 +105,6 @@ such as [deheader](http://www.catb.org/~esr/deheader/). After you identify and
91105
remove spurious `#include` lines from your sources, then re-run
92106
`generate_graph.sh` and you should see a smaller diagram.
93107

94-
You might find that generating the diagram periodically (during CI, even!) gives
95-
you a good way to notice spurious `#include` edges and stay on top of your
108+
You might find that generating the diagram regularly (during every build, even!)
109+
gives you a good way to notice spurious `#include` edges and stay on top of your
96110
header hygiene.

sw_arch_doc/all_src.dot

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,94 @@ digraph "source tree" {
44
fontsize="16";
55
fontname="Helvetica";
66
clusterrank="local";
7-
"event_filter" -> "every_so_often"
8-
"lib" -> "example_shared"
9-
"lib" -> "quarantined_awaiting_warning_fixes"
10-
"main" -> "ios_log_redirect"
11-
"main" -> "logger"
12-
"main" -> "view_model_collection"
13-
"quarantined_awaiting_warning_fixes" -> "sample_header_exempt_from_warnings"
14-
"timer_service_test" -> "timer_service"
15-
"view_model_collection" -> "event_filter"
16-
"view_model_collection" -> "gui_tests"
17-
"view_model_collection" -> "lib"
18-
"view_model_collection" -> "qml_message_interceptor"
7+
subgraph "cluster_box_dir_lib_app" {
8+
label="lib_app";
9+
"cli_options";
10+
}
11+
"cli_options"
12+
subgraph "cluster_box_dir_app" {
13+
label="app";
14+
"event_filter";
15+
}
16+
"event_filter"
17+
"event_filter" -> "every_so_often"
18+
subgraph "cluster_box_dir_util" {
19+
label="util";
20+
"every_so_often";
21+
}
22+
"every_so_often"
23+
subgraph "cluster_box_dir_lib_example_shared" {
24+
label="lib_example_shared";
25+
"example_shared";
26+
}
27+
"example_shared"
28+
subgraph "cluster_box_dir_app" {
29+
label="app";
30+
"gui_tests";
31+
}
32+
"gui_tests"
33+
subgraph "cluster_box_dir_lib_app" {
34+
label="lib_app";
35+
"lib";
36+
}
37+
"lib"
38+
"lib" -> "example_shared"
39+
"lib" -> "quarantined_awaiting_warning_fixes"
40+
subgraph "cluster_box_dir_lib_app" {
41+
label="lib_app";
42+
"logging_tags";
43+
}
44+
"logging_tags"
45+
"logging_tags" -> "cli_options"
46+
subgraph "cluster_box_dir_app" {
47+
label="app";
48+
"main";
49+
}
50+
"main"
51+
"main" -> "cli_options"
52+
"main" -> "view_model_collection"
53+
subgraph "cluster_box_dir_util" {
54+
label="util";
55+
"qml_message_interceptor";
56+
}
57+
"qml_message_interceptor"
58+
subgraph "cluster_box_dir_lib_app" {
59+
label="lib_app";
60+
"quarantined_awaiting_warning_fixes";
61+
}
62+
"quarantined_awaiting_warning_fixes"
63+
subgraph "cluster_box_dir_libstyles" {
64+
label="libstyles";
65+
"resource_helper";
66+
}
67+
"resource_helper"
68+
subgraph "cluster_box_dir_util" {
69+
label="util";
70+
"timer_service";
71+
}
72+
"timer_service"
73+
subgraph "cluster_box_dir_tests" {
74+
label="tests";
75+
"timer_service_test";
76+
}
77+
"timer_service_test"
78+
"timer_service_test" -> "timer_service"
79+
subgraph "cluster_box_dir_util" {
80+
label="util";
81+
"usage_log_t";
82+
}
83+
"usage_log_t"
84+
subgraph "cluster_box_dir_app" {
85+
label="app";
86+
"view_model_collection";
87+
}
88+
"view_model_collection"
89+
"view_model_collection" -> "cli_options"
90+
"view_model_collection" -> "event_filter"
91+
"view_model_collection" -> "gui_tests"
92+
"view_model_collection" -> "lib"
93+
"view_model_collection" -> "logging_tags"
94+
"view_model_collection" -> "qml_message_interceptor"
95+
"view_model_collection" -> "resource_helper"
96+
"view_model_collection" -> "usage_log_t"
1997
}

0 commit comments

Comments
 (0)