bsp_buildings.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import os
  2. import shutil
  3. import re
  4. import multiprocessing
  5. import yaml
  6. def add_summary(text):
  7. """
  8. add summary to github action.
  9. """
  10. os.system(f'echo "{text}" >> $GITHUB_STEP_SUMMARY ;')
  11. def run_cmd(cmd, output_info=True):
  12. """
  13. run command and return output and result.
  14. """
  15. print('\033[1;32m' + cmd + '\033[0m')
  16. output_str_list = []
  17. res = 0
  18. if output_info:
  19. res = os.system(cmd + " > output.txt 2>&1")
  20. else:
  21. res = os.system(cmd + " > /dev/null 2>output.txt")
  22. with open("output.txt", "r") as file:
  23. output_str_list = file.readlines()
  24. for line in output_str_list:
  25. print(line, end='')
  26. os.remove("output.txt")
  27. return output_str_list, res
  28. def build_bsp(bsp, scons_args='',name='default'):
  29. """
  30. build bsp.
  31. cd {rtt_root}
  32. scons -C bsp/{bsp} --pyconfig-silent > /dev/null
  33. cd {rtt_root}/bsp/{bsp}
  34. pkgs --update > /dev/null
  35. pkgs --list
  36. cd {rtt_root}
  37. scons -C bsp/{bsp} -j{nproc} {scons_args}
  38. cd {rtt_root}/bsp/{bsp}
  39. scons -c > /dev/null
  40. rm -rf packages
  41. """
  42. success = True
  43. os.chdir(rtt_root)
  44. os.makedirs(f'{rtt_root}/output/bsp/{bsp}', exist_ok=True)
  45. if os.path.exists(f"{rtt_root}/bsp/{bsp}/Kconfig"):
  46. os.chdir(rtt_root)
  47. run_cmd(f'scons -C bsp/{bsp} --pyconfig-silent', output_info=False)
  48. os.chdir(f'{rtt_root}/bsp/{bsp}')
  49. run_cmd('pkgs --update-force', output_info=False)
  50. run_cmd('pkgs --list')
  51. nproc = multiprocessing.cpu_count()
  52. os.chdir(rtt_root)
  53. cmd = f'scons -C bsp/{bsp} -j{nproc} {scons_args}' # --debug=time for debug time
  54. __, res = run_cmd(cmd, output_info=True)
  55. if res != 0:
  56. success = False
  57. else:
  58. #拷贝当前的文件夹下面的所有以elf结尾的文件拷贝到rt-thread/output文件夹下
  59. import glob
  60. # 拷贝编译生成的文件到output目录,文件拓展为 elf,bin,hex
  61. for file_type in ['*.elf', '*.bin', '*.hex']:
  62. files = glob.glob(f'{rtt_root}/bsp/{bsp}/{file_type}')
  63. for file in files:
  64. shutil.copy(file, f'{rtt_root}/output/bsp/{bsp}/{name.replace("/", "_")}.{file_type[2:]}')
  65. os.chdir(f'{rtt_root}/bsp/{bsp}')
  66. run_cmd('scons -c', output_info=False)
  67. return success
  68. def append_file(source_file, destination_file):
  69. """
  70. append file to another file.
  71. """
  72. with open(source_file, 'r') as source:
  73. with open(destination_file, 'a') as destination:
  74. for line in source:
  75. destination.write(line)
  76. def check_scons_args(file_path):
  77. args = []
  78. with open(file_path, 'r') as file:
  79. for line in file:
  80. match = re.search(r'#\s*scons:\s*(.*)', line)
  81. if match:
  82. args.append(match.group(1).strip())
  83. return ' '.join(args)
  84. def get_details_and_dependencies(details, projects, seen=None):
  85. if seen is None:
  86. seen = set()
  87. detail_list = []
  88. if details is not None:
  89. for dep in details:
  90. if dep not in seen:
  91. dep_details=projects.get(dep)
  92. seen.add(dep)
  93. if dep_details is not None:
  94. if dep_details.get('depends') is not None:
  95. detail_temp=get_details_and_dependencies(dep_details.get('depends'), projects, seen)
  96. for line in detail_temp:
  97. detail_list.append(line)
  98. if dep_details.get('kconfig') is not None:
  99. for line in dep_details.get('kconfig'):
  100. detail_list.append(line)
  101. else:
  102. print(f"::error::There are some problems with attachconfig depend: {dep}");
  103. return detail_list
  104. def build_bsp_attachconfig(bsp, attach_file):
  105. """
  106. build bsp with attach config.
  107. cp bsp/{bsp}/.config bsp/{bsp}/.config.origin
  108. cat .ci/attachconfig/{attach_file} >> bsp/{bsp}/.config
  109. build_bsp()
  110. cp bsp/{bsp}/.config.origin bsp/{bsp}/.config
  111. rm bsp/{bsp}/.config.origin
  112. """
  113. config_file = os.path.join(rtt_root, 'bsp', bsp, '.config')
  114. config_bacakup = config_file+'.origin'
  115. shutil.copyfile(config_file, config_bacakup)
  116. attachconfig_dir = os.path.join(rtt_root, 'bsp', bsp, '.ci/attachconfig')
  117. attach_path = os.path.join(attachconfig_dir, attach_file)
  118. append_file(attach_path, config_file)
  119. scons_args = check_scons_args(attach_path)
  120. res = build_bsp(bsp, scons_args,name=attach_file)
  121. shutil.copyfile(config_bacakup, config_file)
  122. os.remove(config_bacakup)
  123. return res
  124. if __name__ == "__main__":
  125. """
  126. build all bsp and attach config.
  127. 1. build all bsp.
  128. 2. build all bsp with attach config.
  129. """
  130. failed = 0
  131. count = 0
  132. rtt_root = os.getcwd()
  133. srtt_bsp = os.getenv('SRTT_BSP').split(',')
  134. for bsp in srtt_bsp:
  135. count += 1
  136. print(f"::group::Compiling BSP: =={count}=== {bsp} ====")
  137. res = build_bsp(bsp)
  138. if not res:
  139. print(f"::error::build {bsp} failed")
  140. add_summary(f"- ❌ build {bsp} failed.")
  141. failed += 1
  142. else:
  143. add_summary(f'- ✅ build {bsp} success.')
  144. print("::endgroup::")
  145. yml_files_content = []
  146. directory = os.path.join(rtt_root, 'bsp', bsp, '.ci/attachconfig')
  147. if os.path.exists(directory):
  148. for root, dirs, files in os.walk(directory):
  149. for filename in files:
  150. if filename.endswith('attachconfig.yml'):
  151. file_path = os.path.join(root, filename)
  152. if os.path.exists(file_path):
  153. try:
  154. with open(file_path, 'r') as file:
  155. content = yaml.safe_load(file)
  156. if content is None:
  157. continue
  158. yml_files_content.append(content)
  159. except yaml.YAMLError as e:
  160. print(f"::error::Error parsing YAML file: {e}")
  161. continue
  162. except Exception as e:
  163. print(f"::error::Error reading file: {e}")
  164. continue
  165. config_file = os.path.join(rtt_root, 'bsp', bsp, '.config')
  166. for projects in yml_files_content:
  167. for name, details in projects.items():
  168. count += 1
  169. config_bacakup = config_file+'.origin'
  170. shutil.copyfile(config_file, config_bacakup)
  171. with open(config_file, 'a') as destination:
  172. if details.get("kconfig") is None:
  173. continue
  174. if(projects.get(name) is not None):
  175. detail_list=get_details_and_dependencies([name],projects)
  176. for line in detail_list:
  177. destination.write(line + '\n')
  178. scons_arg=[]
  179. if details.get('scons_arg') is not None:
  180. for line in details.get('scons_arg'):
  181. scons_arg.append(line)
  182. scons_arg_str=' '.join(scons_arg) if scons_arg else ' '
  183. print(f"::group::\tCompiling yml project: =={count}==={name}=scons_arg={scons_arg_str}==")
  184. res = build_bsp(bsp, scons_arg_str,name=name)
  185. if not res:
  186. print(f"::error::build {bsp} {name} failed.")
  187. add_summary(f'\t- ❌ build {bsp} {name} failed.')
  188. failed += 1
  189. else:
  190. add_summary(f'\t- ✅ build {bsp} {name} success.')
  191. print("::endgroup::")
  192. shutil.copyfile(config_bacakup, config_file)
  193. os.remove(config_bacakup)
  194. attach_dir = os.path.join(rtt_root, 'bsp', bsp, '.ci/attachconfig')
  195. attach_list = []
  196. for root, dirs, files in os.walk(attach_dir):
  197. for file in files:
  198. if file.endswith('attach'):
  199. file_path = os.path.join(root, file)
  200. relative_path = os.path.relpath(file_path, attach_dir)
  201. attach_list.append(relative_path)
  202. for attach_file in attach_list:
  203. count += 1
  204. print(f"::group::\tCompiling BSP: =={count}=== {bsp} {attach_file}===")
  205. res = build_bsp_attachconfig(bsp, attach_file)
  206. if not res:
  207. print(f"::error::build {bsp} {attach_file} failed.")
  208. add_summary(f'\t- ❌ build {attach_file} failed.')
  209. failed += 1
  210. else:
  211. add_summary(f'\t- ✅ build {attach_file} success.')
  212. print("::endgroup::")
  213. exit(failed)