cmake.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import logging
  2. import os
  3. import shutil
  4. import subprocess
  5. import sys
  6. from .common import BuildError, BuildItem, BuildSystem
  7. try:
  8. from typing import Any, Optional
  9. except ImportError:
  10. pass
  11. BUILD_SYSTEM_CMAKE = 'cmake'
  12. IDF_PY = os.path.join(os.environ['IDF_PATH'], 'tools', 'idf.py')
  13. # While ESP-IDF component CMakeLists files can be identified by the presence of 'idf_component_register' string,
  14. # there is no equivalent for the project CMakeLists files. This seems to be the best option...
  15. CMAKE_PROJECT_LINE = r'include($ENV{IDF_PATH}/tools/cmake/project.cmake)'
  16. class CMakeBuildSystem(BuildSystem):
  17. NAME = BUILD_SYSTEM_CMAKE
  18. @classmethod
  19. def build(cls, build_item): # type: (BuildItem) -> None
  20. build_path, work_path, extra_cmakecache_items = cls.build_prepare(build_item)
  21. # Prepare the build arguments
  22. args = [
  23. sys.executable,
  24. IDF_PY,
  25. '-B',
  26. build_path,
  27. '-C',
  28. work_path,
  29. '-DIDF_TARGET=' + build_item.target,
  30. ]
  31. if extra_cmakecache_items:
  32. for key, val in extra_cmakecache_items.items():
  33. args.append('-D{}={}'.format(key, val))
  34. if 'TEST_EXCLUDE_COMPONENTS' in extra_cmakecache_items \
  35. and 'TEST_COMPONENTS' not in extra_cmakecache_items:
  36. args.append('-DTESTS_ALL=1')
  37. if build_item.verbose:
  38. args.append('-v')
  39. if 'CONFIG_APP_BUILD_BOOTLOADER' in extra_cmakecache_items:
  40. # In case if secure_boot is enabled then for bootloader build need to add `bootloader` cmd
  41. args.append('bootloader')
  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. build_item.size_json_fp = build_item.get_size_json_fp()
  66. finally:
  67. if log_file:
  68. log_file.close()
  69. @staticmethod
  70. def _read_cmakelists(app_path): # type: (str) -> Optional[str]
  71. cmakelists_path = os.path.join(app_path, 'CMakeLists.txt')
  72. if not os.path.exists(cmakelists_path):
  73. return None
  74. with open(cmakelists_path, 'r') as cmakelists_file:
  75. return cmakelists_file.read()
  76. @staticmethod
  77. def is_app(path): # type: (str) -> bool
  78. cmakelists_file_content = CMakeBuildSystem._read_cmakelists(path)
  79. if not cmakelists_file_content:
  80. return False
  81. if CMAKE_PROJECT_LINE not in cmakelists_file_content:
  82. return False
  83. return True
  84. @classmethod
  85. def supported_targets(cls, app_path): # type: (str) -> Any
  86. return cls._supported_targets(app_path)