| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- # Sphinx extension to integrate defines into the Sphinx Build
- #
- # Runs after the IDF dummy project has been built
- #
- # Then emits the new 'idf-defines-generated' event which has a dictionary of raw text define values
- # that other extensions can use to generate relevant data.
- import glob
- import os
- import pprint
- import re
- import subprocess
- def generate_defines(app, project_description):
- sdk_config_path = os.path.join(project_description['build_dir'], 'config')
- # Parse kconfig macros to pass into doxygen
- #
- # TODO: this should use the set of "config which can't be changed" eventually,
- # not the header
- defines = get_defines(os.path.join(project_description['build_dir'],
- 'config', 'sdkconfig.h'), sdk_config_path)
- # Add all SOC _caps.h headers and kconfig macros to the defines
- #
- # kind of a hack, be nicer to add a component info dict in project_description.json
- soc_path = [p for p in project_description['build_component_paths'] if p.endswith('/soc')][0]
- soc_headers = glob.glob(os.path.join(soc_path, project_description['target'],
- 'include', 'soc', '*_caps.h'))
- assert len(soc_headers) > 0
- for soc_header in soc_headers:
- defines.update(get_defines(soc_header, sdk_config_path))
- # write a list of definitions to make debugging easier
- with open(os.path.join(app.config.build_dir, 'macro-definitions.txt'), 'w') as f:
- pprint.pprint(defines, f)
- print('Saved macro list to %s' % f.name)
- add_tags(app, defines)
- app.emit('idf-defines-generated', defines)
- def get_defines(header_path, sdk_config_path):
- defines = {}
- # Note: we run C preprocessor here without any -I arguments (except "sdkconfig.h"), so assumption is
- # that these headers are all self-contained and don't include any other headers
- # not in the same directory
- print('Reading macros from %s...' % (header_path))
- processed_output = subprocess.check_output(['xtensa-esp32-elf-gcc', '-I', sdk_config_path,
- '-dM', '-E', header_path]).decode()
- for line in processed_output.split('\n'):
- line = line.strip()
- m = re.search('#define ([^ ]+) ?(.*)', line)
- if m:
- name = m.group(1)
- value = m.group(2)
- if name.startswith('_'):
- continue # toolchain macro
- if (' ' in value) or ('=' in value):
- value = '' # macros that expand to multiple tokens (ie function macros) cause doxygen errors, so just mark as 'defined'
- defines[name] = value
- return defines
- def add_tags(app, defines):
- # try to parse define values as ints and add to tags
- for name, value in defines.items():
- try:
- define_value = int(value.strip('()'))
- if define_value > 0:
- app.tags.add(name)
- except ValueError:
- continue
- def setup(app):
- app.connect('idf-info', generate_defines)
- app.add_event('idf-defines-generated')
- return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.2'}
|