__init__.py 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. # Sphinx extension to integrate IDF build system information
  2. # into the Sphinx Build
  3. #
  4. # Runs early in the Sphinx process, runs CMake to generate the dummy IDF project
  5. # in this directory - including resolving paths, etc.
  6. #
  7. # Then emits the new 'idf-info' event which has information read from IDF
  8. # build system, that other extensions can use to generate relevant data.
  9. import json
  10. import os.path
  11. import shutil
  12. import subprocess
  13. import sys
  14. # this directory also contains the dummy IDF project
  15. project_path = os.path.abspath(os.path.dirname(__file__))
  16. # Targets which needs --preview to build
  17. PREVIEW_TARGETS = []
  18. def setup(app):
  19. # Setup some common paths
  20. try:
  21. build_dir = os.environ['BUILDDIR'] # TODO see if we can remove this
  22. except KeyError:
  23. build_dir = os.path.dirname(app.doctreedir.rstrip(os.sep))
  24. try:
  25. os.mkdir(build_dir)
  26. except OSError:
  27. pass
  28. try:
  29. os.mkdir(os.path.join(build_dir, 'inc'))
  30. except OSError:
  31. pass
  32. # Fill in a default IDF_PATH if it's missing (ie when Read The Docs is building the docs)
  33. try:
  34. idf_path = os.environ['IDF_PATH']
  35. except KeyError:
  36. idf_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
  37. app.add_config_value('docs_root', os.path.join(idf_path, 'docs'), 'env')
  38. app.add_config_value('idf_path', idf_path, 'env')
  39. app.add_config_value('build_dir', build_dir, 'env') # not actually an IDF thing
  40. app.add_event('idf-info')
  41. # we want this to run early in the docs build but unclear exactly when
  42. app.connect('config-inited', generate_idf_info)
  43. return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'}
  44. def generate_idf_info(app, config):
  45. print('Running CMake on dummy project to get build info...')
  46. build_dir = os.path.dirname(app.doctreedir.rstrip(os.sep))
  47. cmake_build_dir = os.path.join(build_dir, 'build_dummy_project')
  48. idf_py_path = os.path.join(app.config.idf_path, 'tools', 'idf.py')
  49. print('Running idf.py...')
  50. idf_py = [sys.executable,
  51. idf_py_path,
  52. '-B',
  53. cmake_build_dir,
  54. '-C',
  55. project_path,
  56. '-D',
  57. 'SDKCONFIG={}'.format(os.path.join(build_dir, 'dummy_project_sdkconfig'))
  58. ]
  59. # force a clean idf.py build w/ new sdkconfig each time
  60. # (not much slower than 'reconfigure', avoids any potential config & build versioning problems
  61. shutil.rmtree(cmake_build_dir, ignore_errors=True)
  62. print('Starting new dummy IDF project... ')
  63. if (app.config.idf_target in PREVIEW_TARGETS):
  64. subprocess.check_call(idf_py + ['--preview', 'set-target', app.config.idf_target])
  65. else:
  66. subprocess.check_call(idf_py + ['set-target', app.config.idf_target])
  67. print('Running CMake on dummy project...')
  68. subprocess.check_call(idf_py + ['reconfigure'])
  69. with open(os.path.join(cmake_build_dir, 'project_description.json')) as f:
  70. project_description = json.load(f)
  71. if project_description['target'] != app.config.idf_target:
  72. # this shouldn't really happen unless someone has been moving around directories inside _build, as
  73. # the cmake_build_dir path should be target-specific
  74. raise RuntimeError(('Error configuring the dummy IDF project for {}. ' +
  75. 'Target in project description is {}. ' +
  76. 'Is build directory contents corrupt?')
  77. .format(app.config.idf_target, project_description['target']))
  78. app.emit('idf-info', project_description)
  79. return []