Skip to content

Commit a2f4f29

Browse files
committed
docs: generate documentation for Kconfig options
This adds a simple script which parses Kconfig files using Kconfiglib and emits ReST document with the list of all options. For each option a link target is generated, to make it possible to link to any Kconfig option from the rest of the documentation. Since Kconfiglib is not on PyPI, the latest version (45f87b9d) is bundled into the docs directory.
1 parent fb43948 commit a2f4f29

File tree

6 files changed

+3613
-0
lines changed

6 files changed

+3613
-0
lines changed

docs/api-guides/build-system.rst

+2
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@ is overridden then the component can instruct the linker to link other binaries
568568
.. _GNU Make Manual: https://www.gnu.org/software/make/manual/make.html
569569

570570

571+
.. _custom-sdkconfig-defaults:
572+
571573
Custom sdkconfig defaults
572574
-------------------------
573575

docs/api-reference/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ API Reference
1212
Protocols <protocols/index>
1313
Storage <storage/index>
1414
System <system/index>
15+
Configuration Options <kconfig>
1516

docs/api-reference/kconfig.rst

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Configuration Options
2+
*********************
3+
4+
Introduction
5+
============
6+
7+
ESP-IDF uses Kconfig_ system to provide a compile-time configuration mechanism. Kconfig is based around options of several types: integer, string, boolean. Kconfig files specify dependencies between options, default values of the options, the way the options are grouped together, etc.
8+
9+
Applications developers can use ``make menuconfig`` build target to edit components' configuration. This configuration is saved inside ``sdkconfig`` file in the project root directory. Based on ``sdkconfig``, application build targets will generate ``sdkconfig.h`` file in the build directory, and will make sdkconfig options available to component makefiles.
10+
11+
Using sdkconfig.defaults
12+
========================
13+
14+
When updating ESP-IDF version, it is not uncommon to find that new Kconfig options are introduced. When this happens, application build targets will offer an interactive prompt to select values for the new options. New values are then written into ``sdkconfig`` file. To supress interactive prompts, applications can either define ``BATCH_BUILD`` environment variable, which will cause all prompts to be suppressed. This is the same effect as that of ``V`` or ``VERBOSE`` variables. Alternatively, ``defconfig`` build target can be used to update configuration for all new variables to the default values.
15+
16+
In some cases, such as when ``sdkconfig`` file is under revision control, the fact that ``sdkconfig`` file gets changed by the build system may be inconvenient. The build system offers a way to avoid this, in the form of ``sdkconfig.defaults`` file. This file is never touched by the build system, and must be created manually. It can contain all the options which matter for the given application. The format is the same as that of the ``sdkconfig`` file. Once ``sdkconfig.defaults`` is created, ``sdkconfig`` can be deleted and added to the ignore list of the revision control system (e.g. ``.gitignore`` file for git). Project build targets will automatically create ``sdkconfig`` file, populated with the settings from ``sdkconfig.defaults`` file, and the rest of the settings will be set to their default values. Note that when ``make defconfig`` is used, settings in sdkconfig will be overriden by the ones in ``sdkconfig.defaults``. For more information, see :ref:`custom-sdkconfig-defaults`.
17+
18+
Configuration Options Reference
19+
===============================
20+
21+
Subsequent sections contain the list of available ESP-IDF options, automatically generated from Kconfig files. Note that depending on the options selected, some options listed here may not be visible by default in the interface of menuconfig.
22+
23+
By convention, all option names are upper case with underscores. When Kconfig generates sdkconfig and sdkconfig.h files, option names are prefixed with ``CONFIG_``. So if an option ``ENABLE_FOO`` is defined in a Kconfig file and selected in menuconfig, then sdkconfig and sdkconfig.h files will have ``CONFIG_ENABLE_FOO`` defined. In this reference, option names are also prefixed with ``CONFIG_``, same as in the source code.
24+
25+
26+
.. include:: /_build/inc/kconfig.inc
27+
28+
.. _Kconfig: https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt

docs/conf.py

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
call('doxygen')
3030
# Generate 'api_name.inc' files using the XML files by Doxygen
3131
os.system("python gen-dxd.py")
32+
# Generate 'kconfig.inc' file from components' Kconfig files
33+
os.system("python gen-kconfig-doc.py > _build/inc/kconfig.inc")
3234

3335
# http://stackoverflow.com/questions/12772927/specifying-an-online-image-in-sphinx-restructuredtext-format
3436
#

docs/gen-kconfig-doc.py

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# gen-kconfig-doc.py — generate Sphinx .rst file from Kconfig files
5+
#
6+
# This script iterates over Kconfig and Kconfig.projbuild files in
7+
# ESP-IDF component directories, and outputs documentation for these options
8+
# as ReST markup.
9+
# For each option in Kconfig file (e.g. 'FOO'), CONFIG_FOO link target is
10+
# generated, allowing options to be referenced in other documents
11+
# (using :ref:`CONFIG_FOO`)
12+
#
13+
# This script uses kconfiglib library to do all the work of parsing Kconfig
14+
# files: https://github.com/ulfalizer/Kconfiglib
15+
#
16+
# Copyright 2017 Espressif Systems (Shanghai) PTE LTD
17+
#
18+
# Licensed under the Apache License, Version 2.0 (the "License");
19+
# you may not use this file except in compliance with the License.
20+
# You may obtain a copy of the License at
21+
#
22+
# http:#www.apache.org/licenses/LICENSE-2.0
23+
#
24+
# Unless required by applicable law or agreed to in writing, software
25+
# distributed under the License is distributed on an "AS IS" BASIS,
26+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27+
# See the License for the specific language governing permissions and
28+
# limitations under the License.
29+
30+
31+
import os
32+
import kconfiglib
33+
34+
# Indentation to be used in the generated file
35+
INDENT = ' '
36+
37+
# Characters used when underlining section heading
38+
HEADING_SYMBOLS = '#*=-^"+'
39+
40+
# Keep the heading level in sync with api-reference/kconfig.rst
41+
INITIAL_HEADING_LEVEL = 2
42+
MAX_HEADING_LEVEL = 5
43+
OPTION_HEADING_LEVEL = 6
44+
45+
46+
def print_menu_contents(title, items, heading_level, breadcrumbs):
47+
if title:
48+
print_section_heading(title, heading_level)
49+
for entry in items:
50+
if entry.is_menu():
51+
if len(breadcrumbs) > 0:
52+
new_breadcrumbs = breadcrumbs + ' > ' + entry.get_title()
53+
else:
54+
new_breadcrumbs = entry.get_title()
55+
56+
print_menu_contents(entry.get_title(), entry.get_items(),
57+
min(heading_level + 1, MAX_HEADING_LEVEL),
58+
new_breadcrumbs)
59+
elif entry.is_choice():
60+
print_choice(entry, breadcrumbs)
61+
else:
62+
if len(entry.get_prompts()) == 0:
63+
# Skip entries which can never be visible
64+
continue
65+
# Currently this does not handle 'menuconfig' entires in any special way,
66+
# as Kconfglib offers no way of recognizing them automatically.
67+
print_option(entry, breadcrumbs)
68+
# Trailing newline after every option
69+
print
70+
71+
def print_choice(choice, breadcrumbs):
72+
print_option(choice, breadcrumbs)
73+
print
74+
print '%sAvailable options:' % INDENT
75+
for opt in choice.get_symbols():
76+
# Format available options as a list
77+
print '%s- %s' % (INDENT * 2, opt.name)
78+
79+
def print_section_heading(title, heading_level):
80+
print title
81+
print HEADING_SYMBOLS[heading_level] * len(title)
82+
print
83+
84+
def print_option(opt, breadcrumbs):
85+
# add link target so we can use :ref:`CONFIG_FOO`
86+
print '.. _CONFIG_%s:' % opt.name
87+
print
88+
print_section_heading(opt.name, OPTION_HEADING_LEVEL)
89+
if len(opt.prompts) > 0:
90+
print '%s%s' % (INDENT, opt.prompts[0][0])
91+
print
92+
print '%s:emphasis:`Found in: %s`' % (INDENT, breadcrumbs)
93+
print
94+
if opt.get_help() is not None:
95+
# Help text normally contains newlines, but spaces at the beginning of
96+
# each line are stripped by kconfiglib. We need to re-indent the text
97+
# to produce valid ReST.
98+
print '%s%s' % (INDENT, opt.get_help().replace('\n', '\n%s' % INDENT))
99+
100+
def process_kconfig_file(kconfig_file, heading_level, breadcrumbs):
101+
if os.path.exists(kconfig_file):
102+
cfg = kconfiglib.Config(kconfig_file, print_warnings=True)
103+
print_menu_contents(None, cfg.get_top_level_items(), heading_level, breadcrumbs)
104+
105+
def print_all_components():
106+
heading_level = INITIAL_HEADING_LEVEL
107+
# Currently this works only for IDF components.
108+
# TODO: figure out if this can be re-used for documenting applications?
109+
components_path = os.path.join(os.path.curdir, '..', 'components')
110+
for component_name in os.listdir(components_path):
111+
if component_name.startswith('.'):
112+
continue # skip system thumbnail folders
113+
114+
kconfig_file_path = os.path.join(components_path, component_name, 'Kconfig')
115+
116+
process_kconfig_file(kconfig_file_path, heading_level, 'Component config')
117+
process_kconfig_file(kconfig_file_path + '.projbuild', heading_level, '')
118+
119+
if __name__ == '__main__':
120+
print_all_components()

0 commit comments

Comments
 (0)