1+ #
2+ # Copyright (c) 2025, RT-Thread Development Team
3+ #
4+ # SPDX-License-Identifier: Apache-2.0
5+ #
6+ # Change Logs:
7+ # Date Author Notes
8+ # 2025-04-21 supperthomas add the smart yml support and add env
9+ #
10+ import subprocess
11+ import threading
12+ import time
13+ import logging
14+ import sys
115import os
216import shutil
317import re
@@ -36,7 +50,7 @@ def run_cmd(cmd, output_info=True):
3650 return output_str_list , res
3751
3852
39- def build_bsp (bsp , scons_args = '' ,name = 'default' ):
53+ def build_bsp (bsp , scons_args = '' ,name = 'default' , pre_build_commands = None , post_build_command = None , build_check_result = None , bsp_build_env = None ):
4054 """
4155 build bsp.
4256
@@ -56,21 +70,41 @@ def build_bsp(bsp, scons_args='',name='default'):
5670
5771 """
5872 success = True
73+ # 设置环境变量
74+ if bsp_build_env is not None :
75+ print ("Setting environment variables:" )
76+ for key , value in bsp_build_env .items ():
77+ print (f"{ key } ={ value } " )
78+ os .environ [key ] = value # 设置环境变量
5979 os .chdir (rtt_root )
6080 os .makedirs (f'{ rtt_root } /output/bsp/{ bsp } ' , exist_ok = True )
6181 if os .path .exists (f"{ rtt_root } /bsp/{ bsp } /Kconfig" ):
6282 os .chdir (rtt_root )
63- run_cmd (f'scons -C bsp/{ bsp } --pyconfig-silent' , output_info = False )
83+ run_cmd (f'scons -C bsp/{ bsp } --pyconfig-silent' , output_info = True )
6484
6585 os .chdir (f'{ rtt_root } /bsp/{ bsp } ' )
66- run_cmd ('pkgs --update-force' , output_info = False )
86+ run_cmd ('pkgs --update-force' , output_info = True )
6787 run_cmd ('pkgs --list' )
6888
6989 nproc = multiprocessing .cpu_count ()
90+ if pre_build_commands is not None :
91+ print ("Pre-build commands:" )
92+ print (pre_build_commands )
93+ for command in pre_build_commands :
94+ print (command )
95+ output , returncode = run_cmd (command , output_info = True )
96+ print (output )
97+ if returncode != 0 :
98+ print (f"Pre-build command failed: { command } " )
99+ print (output )
70100 os .chdir (rtt_root )
101+ # scons 编译命令
71102 cmd = f'scons -C bsp/{ bsp } -j{ nproc } { scons_args } ' # --debug=time for debug time
72- __ , res = run_cmd (cmd , output_info = True )
73-
103+ output , res = run_cmd (cmd , output_info = True )
104+ if build_check_result is not None :
105+ if res != 0 or not check_output (output , build_check_result ):
106+ print ("Build failed or build check result not found" )
107+ print (output )
74108 if res != 0 :
75109 success = False
76110 else :
@@ -83,6 +117,13 @@ def build_bsp(bsp, scons_args='',name='default'):
83117 shutil .copy (file , f'{ rtt_root } /output/bsp/{ bsp } /{ name .replace ("/" , "_" )} .{ file_type [2 :]} ' )
84118
85119 os .chdir (f'{ rtt_root } /bsp/{ bsp } ' )
120+ if post_build_command is not None :
121+ for command in post_build_command :
122+ output , returncode = run_cmd (command , output_info = True )
123+ print (output )
124+ if returncode != 0 :
125+ print (f"Post-build command failed: { command } " )
126+ print (output )
86127 run_cmd ('scons -c' , output_info = False )
87128
88129 return success
@@ -158,7 +199,17 @@ def build_bsp_attachconfig(bsp, attach_file):
158199
159200 return res
160201
202+ def check_output (output , check_string ):
203+ """检查输出中是否包含指定字符串"""
204+ output_str = '' .join (output ) if isinstance (output , list ) else str (output )
205+ flag = check_string in output_str
206+ if flag == True :
207+ print ('Success: find string ' + check_string )
208+ else :
209+ print (output )
210+ print (f"::error:: can not find string { check_string } output: { output_str } " )
161211
212+ return flag
162213if __name__ == "__main__" :
163214 """
164215 build all bsp and attach config.
@@ -169,10 +220,12 @@ def build_bsp_attachconfig(bsp, attach_file):
169220 """
170221 failed = 0
171222 count = 0
223+ ci_build_run_flag = False
224+ qemu_timeout_second = 50
172225
173226 rtt_root = os .getcwd ()
174227 srtt_bsp = os .getenv ('SRTT_BSP' ).split (',' )
175-
228+ print ( srtt_bsp )
176229 for bsp in srtt_bsp :
177230 count += 1
178231 print (f"::group::Compiling BSP: =={ count } === { bsp } ====" )
@@ -207,26 +260,80 @@ def build_bsp_attachconfig(bsp, attach_file):
207260 continue
208261
209262 config_file = os .path .join (rtt_root , 'bsp' , bsp , '.config' )
210-
263+ # 在使用 pre_build_commands 之前,确保它被定义
264+ pre_build_commands = None
265+ build_command = None
266+ post_build_command = None
267+ qemu_command = None
268+ build_check_result = None
269+ commands = None
270+ check_result = None
271+ bsp_build_env = None
211272 for projects in yml_files_content :
212273 for name , details in projects .items ():
274+ # 如果是bsp_board_info,读取基本的信息
275+ if (name == 'bsp_board_info' ):
276+ print (details )
277+ pre_build_commands = details .get ("pre_build" ).splitlines ()
278+ build_command = details .get ("build_cmd" ).splitlines ()
279+ post_build_command = details .get ("post_build" ).splitlines ()
280+ qemu_command = details .get ("run_cmd" )
281+
282+ if details .get ("kconfig" ) is not None :
283+ if details .get ("buildcheckresult" ) is not None :
284+ build_check_result = details .get ("buildcheckresult" )
285+ else :
286+ build_check_result = None
287+ if details .get ("msh_cmd" ) is not None :
288+ commands = details .get ("msh_cmd" ).splitlines ()
289+ else :
290+ msh_cmd = None
291+ if details .get ("checkresult" ) is not None :
292+ check_result = details .get ("checkresult" )
293+ else :
294+ check_result = None
295+ if details .get ("ci_build_run_flag" ) is not None :
296+ ci_build_run_flag = details .get ("ci_build_run_flag" )
297+ else :
298+ ci_build_run_flag = None
299+ if details .get ("pre_build" ) is not None :
300+ pre_build_commands = details .get ("pre_build" ).splitlines ()
301+ if details .get ("env" ) is not None :
302+ bsp_build_env = details .get ("env" )
303+ else :
304+ bsp_build_env = None
305+ if details .get ("build_cmd" ) is not None :
306+ build_command = details .get ("build_cmd" ).splitlines ()
307+ else :
308+ build_command = None
309+ if details .get ("post_build" ) is not None :
310+ post_build_command = details .get ("post_build" ).splitlines ()
311+ if details .get ("run_cmd" ) is not None :
312+ qemu_command = details .get ("run_cmd" )
313+ else :
314+ qemu_command = None
213315 count += 1
214316 config_bacakup = config_file + '.origin'
215317 shutil .copyfile (config_file , config_bacakup )
318+ #加载yml中的配置放到.config文件
216319 with open (config_file , 'a' ) as destination :
217320 if details .get ("kconfig" ) is None :
321+ #如果没有Kconfig,读取下一个配置
218322 continue
219323 if (projects .get (name ) is not None ):
324+ # 获取Kconfig中所有的信息
220325 detail_list = get_details_and_dependencies ([name ],projects )
221326 for line in detail_list :
222327 destination .write (line + '\n ' )
223328 scons_arg = []
329+ #如果配置中有scons_arg
224330 if details .get ('scons_arg' ) is not None :
225331 for line in details .get ('scons_arg' ):
226332 scons_arg .append (line )
227333 scons_arg_str = ' ' .join (scons_arg ) if scons_arg else ' '
228334 print (f"::group::\t Compiling yml project: =={ count } ==={ name } =scons_arg={ scons_arg_str } ==" )
229- res = build_bsp (bsp , scons_arg_str ,name = name )
335+ # #开始编译bsp
336+ res = build_bsp (bsp , scons_arg_str ,name = name ,pre_build_commands = pre_build_commands ,post_build_command = post_build_command ,build_check_result = build_check_result ,bsp_build_env = bsp_build_env )
230337 if not res :
231338 print (f"::error::build { bsp } { name } failed." )
232339 add_summary (f'\t - ❌ build { bsp } { name } failed.' )
@@ -235,11 +342,15 @@ def build_bsp_attachconfig(bsp, attach_file):
235342 add_summary (f'\t - ✅ build { bsp } { name } success.' )
236343 print ("::endgroup::" )
237344
345+
238346 shutil .copyfile (config_bacakup , config_file )
239347 os .remove (config_bacakup )
240348
349+
350+
241351 attach_dir = os .path .join (rtt_root , 'bsp' , bsp , '.ci/attachconfig' )
242352 attach_list = []
353+ #这里是旧的文件方式
243354 for root , dirs , files in os .walk (attach_dir ):
244355 for file in files :
245356 if file .endswith ('attach' ):
0 commit comments