Browse Source

[action/ci] add qemu-pre-build-and-post-build for RT_SMART build (#10203)

[action/ci] add qemu-pre-build-and-post-build for RT_SMART build
Supper Thomas 5 days ago
parent
commit
427e177526

+ 8 - 1
.github/ALL_BSP_COMPILE.json

@@ -69,7 +69,6 @@
       "RTT_TOOL_CHAIN": "sourcery-arm",
       "SUB_RTT_BSP": [
         "phytium/aarch32",
-        "qemu-vexpress-a9",
         "airm2m/air32f103",
         "acm32/acm32f0x0-nucleo",
         "acm32/acm32f0x0-nucleo",
@@ -457,6 +456,14 @@
         "nrf5x/nrf52840",
         "nrf5x/nrf5340"
       ]
+    },
+    {
+      "RTT_BSP": "arm-none-bsp-smart",
+      "RTT_TOOL_CHAIN": "sourcery-arm",
+      "RTT_SMART_TOOL_CHAIN": "arm-linux-musleabi",
+      "SUB_RTT_BSP": [
+        "qemu-vexpress-a9"
+      ]
     }
   ]
 }

+ 8 - 0
.github/workflows/bsp_buildings.yml

@@ -216,6 +216,14 @@ jobs:
           pip3 install esptool
           echo "RTT_EXEC_PATH=/opt/riscv32-esp-elf/bin" >> $GITHUB_ENV
 
+      - name: Install Arm Musl ToolChains
+        if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-arm' && matrix.legs.RTT_SMART_TOOL_CHAIN == 'arm-linux-musleabi'  && success() }}
+        shell: bash
+        run: |
+          wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.7/arm-linux-musleabi_for_x86_64-pc-linux-gnu_stable.tar.bz2
+          sudo tar xjf arm-linux-musleabi_for_x86_64-pc-linux-gnu_stable.tar.bz2 -C /opt
+          /opt/arm-linux-musleabi_for_x86_64-pc-linux-gnu/bin/arm-linux-musleabi-gcc --version
+
       - name: Install Simulator Tools
         if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'gcc' && success() }}
         run: |

+ 40 - 5
bsp/qemu-vexpress-a9/.ci/attachconfig/ci.attachconfig.yml

@@ -1,3 +1,14 @@
+bsp_board_info:
+  arch: arm
+  toolchain: arm-none-eabi-gcc
+  pre_build: |
+    scons --version
+  build_cmd: |
+    scons -j8
+  post_build: |
+    scons --version
+  run_cmd: ./qemu-nographic.sh
+  qemu_flag: true
 # ------ PERIPHERAL CI ------
 peripheral.UARTv2:
     kconfig:
@@ -15,15 +26,39 @@ peripheral.LVGL:
       - CONFIG_BSP_USING_LVGL=y     
       
 # ------ online-packages CI ------
+online-packages.tools.coremark:
+  kconfig:
+    - CONFIG_PKG_USING_COREMARK=y
+    - CONFIG_COREMARK_ITERATIONS=36000
+  pre_build: |
+    scons --version
+  build_cmd: |
+    scons -j8
+  post_build: |
+    scons --version
+  ci_build_run_flag : true
+  buildcheckresult: "core_main"              #检查编译的log中是否有匹配字
+  msh_cmd: |
+    ps
+    version
+    core_mark
+  msh_cmd_timeout: 60
+  checkresult: 'CoreMark 1.0' #检查执行过程中的log是否有匹配字
+
 online-packages.misc.entertainment.tetris:
     kconfig:
       - CONFIG_PKG_USING_TETRIS=y
 online-packages.misc.entertainment.2048:
     kconfig:
       - CONFIG_PKG_USING_2048=y
-online-packages.ai.llmchat:
+# ------ RT_SMART PART ------
+rt_smart.base:
+    env:
+      RTT_CC_PREFIX: arm-linux-musleabi-
+      RTT_EXEC_PATH: /opt/arm-linux-musleabi_for_x86_64-pc-linux-gnu/bin
+    pre_build: |
+      echo $RTT_CC_PREFIX
     kconfig:
-      - CONFIG_WEBCLIENT_USING_MBED_TLS=y
-      - CONFIG_BSP_DRV_EMAC=y
-      - CONFIG_PKG_USING_LLMCHAT=y
-      - CONFIG_PKG_LLM_API_KEY="sk-xxxxxx"
+      - CONFIG_RT_USING_SMART=y
+      - CONFIG_RT_USING_MEMHEAP=y
+      - CONFIG_RT_USING_DFS_V2=y

+ 119 - 8
tools/ci/bsp_buildings.py

@@ -1,3 +1,17 @@
+# 
+# Copyright (c) 2025, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Change Logs:
+# Date           Author       Notes
+# 2025-04-21     supperthomas add the smart yml support and add env 
+#
+import subprocess
+import threading
+import time
+import logging
+import sys
 import os
 import shutil
 import re
@@ -36,7 +50,7 @@ def run_cmd(cmd, output_info=True):
     return output_str_list, res
 
 
-def build_bsp(bsp, scons_args='',name='default'):
+def build_bsp(bsp, scons_args='',name='default', pre_build_commands=None, post_build_command=None,build_check_result = None,bsp_build_env=None):
     """
     build bsp.
 
@@ -56,21 +70,41 @@ def build_bsp(bsp, scons_args='',name='default'):
 
     """
     success = True
+    # 设置环境变量
+    if bsp_build_env is not None:
+        print("Setting environment variables:")
+        for key, value in bsp_build_env.items():
+            print(f"{key}={value}")
+            os.environ[key] = value  # 设置环境变量
     os.chdir(rtt_root)
     os.makedirs(f'{rtt_root}/output/bsp/{bsp}', exist_ok=True)
     if os.path.exists(f"{rtt_root}/bsp/{bsp}/Kconfig"):
         os.chdir(rtt_root)
-        run_cmd(f'scons -C bsp/{bsp} --pyconfig-silent', output_info=False)
+        run_cmd(f'scons -C bsp/{bsp} --pyconfig-silent', output_info=True)
 
         os.chdir(f'{rtt_root}/bsp/{bsp}')
-        run_cmd('pkgs --update-force', output_info=False)
+        run_cmd('pkgs --update-force', output_info=True)
         run_cmd('pkgs --list')
 
         nproc = multiprocessing.cpu_count()
+        if pre_build_commands is not None:
+            print("Pre-build commands:")
+            print(pre_build_commands)
+            for command in pre_build_commands:
+                print(command)
+                output, returncode = run_cmd(command, output_info=True)
+                print(output)
+                if returncode != 0:
+                    print(f"Pre-build command failed: {command}")
+                    print(output)
         os.chdir(rtt_root)
+        # scons 编译命令
         cmd = f'scons -C bsp/{bsp} -j{nproc} {scons_args}' # --debug=time for debug time
-        __, res = run_cmd(cmd, output_info=True)
-
+        output, res = run_cmd(cmd, output_info=True)
+        if build_check_result is not None:
+            if res != 0 or not check_output(output, build_check_result):
+                    print("Build failed or build check result not found")
+                    print(output)
         if res != 0:
             success = False
         else:
@@ -83,6 +117,13 @@ def build_bsp(bsp, scons_args='',name='default'):
                     shutil.copy(file, f'{rtt_root}/output/bsp/{bsp}/{name.replace("/", "_")}.{file_type[2:]}')
 
     os.chdir(f'{rtt_root}/bsp/{bsp}')
+    if post_build_command is not None:
+        for command in post_build_command:
+            output, returncode = run_cmd(command, output_info=True)
+            print(output)
+            if returncode != 0:
+                print(f"Post-build command failed: {command}")
+                print(output)
     run_cmd('scons -c', output_info=False)
 
     return success
@@ -158,7 +199,17 @@ def build_bsp_attachconfig(bsp, attach_file):
 
     return res
 
+def check_output(output, check_string):
+    """检查输出中是否包含指定字符串"""
+    output_str = ''.join(output) if isinstance(output, list) else str(output)
+    flag = check_string in output_str
+    if flag == True:
+        print('Success: find string ' + check_string)
+    else:
+        print(output)
+        print(f"::error:: can not find string {check_string}  output: {output_str}")
 
+    return flag
 if __name__ == "__main__":
     """
     build all bsp and attach config.
@@ -169,10 +220,12 @@ if __name__ == "__main__":
     """
     failed = 0
     count = 0
+    ci_build_run_flag = False
+    qemu_timeout_second = 50
 
     rtt_root = os.getcwd()
     srtt_bsp = os.getenv('SRTT_BSP').split(',')
-
+    print(srtt_bsp)
     for bsp in srtt_bsp:
         count += 1
         print(f"::group::Compiling BSP: =={count}=== {bsp} ====")
@@ -207,26 +260,80 @@ if __name__ == "__main__":
                                 continue
         
         config_file = os.path.join(rtt_root, 'bsp', bsp, '.config')
-
+        # 在使用 pre_build_commands 之前,确保它被定义
+        pre_build_commands = None
+        build_command = None
+        post_build_command = None
+        qemu_command = None
+        build_check_result = None
+        commands = None
+        check_result = None
+        bsp_build_env = None
         for projects in yml_files_content:
             for name, details in projects.items():
+                # 如果是bsp_board_info,读取基本的信息
+                if(name == 'bsp_board_info'):
+                    print(details)
+                    pre_build_commands = details.get("pre_build").splitlines()
+                    build_command = details.get("build_cmd").splitlines()
+                    post_build_command = details.get("post_build").splitlines()
+                    qemu_command = details.get("run_cmd")
+                
+                if details.get("kconfig") is not None:
+                    if details.get("buildcheckresult")  is not None:
+                        build_check_result = details.get("buildcheckresult")
+                    else:
+                        build_check_result = None
+                    if details.get("msh_cmd") is not None:
+                        commands = details.get("msh_cmd").splitlines()
+                    else:
+                        msh_cmd = None
+                    if details.get("checkresult") is not None:
+                        check_result = details.get("checkresult")
+                    else:
+                        check_result = None
+                    if details.get("ci_build_run_flag") is not None:
+                        ci_build_run_flag = details.get("ci_build_run_flag")
+                    else:
+                        ci_build_run_flag = None
+                    if details.get("pre_build") is not None:
+                        pre_build_commands = details.get("pre_build").splitlines()
+                    if details.get("env") is not None:
+                        bsp_build_env = details.get("env")
+                    else:
+                        bsp_build_env = None
+                    if details.get("build_cmd") is not None:
+                        build_command = details.get("build_cmd").splitlines()
+                    else:
+                        build_command = None
+                    if details.get("post_build") is not None:
+                        post_build_command = details.get("post_build").splitlines()
+                    if details.get("run_cmd") is not None:
+                        qemu_command = details.get("run_cmd")
+                    else:
+                        qemu_command = None
                 count += 1
                 config_bacakup = config_file+'.origin'
                 shutil.copyfile(config_file, config_bacakup)
+                #加载yml中的配置放到.config文件
                 with open(config_file, 'a') as destination:
                     if details.get("kconfig") is None:
+                        #如果没有Kconfig,读取下一个配置
                         continue
                     if(projects.get(name) is not None):
+                        # 获取Kconfig中所有的信息
                         detail_list=get_details_and_dependencies([name],projects)
                         for line in detail_list:
                             destination.write(line + '\n')
                 scons_arg=[]
+                #如果配置中有scons_arg
                 if details.get('scons_arg') is not None:
                     for line in details.get('scons_arg'):
                         scons_arg.append(line)
                 scons_arg_str=' '.join(scons_arg) if scons_arg else ' '
                 print(f"::group::\tCompiling yml project: =={count}==={name}=scons_arg={scons_arg_str}==")
-                res = build_bsp(bsp, scons_arg_str,name=name)
+                # #开始编译bsp
+                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)
                 if not res:
                     print(f"::error::build {bsp} {name} failed.")
                     add_summary(f'\t- ❌ build {bsp} {name} failed.')
@@ -235,11 +342,15 @@ if __name__ == "__main__":
                     add_summary(f'\t- ✅ build {bsp} {name} success.')
                 print("::endgroup::")
 
+
                 shutil.copyfile(config_bacakup, config_file)
                 os.remove(config_bacakup)
 
+
+
         attach_dir = os.path.join(rtt_root, 'bsp', bsp, '.ci/attachconfig')
         attach_list = []
+        #这里是旧的文件方式
         for root, dirs, files in os.walk(attach_dir):
             for file in files:
                 if file.endswith('attach'):