Skip to content

Commit 348422d

Browse files
committed
doc: fix graphviz scanning and processing
The doc build process copies files using script/extract-content.py from outside of the doc/ folder (specifically content in the tools/ folders). The script was not copying graphviz directive files. This has been fixed and the embedded graphviz directives are not (properly) stored in separate image/*.dot files. Note the extract-content.py file is derived from the Zephyr project. Signed-off-by: David B. Kinder <david.b.kinder@intel.com>
1 parent e49c42d commit 348422d

File tree

8 files changed

+153
-98
lines changed

8 files changed

+153
-98
lines changed

doc/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ doxy:
4242
$(Q)(cat acrn.doxyfile) | doxygen - > doc.log 2>&1
4343

4444
content:
45-
$(Q)scripts/extract_content.py
45+
$(Q)scripts/extract_content.py . tools
4646

4747
kconfig:
4848
$(Q)srctree=../hypervisor \

doc/scripts/extract_content.py

Lines changed: 87 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,113 @@
11
#!/usr/bin/env python3
22
#
3+
# Copyright (c) 2018, Nordic Semiconductor ASA
34
# Copyright (c) 2017, Intel Corporation
45
#
56
# SPDX-License-Identifier: Apache-2.0
67

7-
# Script to move docs from different places into the doc directory
8+
# Very quick script to move docs from different places into the doc directory
89
# to fix the website and external links
910

11+
import argparse
12+
import errno
13+
import filecmp
14+
import fnmatch
1015
import os
11-
import shutil
1216
import re
17+
import shutil
1318
import sys
14-
import fnmatch
15-
16-
17-
# direcories to search for .rst files
18-
CONTENT_DIRS = ["tools"]
1919

2020
# directives to parse for included files
21-
DIRECTIVES = ["figure","include","image","literalinclude"]
21+
DIRECTIVES = ["figure","include","image","literalinclude", "graphviz"]
22+
23+
ZEPHYR_BASE = "../"
24+
ZEPHYR_BUILD = None
2225

23-
# should get this from the environment...
24-
ACRN_BASE = "../"
26+
def copy_if_different(src, dst):
27+
# Copies 'src' as 'dst', but only if dst does not exist or if itx contents
28+
# differ from src.This avoids unnecessary # timestamp updates, which
29+
# trigger documentation rebuilds.
30+
if os.path.exists(dst) and filecmp.cmp(src, dst):
31+
return
32+
shutil.copyfile(src, dst)
2533

26-
def get_rst_files(dir):
34+
def get_files(all, dest, dir):
2735
matches = []
28-
for root, dirnames, filenames in os.walk('%s/%s' %(ACRN_BASE, dir)):
29-
for filename in fnmatch.filter(filenames, '*.rst'):
36+
for root, dirnames, filenames in os.walk('%s/%s' %(ZEPHYR_BASE, dir)):
37+
if ZEPHYR_BUILD:
38+
if os.path.normpath(root).startswith(os.path.normpath(ZEPHYR_BUILD)):
39+
# Build folder, skip it
40+
continue
41+
42+
for filename in fnmatch.filter(filenames, '*' if all else '*.rst'):
3043
matches.append(os.path.join(root, filename))
3144
for file in matches:
32-
frel = file.replace(ACRN_BASE,"").strip("/")
45+
frel = file.replace(ZEPHYR_BASE,"").strip("/")
3346
dir=os.path.dirname(frel)
34-
if not os.path.exists(os.path.join(ACRN_BASE, "doc", dir)):
35-
os.makedirs(os.path.join(ACRN_BASE, "doc", dir))
36-
37-
shutil.copyfile(file, os.path.join(ACRN_BASE, "doc", frel))
38-
39-
with open(file, encoding="utf-8") as f:
40-
content = f.readlines()
41-
content = [x.strip() for x in content]
42-
directives = "|".join(DIRECTIVES)
43-
pattern = re.compile("\s*\.\.\s+(%s)::\s+(.*)" %directives)
44-
for l in content:
45-
m = pattern.match(l)
46-
if m:
47-
inf = m.group(2)
48-
ind = os.path.dirname(inf)
49-
if not os.path.exists(os.path.join(ACRN_BASE, "doc", dir, ind)):
50-
os.makedirs(os.path.join(ACRN_BASE, "doc", dir, ind))
51-
52-
shutil.copyfile(os.path.join(ACRN_BASE, dir, inf),
53-
os.path.join(ACRN_BASE, "doc", dir, inf))
47+
if not os.path.exists(os.path.join(dest, dir)):
48+
os.makedirs(os.path.join(dest, dir))
49+
50+
copy_if_different(file, os.path.join(dest, frel))
51+
52+
# Inspect only .rst files for directives referencing other files
53+
# we'll need to copy (as configured in the DIRECTIVES variable)
54+
if not fnmatch.fnmatch(file, "*.rst"):
55+
continue
56+
57+
try:
58+
with open(file, encoding="utf-8") as f:
59+
content = f.readlines()
60+
61+
content = [x.strip() for x in content]
62+
directives = "|".join(DIRECTIVES)
63+
pattern = re.compile("\s*\.\.\s+(%s)::\s+(.*)" %directives)
64+
for l in content:
65+
m = pattern.match(l)
66+
if m:
67+
inf = m.group(2)
68+
ind = os.path.dirname(inf)
69+
if not os.path.exists(os.path.join(dest, dir, ind)):
70+
os.makedirs(os.path.join(dest, dir, ind))
71+
72+
src = os.path.join(ZEPHYR_BASE, dir, inf)
73+
dst = os.path.join(dest, dir, inf)
74+
try:
75+
copy_if_different(src, dst)
76+
77+
except FileNotFoundError:
78+
sys.stderr.write("File not found: %s\n reference by %s\n" % (inf, file))
79+
80+
except UnicodeDecodeError as e:
81+
sys.stderr.write(
82+
"Malformed {} in {}\n"
83+
" Context: {}\n"
84+
" Problematic data: {}\n"
85+
" Reason: {}\n".format(
86+
e.encoding, file,
87+
e.object[max(e.start - 40, 0):e.end + 40],
88+
e.object[e.start:e.end],
89+
e.reason))
5490

5591
f.close()
5692

5793
def main():
58-
for d in CONTENT_DIRS:
59-
get_rst_files(d)
94+
95+
parser = argparse.ArgumentParser(description='Recursively copy .rst files '
96+
'from the origin folder(s) to the '
97+
'destination folder, plus files referenced '
98+
'in those .rst files by a configurable '
99+
'list of directives: {}.'.format(DIRECTIVES))
100+
101+
parser.add_argument('-a', '--all', action='store_true', help='Copy all files '
102+
'(recursively) in the specified source folder(s).')
103+
parser.add_argument('dest', nargs=1)
104+
parser.add_argument('src', nargs='+')
105+
args = parser.parse_args()
106+
107+
dest = args.dest[0]
108+
109+
for d in args.src:
110+
get_files(args.all, dest, d)
60111

61112
if __name__ == "__main__":
62113
main()

tools/acrn-crashlog/README.rst

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,11 @@ telemetrics-client on the system:
7979
telemetrics daemon. The work flow of ``acrnprobe`` and
8080
telemetrics-client is shown in :numref:`crashlog-workflow`:
8181

82-
.. graphviz::
82+
.. graphviz:: images/crashlog-workflow.dot
8383
:name: crashlog-workflow
8484
:align: center
8585
:caption: acrnprobe and telemetrics-client workflow
8686

87-
digraph {
88-
bgcolor=transparent; rankdir=LR;
89-
node [shape="rectangle" style="filled" color="lightblue"]
90-
edge [fontsize="12" fontcolor="blue"]
91-
92-
"acrnprobe" -> "telemetrics-client" [label="crashlog\npath"]
93-
"telemetrics-client" -> "backend" [label="log\ncontent"]
94-
}
95-
9687

9788
Crashlog can be retrieved with ``telem_journal`` command:
9889

tools/acrn-crashlog/acrnprobe/conf.rst

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -97,29 +97,10 @@ D inherit from crash A, and crash C is the child of crash B.
9797
Build crash tree in configuration
9898
=================================
9999

100-
.. graphviz::
101-
102-
digraph {
103-
{
104-
node [shape=plaintext];
105-
"level 1" -> "level 2" -> "level 3";
106-
}
107-
108-
node [shape=box;style="rounded,filled";color=AntiqueWhite;];
109-
c1 [ label="crash A\nid 1\ncrash root" ];
110-
c2 [ label="crash B\nid 2" ];
111-
c3 [ label="crash C\nid 3\ncrash leaf" ];
112-
c4 [ label="crash D\nid 4\ncrash leaf" ];
113-
c5 [ label="crash E\nid 5\ncrash root\ncrash leaf" ];
114-
{ rank = same; "level 1"; c1; c5;}
115-
{ rank = same; "level 2"; c2; c4;}
116-
{ rank = same; "level 3"; c3;}
117-
118-
node [shape=box;color="transparent";];
119-
"None" -> {c1 c5} [ label="inherit 0" ];
120-
c1 -> {c2 c4} [ label="inherit 1" ];
121-
c2 -> c3 [ label="inherit 2" ];
122-
}
100+
.. graphviz:: images/crash-config.dot
101+
:name: crash-config
102+
:align: center
103+
:caption: Build crash tree in configuration
123104

124105
Match crash at runtime
125106
======================
@@ -136,33 +117,10 @@ If a crash A is triggered, then the candidates are crash A, B, C and D.
136117
The following diagram describes what ``acrnprobe`` will do if the matched
137118
result is crash D.
138119

139-
.. graphviz::
140-
141-
digraph {
142-
{
143-
node [shape=plaintext];
144-
"level 1" -> "level 2" -> "level 3";
145-
}
146-
147-
node [shape=box;style="rounded,filled";color=AntiqueWhite;];
148-
c1 [ label="crash A\nid 1\ncrash root" ];
149-
c2 [ label="crash B\nid 2" ];
150-
c3 [ label="crash C\nid 3\ncrash leaf" ];
151-
c4 [ label="crash D\nid 4\ncrash leaf" ];
152-
{ rank = same; "level 1"; c1;}
153-
{ rank = same; "level 2"; c2; c4;}
154-
{ rank = same; "level 3"; c3;}
155-
156-
node [shape=box;style="rounded,dashed";];
157-
exp1 [ label="crash B matches fail\nmatch for the next child\nof crash A"];
158-
exp2 [ label="crash D matches successfully\nreturn crash D"];
159-
160-
node [shape=box;style="invis";];
161-
"channel" -> c1 [ label="trigger" ]
162-
c1 -> {exp1 exp2}
163-
exp1 -> c2 -> c3 [ style=dashed dir=none]
164-
exp2 -> c4
165-
}
120+
.. graphviz:: images/crash-match.dot
121+
:name: crash-match
122+
:align: center
123+
:caption: Match crash at runtime
166124

167125
Sections
168126
********
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
digraph {
2+
{
3+
node [shape=plaintext];
4+
"level 1" -> "level 2" -> "level 3";
5+
}
6+
7+
node [shape=box;style="rounded,filled";color=AntiqueWhite;];
8+
c1 [ label="crash A\nid 1\ncrash root" ];
9+
c2 [ label="crash B\nid 2" ];
10+
c3 [ label="crash C\nid 3\ncrash leaf" ];
11+
c4 [ label="crash D\nid 4\ncrash leaf" ];
12+
c5 [ label="crash E\nid 5\ncrash root\ncrash leaf" ];
13+
{ rank = same; "level 1"; c1; c5;}
14+
{ rank = same; "level 2"; c2; c4;}
15+
{ rank = same; "level 3"; c3;}
16+
17+
node [shape=box;color="transparent";];
18+
"None" -> {c1 c5} [ label="inherit 0" ];
19+
c1 -> {c2 c4} [ label="inherit 1" ];
20+
c2 -> c3 [ label="inherit 2" ];
21+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
digraph {
2+
{
3+
node [shape=plaintext];
4+
"level 1" -> "level 2" -> "level 3";
5+
}
6+
7+
node [shape=box;style="rounded,filled";color=AntiqueWhite;];
8+
c1 [ label="crash A\nid 1\ncrash root" ];
9+
c2 [ label="crash B\nid 2" ];
10+
c3 [ label="crash C\nid 3\ncrash leaf" ];
11+
c4 [ label="crash D\nid 4\ncrash leaf" ];
12+
{ rank = same; "level 1"; c1;}
13+
{ rank = same; "level 2"; c2; c4;}
14+
{ rank = same; "level 3"; c3;}
15+
16+
node [shape=box;style="rounded,dashed";];
17+
exp1 [ label="crash B matches fail\nmatch for the next child\nof crash A"];
18+
exp2 [ label="crash D matches successfully\nreturn crash D"];
19+
20+
node [shape=box;style="invis";];
21+
"channel" -> c1 [ label="trigger" ]
22+
c1 -> {exp1 exp2}
23+
exp1 -> c2 -> c3 [ style=dashed dir=none]
24+
exp2 -> c4
25+
}
26+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
digraph {
2+
bgcolor=transparent; rankdir=LR;
3+
node [shape="rectangle" style="filled" color="lightblue"]
4+
edge [fontsize="12" fontcolor="blue"]
5+
6+
"acrnprobe" -> "telemetrics-client" [label="crashlog\npath"]
7+
"telemetrics-client" -> "backend" [label="log\ncontent"]
8+
}

tools/acrn-crashlog/usercrash/README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Description
77
***********
88

99
The ``usercrash`` tool gets the crash info for the crashing process in
10-
userpace. The collected information is saved as usercrash_xx under
10+
userspace. The collected information is saved as usercrash_xx under
1111
``/var/log/usercrashes/``.
1212

1313
Design

0 commit comments

Comments
 (0)