1import logging 2import os 3import shutil 4import subprocess 5import sys 6 7from .common import BuildError, BuildItem, BuildSystem 8 9BUILD_SYSTEM_CMAKE = 'cmake' 10IDF_PY = os.path.join(os.environ['IDF_PATH'], 'tools', 'idf.py') 11 12# While ESP-IDF component CMakeLists files can be identified by the presence of 'idf_component_register' string, 13# there is no equivalent for the project CMakeLists files. This seems to be the best option... 14CMAKE_PROJECT_LINE = r'include($ENV{IDF_PATH}/tools/cmake/project.cmake)' 15 16 17class CMakeBuildSystem(BuildSystem): 18 NAME = BUILD_SYSTEM_CMAKE 19 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 sys.executable, 26 IDF_PY, 27 '-B', 28 build_path, 29 '-C', 30 work_path, 31 '-DIDF_TARGET=' + build_item.target, 32 ] 33 if extra_cmakecache_items: 34 for key, val in extra_cmakecache_items.items(): 35 args.append('-D{}={}'.format(key, val)) 36 if 'TEST_EXCLUDE_COMPONENTS' in extra_cmakecache_items \ 37 and 'TEST_COMPONENTS' not in extra_cmakecache_items: 38 args.append('-DTESTS_ALL=1') 39 if build_item.verbose: 40 args.append('-v') 41 args.append('build') 42 cmdline = format(' '.join(args)) 43 logging.info('Running {}'.format(cmdline)) 44 45 if build_item.dry_run: 46 return 47 48 log_file = None 49 build_stdout = sys.stdout 50 build_stderr = sys.stderr 51 if build_item.build_log_path: 52 logging.info('Writing build log to {}'.format(build_item.build_log_path)) 53 log_file = open(build_item.build_log_path, 'w') 54 build_stdout = log_file 55 build_stderr = log_file 56 57 try: 58 subprocess.check_call(args, stdout=build_stdout, stderr=build_stderr) 59 except subprocess.CalledProcessError as e: 60 raise BuildError('Build failed with exit code {}'.format(e.returncode)) 61 else: 62 # Also save the sdkconfig file in the build directory 63 shutil.copyfile( 64 os.path.join(work_path, 'sdkconfig'), 65 os.path.join(build_path, 'sdkconfig'), 66 ) 67 build_item.size_json_fp = build_item.get_size_json_fp() 68 finally: 69 if log_file: 70 log_file.close() 71 72 @staticmethod 73 def _read_cmakelists(app_path): 74 cmakelists_path = os.path.join(app_path, 'CMakeLists.txt') 75 if not os.path.exists(cmakelists_path): 76 return None 77 with open(cmakelists_path, 'r') as cmakelists_file: 78 return cmakelists_file.read() 79 80 @staticmethod 81 def is_app(path): 82 cmakelists_file_content = CMakeBuildSystem._read_cmakelists(path) 83 if not cmakelists_file_content: 84 return False 85 if CMAKE_PROJECT_LINE not in cmakelists_file_content: 86 return False 87 return True 88 89 @classmethod 90 def supported_targets(cls, app_path): 91 return cls._supported_targets(app_path) 92