From b96719f7d77f21a3d6743469e0216f7f646bcb70 Mon Sep 17 00:00:00 2001 From: CYFS <2805686936@qq.com> Date: Mon, 6 Jul 2026 15:37:58 +0800 Subject: [PATCH 1/2] ci: add armclang BSP build coverage --- .github/ALL_BSP_COMPILE.json | 7 ++ .github/armclang-vcpkg-configuration.json | 12 ++++ .github/workflows/bsp_buildings.yml | 38 ++++++++++- tools/building.py | 83 ++++++++++++++++++++++- tools/ci/bsp_buildings.py | 22 ++++-- 5 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 .github/armclang-vcpkg-configuration.json diff --git a/.github/ALL_BSP_COMPILE.json b/.github/ALL_BSP_COMPILE.json index 641d950ce53..5a78a865e5e 100644 --- a/.github/ALL_BSP_COMPILE.json +++ b/.github/ALL_BSP_COMPILE.json @@ -466,6 +466,13 @@ "stm32/stm32l475-atk-pandora" ] }, + { + "RTT_BSP": "armclang-stm32", + "RTT_TOOL_CHAIN": "armclang", + "SUB_RTT_BSP": [ + "stm32/stm32f407-rt-spark" + ] + }, { "RTT_BSP": "simulator", "RTT_TOOL_CHAIN": "gcc", diff --git a/.github/armclang-vcpkg-configuration.json b/.github/armclang-vcpkg-configuration.json new file mode 100644 index 00000000000..02f6c0b3501 --- /dev/null +++ b/.github/armclang-vcpkg-configuration.json @@ -0,0 +1,12 @@ +{ + "registries": [ + { + "name": "arm", + "kind": "artifact", + "location": "https://artifacts.tools.arm.com/vcpkg-registry" + } + ], + "requires": { + "arm:compilers/arm/armclang": "^6.24.0" + } +} diff --git a/.github/workflows/bsp_buildings.yml b/.github/workflows/bsp_buildings.yml index 707777a250c..0792d9fdf31 100644 --- a/.github/workflows/bsp_buildings.yml +++ b/.github/workflows/bsp_buildings.yml @@ -161,6 +161,42 @@ jobs: echo "RTT_CC=llvm-arm" >> $GITHUB_ENV echo "RTT_EXEC_PATH=/opt/LLVMEmbeddedToolchainForArm-16.0.0-Linux-x86_64/bin" >> $GITHUB_ENV + - name: Install ArmClang ToolChains + if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'armclang' && success() }} + uses: ARM-software/cmsis-actions/setup-vcpkg@v1 + with: + version: 2026.04.27 + + - name: Activate ArmClang ToolChains + if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'armclang' && success() }} + uses: ARM-software/cmsis-actions/vcpkg@v1 + with: + config: .github/armclang-vcpkg-configuration.json + cache: ${{ runner.os }}-armclang-6.24.0 + + - name: Activate ArmClang License + if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'armclang' && success() }} + uses: ARM-software/cmsis-actions/armlm@v1 + with: + product: KEMDK-COM0 + + - name: Configure ArmClang ToolChains + if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'armclang' && success() }} + shell: bash + run: | + armclang --version + command -v armlink + command -v fromelf + ARMCLANG_BIN="${AC6_TOOLCHAIN_6_24_0:-$(dirname "$(command -v armclang)")}" + ARMCLANG_BIN="${ARMCLANG_BIN%/}" + ARMCLANG_ROOT="$(dirname "$ARMCLANG_BIN")" + test -d "$ARMCLANG_ROOT/include" + test -d "$ARMCLANG_ROOT/lib" + sudo mkdir -p /opt/Keil_v5/ARM + sudo ln -sfn "$ARMCLANG_ROOT" /opt/Keil_v5/ARM/ARMCLANG + echo "RTT_CC=keil" >> $GITHUB_ENV + echo "RTT_EXEC_PATH=/opt/Keil_v5" >> $GITHUB_ENV + - name: Install AArch64 ToolChains if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-aarch64' && matrix.legs.RTT_SMART_TOOL_CHAIN != 'aarch64-linux-musleabi' && success() }} shell: bash @@ -288,7 +324,7 @@ jobs: RTT_TOOL_CHAIN: ${{ matrix.legs.RTT_TOOL_CHAIN }} SRTT_BSP: ${{ join(matrix.legs.SUB_RTT_BSP, ',') }} ATTACHCONFIG_RTT_BSP: ${{ join(matrix.legs.ATTACHCONFIG_RTT_BSP || fromJSON('[]'), ',') }} - RTT_CI_BUILD_DIST: "1" + RTT_CI_BUILD_DIST: ${{ matrix.legs.RTT_TOOL_CHAIN == 'armclang' && '0' || '1' }} run: | source ~/.env/env.sh python tools/ci/bsp_buildings.py diff --git a/tools/building.py b/tools/building.py index 6f0eb78775e..125da8521e7 100644 --- a/tools/building.py +++ b/tools/building.py @@ -48,6 +48,74 @@ 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 a07340d4397..5c6ade660ba 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 From f90a6c4d6c5f925f986aae037f369f6ac3d80de3 Mon Sep 17 00:00:00 2001 From: CYFS <2805686936@qq.com> Date: Mon, 6 Jul 2026 15:38:29 +0800 Subject: [PATCH 2/2] components/libc: avoid armclang errno include recursion --- .../compilers/common/extension/sys/errno.h | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/components/libc/compilers/common/extension/sys/errno.h b/components/libc/compilers/common/extension/sys/errno.h index 6c6727ca841..20ac628e469 100644 --- a/components/libc/compilers/common/extension/sys/errno.h +++ b/components/libc/compilers/common/extension/sys/errno.h @@ -38,8 +38,30 @@ defined in armcc/errno.h #define ERROR_BASE_NO 0 #endif -#if defined(__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__) +#if defined(__ARMCC_VERSION) +#ifndef EDOM +#define EDOM 1 +#endif +#ifndef ERANGE +#define ERANGE 2 +#endif +#ifndef ESIGNUM +#define ESIGNUM 3 +#endif +#ifndef EILSEQ +#define EILSEQ 4 +#endif +#ifndef EINVAL +#define EINVAL 5 +#endif +#ifndef ENOMEM +#define ENOMEM 6 +#endif +#elif defined(__IAR_SYSTEMS_ICC__) #include +#endif + +#if defined(__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__) #ifndef EPERM #define EPERM (ERROR_BASE_NO + 1)