scripts: move to buildtools
[dpdk.git] / doc / guides / conf.py
1 #   BSD LICENSE
2 #   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
3 #   All rights reserved.
4 #
5 #   Redistribution and use in source and binary forms, with or without
6 #   modification, are permitted provided that the following conditions
7 #   are met:
8 #
9 #   * Redistributions of source code must retain the above copyright
10 #   notice, this list of conditions and the following disclaimer.
11 #   * Redistributions in binary form must reproduce the above copyright
12 #   notice, this list of conditions and the following disclaimer in
13 #   the documentation and/or other materials provided with the
14 #   distribution.
15 #   * Neither the name of Intel Corporation nor the names of its
16 #   contributors may be used to endorse or promote products derived
17 #   from this software without specific prior written permission.
18 #
19 #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 #   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 #   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 #   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 #   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 #   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 from __future__ import print_function
32 import subprocess
33 from docutils import nodes
34 from distutils.version import LooseVersion
35 from sphinx import __version__ as sphinx_version
36 from sphinx.highlighting import PygmentsBridge
37 from pygments.formatters.latex import LatexFormatter
38 from os import listdir
39 from os.path import basename
40 from os.path import dirname
41 from os.path import join as path_join
42
43 try:
44     # Python 2.
45     import ConfigParser as configparser
46 except:
47     # Python 3.
48     import configparser
49
50
51 project = 'Data Plane Development Kit'
52
53 if LooseVersion(sphinx_version) >= LooseVersion('1.3.1'):
54     html_theme = "sphinx_rtd_theme"
55 html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
56 latex_logo = '../logo/DPDK_logo_horizontal_tag.png'
57 html_add_permalinks = ""
58 html_show_copyright = False
59 highlight_language = 'none'
60
61 version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion'])
62 version = version.decode('utf-8').rstrip()
63 release = version
64
65 master_doc = 'index'
66
67 # Figures, tables and code-blocks automatically numbered if they have caption
68 numfig = True
69
70 latex_documents = [
71     ('index',
72      'doc.tex',
73      '',
74      '',
75      'manual')
76 ]
77
78 # Latex directives to be included directly in the latex/pdf docs.
79 latex_preamble = r"""
80 \usepackage[utf8]{inputenc}
81 \usepackage[T1]{fontenc}
82 \usepackage{helvet}
83 \renewcommand{\familydefault}{\sfdefault}
84 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
85 """
86
87 # Configuration for the latex/pdf docs.
88 latex_elements = {
89     'papersize': 'a4paper',
90     'pointsize': '11pt',
91     # remove blank pages
92     'classoptions': ',openany,oneside',
93     'babel': '\\usepackage[english]{babel}',
94     # customize Latex formatting
95     'preamble': latex_preamble
96 }
97
98
99 # Override the default Latex formatter in order to modify the
100 # code/verbatim blocks.
101 class CustomLatexFormatter(LatexFormatter):
102     def __init__(self, **options):
103         super(CustomLatexFormatter, self).__init__(**options)
104         # Use the second smallest font size for code/verbatim blocks.
105         self.verboptions = r'formatcom=\footnotesize'
106
107 # Replace the default latex formatter.
108 PygmentsBridge.latex_formatter = CustomLatexFormatter
109
110 # Configuration for man pages
111 man_pages = [("testpmd_app_ug/run_app", "testpmd",
112               "tests for dpdk pmds", "", 1),
113              ("tools/pdump", "dpdk-pdump",
114               "enable packet capture on dpdk ports", "", 1),
115              ("tools/proc_info", "dpdk-procinfo",
116               "access dpdk port stats and memory info", "", 1),
117              ("tools/pmdinfo", "dpdk-pmdinfo",
118               "dump a PMDs hardware support info", "", 1),
119              ("tools/devbind", "dpdk-devbind",
120               "check device status and bind/unbind them from drivers", "", 8)]
121
122
123 # ####### :numref: fallback ########
124 # The following hook functions add some simple handling for the :numref:
125 # directive for Sphinx versions prior to 1.3.1. The functions replace the
126 # :numref: reference with a link to the target (for all Sphinx doc types).
127 # It doesn't try to label figures/tables.
128 def numref_role(reftype, rawtext, text, lineno, inliner):
129     """
130     Add a Sphinx role to handle numref references. Note, we can't convert
131     the link here because the doctree isn't build and the target information
132     isn't available.
133     """
134     # Add an identifier to distinguish numref from other references.
135     newnode = nodes.reference('',
136                               '',
137                               refuri='_local_numref_#%s' % text,
138                               internal=True)
139     return [newnode], []
140
141
142 def process_numref(app, doctree, from_docname):
143     """
144     Process the numref nodes once the doctree has been built and prior to
145     writing the files. The processing involves replacing the numref with a
146     link plus text to indicate if it is a Figure or Table link.
147     """
148
149     # Iterate over the reference nodes in the doctree.
150     for node in doctree.traverse(nodes.reference):
151         target = node.get('refuri', '')
152
153         # Look for numref nodes.
154         if target.startswith('_local_numref_#'):
155             target = target.replace('_local_numref_#', '')
156
157             # Get the target label and link information from the Sphinx env.
158             data = app.builder.env.domains['std'].data
159             docname, label, _ = data['labels'].get(target, ('', '', ''))
160             relative_url = app.builder.get_relative_uri(from_docname, docname)
161
162             # Add a text label to the link.
163             if target.startswith('figure'):
164                 caption = 'Figure'
165             elif target.startswith('table'):
166                 caption = 'Table'
167             else:
168                 caption = 'Link'
169
170             # New reference node with the updated link information.
171             newnode = nodes.reference('',
172                                       caption,
173                                       refuri='%s#%s' % (relative_url, label),
174                                       internal=True)
175             node.replace_self(newnode)
176
177
178 def generate_nic_overview_table(output_filename):
179     """
180     Function to generate the NIC Overview Table from the ini files that define
181     the features for each NIC.
182
183     The default features for the table and their order is defined by the
184     'default.ini' file.
185
186     """
187     # Default worning string.
188     warning = 'Warning generate_nic_overview_table()'
189
190     # Get the default features and order from the 'default.ini' file.
191     ini_path = path_join(dirname(output_filename), 'features')
192     config = configparser.ConfigParser()
193     config.optionxform = str
194     config.read(path_join(ini_path, 'default.ini'))
195     default_section = 'Features'
196     default_features = config.items(default_section)
197
198     # Create a dict of the valid features to validate the other ini files.
199     valid_features = {}
200     max_feature_length = 0
201     for feature in default_features:
202         key = feature[0]
203         valid_features[key] = ' '
204         max_feature_length = max(max_feature_length, len(key))
205
206     # Get a list of NIC ini files, excluding 'default.ini'.
207     ini_files = [basename(file) for file in listdir(ini_path)
208                  if file.endswith('.ini') and file != 'default.ini']
209     ini_files.sort()
210
211     # Build up a list of the table header names from the ini filenames.
212     header_names = []
213     for ini_filename in ini_files:
214         name = ini_filename[:-4]
215         name = name.replace('_vf', 'vf')
216
217         # Pad the table header names to match the existing format.
218         if '_vec' in name:
219             pmd, vec = name.split('_')
220             name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<')
221         else:
222             name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<')
223
224         header_names.append(name)
225
226     # Create a dict of the defined features for each NIC from the ini files.
227     ini_data = {}
228     for ini_filename in ini_files:
229         config = configparser.ConfigParser()
230         config.optionxform = str
231         config.read(path_join(ini_path, ini_filename))
232
233         # Initialize the dict with the default.ini value.
234         ini_data[ini_filename] = valid_features.copy()
235
236         # Check for a valid ini section.
237         if not config.has_section(default_section):
238             print("{}: File '{}' has no [{}] secton".format(warning,
239                                                             ini_filename,
240                                                             default_section))
241             continue
242
243         # Check for valid features names.
244         for name, value in config.items(default_section):
245             if name not in valid_features:
246                 print("{}: Unknown feature '{}' in '{}'".format(warning,
247                                                                 name,
248                                                                 ini_filename))
249                 continue
250
251             if value is not '':
252                 # Get the first letter only.
253                 ini_data[ini_filename][name] = value[0]
254
255     # Print out the RST NIC Overview table from the ini file data.
256     outfile = open(output_filename, 'w')
257     num_cols = len(header_names)
258
259     print('.. table:: Features availability in networking drivers\n',
260           file=outfile)
261
262     print_table_header(outfile, num_cols, header_names)
263     print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
264
265
266 def print_table_header(outfile, num_cols, header_names):
267     """ Print the RST table header. The header names are vertical. """
268     print_table_divider(outfile, num_cols)
269
270     line = ''
271     for name in header_names:
272         line += ' ' + name[0]
273
274     print_table_row(outfile, 'Feature', line)
275
276     for i in range(1, 10):
277         line = ''
278         for name in header_names:
279             line += ' ' + name[i]
280
281         print_table_row(outfile, '', line)
282
283     print_table_divider(outfile, num_cols)
284
285
286 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
287     """ Print out the body of the table. Each row is a NIC feature. """
288
289     for feature, _ in default_features:
290         line = ''
291
292         for ini_filename in ini_files:
293             line += ' ' + ini_data[ini_filename][feature]
294
295         print_table_row(outfile, feature, line)
296
297     print_table_divider(outfile, num_cols)
298
299
300 def print_table_row(outfile, feature, line):
301     """ Print a single row of the table with fixed formatting. """
302     line = line.rstrip()
303     print('   {:<20}{}'.format(feature, line), file=outfile)
304
305
306 def print_table_divider(outfile, num_cols):
307     """ Print the table divider line. """
308     line = ' '
309     column_dividers = ['='] * num_cols
310     line += ' '.join(column_dividers)
311
312     feature = '=' * 20
313
314     print_table_row(outfile, feature, line)
315
316
317 def setup(app):
318     table_file = dirname(__file__) + '/nics/overview_table.txt'
319     generate_nic_overview_table(table_file)
320
321     if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
322         print('Upgrade sphinx to version >= 1.3.1 for '
323               'improved Figure/Table number handling.')
324         # Add a role to handle :numref: references.
325         app.add_role('numref', numref_role)
326         # Process the numref references once the doctree has been created.
327         app.connect('doctree-resolved', process_numref)