[ci]:add armclang BSP build coverage (#11577)

* ci: add armclang BSP build coverage

* components/libc: avoid armclang errno include recursion
This commit is contained in:
CYFS 2026-07-07 11:52:14 +08:00 committed by GitHub
parent 937be2c97d
commit ee43eeb685
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 177 additions and 9 deletions

View File

@ -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",

View File

@ -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"
}
}

View File

@ -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

View File

@ -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 <errno.h>
#endif
#if defined(__ARMCC_VERSION) || defined(__IAR_SYSTEMS_ICC__)
#ifndef EPERM
#define EPERM (ERROR_BASE_NO + 1)

View File

@ -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']
elif rtconfig.PLATFORM == 'iccarm':
else:
env['ASCOM'] = env['ASPPCOM']
if rtconfig.PLATFORM == 'iccarm':
env['LIBPREFIX'] = ''
env['LIBSUFFIX'] = '.a'
env['LIBLINKPREFIX'] = ''

View File

@ -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