__init__.py 3.3 KB

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