From ee43eeb68577edeb56d2582d657b31e4e29243fb Mon Sep 17 00:00:00 2001 From: CYFS <2805686936@qq.com> Date: Tue, 7 Jul 2026 11:52:14 +0800 Subject: [ci]:add armclang BSP build coverage (#11577) * ci: add armclang BSP build coverage * components/libc: avoid armclang errno include recursion --- tools/building.py | 83 +++++++++++++++++++++++++++++++++++++++++++++-- tools/ci/bsp_buildings.py | 22 ++++++++++--- 2 files changed, 98 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/building.py b/tools/building.py index 6f0eb78775..125da8521e 100644 --- a/tools/building.py +++ b/tools/building.py @@ -48,6 +48,74 @@ Projects = [] Rtt_Root = '' Env = None +if not hasattr(rtconfig, 'CXXFLAGS') and hasattr(rtconfig, 'CFLAGS'): + rtconfig.CXXFLAGS = rtconfig.CFLAGS + +def _path_variants(path): + variants = set() + if not path: + return variants + + normalized = path.replace('\\', '/').rstrip('/') + variants.add(normalized) + variants.add(normalized + '/') + variants.add(normalized.replace('/', '\\')) + variants.add((normalized + '/').replace('/', '\\')) + + return variants + +def _split_exec_path(exec_path): + normalized = exec_path.replace('\\', '/').rstrip('/') + lower = normalized.lower() + for suffix in ('/arm/armclang/bin', '/arm/armcc/bin', '/arm/bin40', '/arm/bin', '/bin'): + if lower.endswith(suffix): + return normalized[:-len(suffix)], normalized[-len(suffix):] + + return normalized, '' + +def _replace_exec_path(value, old_path, new_path): + if not isinstance(value, str): + return value + + result = value + normalized_new_path = new_path.replace('\\', '/').rstrip('/') + for old in sorted(_path_variants(old_path), key=len, reverse=True): + replacement = normalized_new_path.replace('/', '\\') if '\\' in old else normalized_new_path + if old.endswith(('/', '\\')): + replacement += old[-1] + result = result.replace(old, replacement) + + return result + +def _apply_exec_path_override(env, exec_path): + old_exec_path = getattr(rtconfig, 'EXEC_PATH', '') + old_root, suffix = _split_exec_path(old_exec_path) + new_root, new_suffix = _split_exec_path(exec_path) + new_exec_path = new_root + (new_suffix or suffix) + + if old_root: + for name in ('CFLAGS', 'CXXFLAGS', 'AFLAGS', 'LFLAGS', + 'M_CFLAGS', 'M_CXXFLAGS', 'M_LFLAGS'): + if hasattr(rtconfig, name): + setattr(rtconfig, name, _replace_exec_path(getattr(rtconfig, name), old_root, new_root)) + + rtconfig.EXEC_PATH = new_exec_path + for key, name in (('CC', 'CC'), ('CXX', 'CXX'), ('AS', 'AS'), ('AR', 'AR'), + ('LINK', 'LINK'), ('CFLAGS', 'CFLAGS'), + ('CXXFLAGS', 'CXXFLAGS'), ('ASFLAGS', 'AFLAGS'), + ('LINKFLAGS', 'LFLAGS')): + if hasattr(rtconfig, name): + env[key] = getattr(rtconfig, name) + +def _normalize_armclang_flags_for_host(env): + if rtconfig.PLATFORM == 'armclang' and env['PLATFORM'] != 'win32': + for name in ('LFLAGS', 'M_LFLAGS'): + if hasattr(rtconfig, name): + setattr(rtconfig, name, getattr(rtconfig, name).replace('\\', '/')) + + if hasattr(rtconfig, 'LFLAGS'): + env['LINKFLAGS'] = rtconfig.LFLAGS + def _as_unicode(value): try: unicode @@ -208,6 +276,9 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [ os.environ['RTT_EXEC_PATH'] = exec_path utils.ReloadModule(rtconfig) # update environment variables to rtconfig.py + if exec_path: + _apply_exec_path_override(env, exec_path) + _normalize_armclang_flags_for_host(env) # some env variables have loaded in Environment() of SConstruct before re-load rtconfig.py; # after update rtconfig.py's variables, those env variables need to synchronize @@ -219,8 +290,6 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [ env['LINK'] = rtconfig.LINK if exec_path: env.PrependENVPath('PATH', rtconfig.EXEC_PATH) - env['ASCOM']= env['ASPPCOM'] - if GetOption('strict-compiling'): STRICT_FLAGS = '' if rtconfig.PLATFORM in ['gcc']: @@ -241,8 +310,16 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [ env['LIBLINKPREFIX'] = '' env['LIBLINKSUFFIX'] = '.lib' env['LIBDIRPREFIX'] = '--userlibpath ' + if rtconfig.PLATFORM == 'armclang' and rtconfig.AS == 'armasm': + env['ASCOM'] = '$AS $ASFLAGS -o $TARGET $SOURCES' + env['ASPPCOM'] = env['ASCOM'] + else: + env['ASCOM'] = env['ASPPCOM'] + + else: + env['ASCOM'] = env['ASPPCOM'] - elif rtconfig.PLATFORM == 'iccarm': + if rtconfig.PLATFORM == 'iccarm': env['LIBPREFIX'] = '' env['LIBSUFFIX'] = '.a' env['LIBLINKPREFIX'] = '' diff --git a/tools/ci/bsp_buildings.py b/tools/ci/bsp_buildings.py index a07340d439..5c6ade660b 100644 --- a/tools/ci/bsp_buildings.py +++ b/tools/ci/bsp_buildings.py @@ -115,10 +115,20 @@ def is_env_enabled(name, default=False): return value.lower() not in ('', '0', 'false', 'no', 'off') +def get_ci_scons_args(scons_args=''): + args = scons_args.strip() + if os.getenv('RTT_TOOL_CHAIN') == 'armclang' and '--exec-path' not in args: + exec_path = os.getenv('RTT_EXEC_PATH') + if exec_path: + args = f'{args} --exec-path="{exec_path}"'.strip() + + return args + def run_dist_build_check(bsp, scons_args=''): """ build BSP distribution and verify that the generated project can compile. """ + scons_args = get_ci_scons_args(scons_args) os.chdir(rtt_root) bsp_dir = os.path.join(rtt_root, 'bsp', bsp) if not check_bsp_build_scripts(bsp_dir): @@ -144,13 +154,13 @@ def run_dist_build_check(bsp, scons_args=''): return False old_rtt_root = os.environ.pop('RTT_ROOT', None) - _, res = run_cmd(f'scons --pyconfig-silent -C {dist_project}', output_info=True) + _, res = run_cmd(f'scons --pyconfig-silent -C {dist_project} {scons_args}', output_info=True) if res != 0: print(f"::error::dist project pyconfig failed for {bsp}") return False nproc = multiprocessing.cpu_count() - _, res = run_cmd(f'scons -C {dist_project} -j{nproc}', output_info=True) + _, res = run_cmd(f'scons -C {dist_project} -j{nproc} {scons_args}', output_info=True) if res != 0: print(f"::error::dist project build failed for {bsp}") return False @@ -193,6 +203,8 @@ def build_bsp(bsp, scons_args='',name='default', pre_build_commands=None, post_b if not check_bsp_build_scripts(bsp_dir): return False + scons_args = get_ci_scons_args(scons_args) + # 设置环境变量 if bsp_build_env is not None: print("Setting environment variables:") @@ -203,7 +215,7 @@ def build_bsp(bsp, scons_args='',name='default', pre_build_commands=None, post_b 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) - _, res = run_cmd(f'scons -C bsp/{bsp} --pyconfig-silent', output_info=True) + _, res = run_cmd(f'scons -C bsp/{bsp} --pyconfig-silent {scons_args}', output_info=True) if res != 0: print(f"::error::pyconfig failed for {bsp}") success = False @@ -250,6 +262,8 @@ def build_bsp(bsp, scons_args='',name='default', pre_build_commands=None, post_b for file_type in ['*.elf', '*.bin', '*.hex']: files = glob.glob(f'{rtt_root}/bsp/{bsp}/{file_type}') for file in files: + if not os.path.isfile(file): + continue shutil.copy(file, f'{rtt_root}/output/bsp/{bsp}/{name.replace("/", "_")}.{file_type[2:]}') if is_env_enabled('RTT_CI_BUILD_DIST'): print(f"::group::\tChecking dist project: {bsp} {name}") @@ -270,7 +284,7 @@ def build_bsp(bsp, scons_args='',name='default', pre_build_commands=None, post_b print(f"Post-build command failed: {command}") print(output) success = False - _, clean_res = run_cmd('scons -c', output_info=False) + _, clean_res = run_cmd(f'scons -c {scons_args}', output_info=False) if clean_res != 0: print(f"::error::scons clean failed for {bsp}") success = False -- cgit v1.3.1