cmake.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import os
  2. import sys
  3. import subprocess
  4. import logging
  5. import shutil
  6. import re
  7. from .common import BuildSystem, BuildItem, BuildError
  8. BUILD_SYSTEM_CMAKE = "cmake"
  9. IDF_PY = "idf.py"
  10. # While ESP-IDF component CMakeLists files can be identified by the presence of 'idf_component_register' string,
  11. # there is no equivalent for the project CMakeLists files. This seems to be the best option...
  12. CMAKE_PROJECT_LINE = r"include($ENV{IDF_PATH}/tools/cmake/project.cmake)"
  13. SUPPORTED_TARGETS_REGEX = re.compile(r'Supported [Tt]argets((?:[\s|]+(?:ESP[0-9A-Z\-]+))+)')
  14. FORMAL_TO_USUAL = {
  15. 'ESP32': 'esp32',
  16. 'ESP32-S2': 'esp32s2',
  17. }
  18. class CMakeBuildSystem(BuildSystem):
  19. NAME = BUILD_SYSTEM_CMAKE
  20. @classmethod
  21. def build(cls, build_item): # type: (BuildItem) -> None
  22. build_path, work_path, extra_cmakecache_items = cls.build_prepare(build_item)
  23. # Prepare the build arguments
  24. args = [
  25. # Assume it is the responsibility of the caller to
  26. # set up the environment (run . ./export.sh)
  27. IDF_PY,
  28. "-B",
  29. build_path,
  30. "-C",
  31. work_path,
  32. "-DIDF_TARGET=" + build_item.target,
  33. ]
  34. if extra_cmakecache_items:
  35. for key, val in extra_cmakecache_items.items():
  36. args.append("-D{}={}".format(key, val))
  37. if "TEST_EXCLUDE_COMPONENTS" in extra_cmakecache_items \
  38. and "TEST_COMPONENTS" not in extra_cmakecache_items:
  39. args.append("-DTESTS_ALL=1")
  40. if build_item.verbose:
  41. args.append("-v")
  42. args.append("build")
  43. cmdline = format(" ".join(args))
  44. logging.info("Running {}".format(cmdline))
  45. if build_item.dry_run:
  46. return
  47. log_file = None
  48. build_stdout = sys.stdout
  49. build_stderr = sys.stderr
  50. if build_item.build_log_path:
  51. logging.info("Writing build log to {}".format(build_item.build_log_path))
  52. log_file = open(build_item.build_log_path, "w")
  53. build_stdout = log_file
  54. build_stderr = log_file
  55. try:
  56. subprocess.check_call(args, stdout=build_stdout, stderr=build_stderr)
  57. except subprocess.CalledProcessError as e:
  58. raise BuildError("Build failed with exit code {}".format(e.returncode))
  59. else:
  60. # Also save the sdkconfig file in the build directory
  61. shutil.copyfile(
  62. os.path.join(work_path, "sdkconfig"),
  63. os.path.join(build_path, "sdkconfig"),
  64. )
  65. finally:
  66. if log_file:
  67. log_file.close()
  68. @staticmethod
  69. def _read_cmakelists(app_path):
  70. cmakelists_path = os.path.join(app_path, "CMakeLists.txt")
  71. if not os.path.exists(cmakelists_path):
  72. return None
  73. with open(cmakelists_path, "r") as cmakelists_file:
  74. return cmakelists_file.read()
  75. @staticmethod
  76. def is_app(path):
  77. cmakelists_file_content = CMakeBuildSystem._read_cmakelists(path)
  78. if not cmakelists_file_content:
  79. return False
  80. if CMAKE_PROJECT_LINE not in cmakelists_file_content:
  81. return False
  82. return True