Skip to content

Commit c466659

Browse files
committed
Arm backend: Add build support aarch64-linux-musl
Add support for aarch64-linux-musl as a toolchain in setup.sh and building the executor_runner as a Linux binary used for direct drive. To download the toolchain and setup the development environment: examples/arm/setup.sh \ --i-agree-to-the-contained-eula \ --target-toolchain linux-musl To build the binary: backends/arm/scripts/build_executorch.sh \ --toolchain=aarch64-linux-musl-gcc --build_type=Debug Signed-off-by: Per Held <per.held@arm.com> Change-Id: If0335b41754be598647dfef08bf23aae1a72409f
1 parent 7edb46d commit c466659

7 files changed

Lines changed: 111 additions & 21 deletions

File tree

CMakePresets.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,20 @@
285285
"EXECUTORCH_BUILD_PRESET_FILE": "${sourceDir}/tools/cmake/preset/arm_baremetal.cmake",
286286
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake"
287287
}
288+
},
289+
{
290+
"name": "arm-ethosu-linux",
291+
"displayName": "Build ExecuTorch for Arm Ethos-U Linux",
292+
"inherits": ["common"],
293+
"cacheVariables": {
294+
"EXECUTORCH_BUILD_ARM_ETHOSU_LINUX": "ON",
295+
"EXECUTORCH_BUILD_EXECUTOR_RUNNER": "ON",
296+
"EXECUTORCH_BUILD_KERNELS_QUANTIZED": "ON",
297+
"CMAKE_C_FLAGS_RELEASE": "-UNDEBUG",
298+
"CMAKE_CXX_FLAGS_RELEASE": "-UNDEBUG",
299+
"_comment": "musl declares __assert_fail with int for line; avoid NDEBUG forward-decl mismatch in Release builds",
300+
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/examples/arm/ethos-u-setup/aarch64-linux-musl-toolchain.cmake"
301+
}
288302
}
289303
],
290304
"buildPresets": [

backends/arm/runtime/EthosUBackend_Cortex_A.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,12 @@ EthosULinuxDeviceCache& get_linux_device_cache() {
150150
return cache;
151151
}
152152

153-
const char* inference_status_to_string(EthosU::InferenceStatus status) {
153+
/*
154+
* Used for logging when building in Debug mode, but unused building
155+
* for Release.
156+
*/
157+
[[maybe_unused]] const char* inference_status_to_string(
158+
EthosU::InferenceStatus status) {
154159
switch (status) {
155160
case EthosU::InferenceStatus::OK:
156161
return "OK";
@@ -288,11 +293,10 @@ Error invoke_linux_driver(
288293

289294
if (options.enable_cycle_counter) {
290295
try {
291-
uint64_t cycles = inference->getCycleCounter();
292296
ET_LOG(
293297
Info,
294298
"Ethos-U Linux delegate cycle counter: %llu",
295-
static_cast<unsigned long long>(cycles));
299+
static_cast<unsigned long long>(inference->getCycleCounter()));
296300
} catch (const std::exception& e) {
297301
ET_LOG(Debug, "Failed to read Ethos-U cycle counter: %s", e.what());
298302
}

backends/arm/scripts/build_executor_runner.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ help() {
5050
echo " --output=<FOLDER> Output folder Default: <MODEL>/<MODEL>_<TARGET INFO>.pte"
5151
echo " --et_build_root=<FOLDER> Build output root folder to use, defaults to ${et_build_root}"
5252
echo " --ethosu_tools_dir=<FOLDER> Path to your Ethos-U tools dir if you not using default: ${ethosu_tools_dir}"
53-
echo " --toolchain=<TOOLCHAIN> Toolchain can be specified (e.g. bare metal as arm-none-eabi-gcc or zephyr as arm-zephyr-eabi-gcc Default: ${toolchain}"
53+
echo " --toolchain=<TOOLCHAIN> Toolchain can be specified (arm-none-eabi-gcc, arm-zephyr-eabi-gcc). Default: ${toolchain}"
5454
echo " --select_ops_list=<OPS> Comma separated list of portable (non delagated) kernels to include Default: ${select_ops_list}"
5555
echo " NOTE: This is used when select_ops_model is not possible to use, e.g. for semihosting or bundleio."
5656
echo " See https://docs.pytorch.org/executorch/stable/kernel-library-selective-build.html for more information."
@@ -82,6 +82,11 @@ if [[ ${toolchain} == "arm-none-eabi-gcc" ]]; then
8282
toolchain_cmake=${et_root_dir}/examples/arm/ethos-u-setup/${toolchain}.cmake
8383
elif [[ ${toolchain} == "arm-zephyr-eabi-gcc" ]]; then
8484
toolchain_cmake=${et_root_dir}/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake
85+
elif [[ ${toolchain} == "aarch64-linux-musl-gcc" ]]; then
86+
echo "Error: aarch64-linux-musl-gcc is not supported for this bare-metal runner."
87+
echo " Use executorch/backends/arm/scripts/build_executorch.sh with aarch64-linux-musl-gcc"
88+
echo " or run the direct drive CMake flow to build executor_runner for Linux."
89+
exit 1;
8590
else
8691
echo "Error: Invalid toolchain selection, provided: ${toolchain}"
8792
echo " Valid options are {arm-none-eabi-gcc, arm-zephyr-eabi-gcc}"

backends/arm/scripts/build_executorch.sh

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
# Copyright 2025 Arm Limited and/or its affiliates.
2+
# Copyright 2025-2026 Arm Limited and/or its affiliates.
33
#
44
# This source code is licensed under the BSD-style license found in the
55
# LICENSE file in the root directory of this source tree.
@@ -23,6 +23,7 @@ et_build_root="${et_root_dir}/arm_test"
2323
build_type="Release"
2424
build_devtools=OFF
2525
build_with_etdump=OFF
26+
is_linux_musl=0
2627

2728
help() {
2829
echo "Usage: $(basename $0) [options]"
@@ -31,7 +32,7 @@ help() {
3132
echo " --build_type=<TYPE> Build with Release, Debug, RelWithDebInfo, UndefinedSanitizer or AddressSanitizer, default is ${build_type}"
3233
echo " --devtools Build Devtools libs"
3334
echo " --etdump Adds Devtools etdump support to track timing, etdump area will be base64 encoded in the log"
34-
echo " --toolchain=<TOOLCHAIN> Toolchain can be specified (e.g. bare metal as arm-none-eabi-gcc or zephyr as arm-zephyr-eabi-gcc Default: ${toolchain}"
35+
echo " --toolchain=<TOOLCHAIN> Toolchain can be specified (arm-none-eabi-gcc, arm-zephyr-eabi-gcc, aarch64-linux-musl-gcc). Default: ${toolchain}"
3536
exit 0
3637
}
3738

@@ -52,9 +53,12 @@ if [[ ${toolchain} == "arm-none-eabi-gcc" ]]; then
5253
toolchain_cmake=${et_root_dir}/examples/arm/ethos-u-setup/${toolchain}.cmake
5354
elif [[ ${toolchain} == "arm-zephyr-eabi-gcc" ]]; then
5455
toolchain_cmake=${et_root_dir}/examples/zephyr/x86_64-linux-arm-zephyr-eabi-gcc.cmake
56+
elif [[ ${toolchain} == "aarch64-linux-musl-gcc" ]]; then
57+
toolchain_cmake=${et_root_dir}/examples/arm/ethos-u-setup/aarch64-linux-musl-toolchain.cmake
58+
is_linux_musl=1
5559
else
5660
echo "Error: Invalid toolchain selection, provided: ${toolchain}"
57-
echo " Valid options are {arm-none-eabi-gcc, arm-zephyr-eabi-gcc}"
61+
echo " Valid options are {arm-none-eabi-gcc, arm-zephyr-eabi-gcc, aarch64-linux-musl-gcc}"
5862
exit 1;
5963
fi
6064
toolchain_cmake=$(realpath ${toolchain_cmake})
@@ -76,18 +80,40 @@ cd "${et_root_dir}"
7680
echo "Build ExecuTorch target libs ${build_type} into '${et_build_dir}'" ;
7781
echo "--------------------------------------------------------------------------------" )
7882

79-
# Build
80-
cmake -DCMAKE_TOOLCHAIN_FILE=${toolchain_cmake} \
81-
-DCMAKE_BUILD_TYPE=${build_type} \
82-
-DEXECUTORCH_BUILD_DEVTOOLS=$build_devtools \
83-
-DEXECUTORCH_BUILD_ARM_ETDUMP=$build_with_etdump \
84-
--preset arm-baremetal -B${et_build_dir}
83+
cmake_args=(
84+
-DCMAKE_TOOLCHAIN_FILE=${toolchain_cmake}
85+
-DCMAKE_BUILD_TYPE=${build_type}
86+
-DEXECUTORCH_BUILD_DEVTOOLS=${build_devtools}
87+
-DEXECUTORCH_BUILD_ARM_ETDUMP=${build_with_etdump}
88+
)
89+
90+
if [[ ${is_linux_musl} -eq 1 ]]; then
91+
if [[ -z "${MUSL_TOOLCHAIN_ROOT:-}" ]]; then
92+
echo "Error: MUSL_TOOLCHAIN_ROOT is required for aarch64-linux-musl-gcc."
93+
echo " Source ${setup_path_script} after running examples/arm/setup.sh --target-toolchain linux-musl."
94+
exit 1
95+
fi
96+
cmake -S "${et_root_dir}" -B "${et_build_dir}" \
97+
"${cmake_args[@]}" \
98+
--preset arm-ethosu-linux \
99+
-DPYTHON_EXECUTABLE=$(which python3)
100+
else
101+
cmake "${cmake_args[@]}" --preset arm-baremetal -B${et_build_dir}
102+
fi
85103

86104
parallel_jobs="$(get_parallel_jobs)"
87105

88-
cmake --build ${et_build_dir} -j"${parallel_jobs}" --target install --config ${build_type} --
106+
if [[ ${is_linux_musl} -eq 1 ]]; then
107+
cmake --build ${et_build_dir} -j"${parallel_jobs}" --target executorch_delegate_ethos_u executor_runner --config ${build_type} --
108+
else
109+
cmake --build ${et_build_dir} -j"${parallel_jobs}" --target install --config ${build_type} --
110+
fi
89111

90112
set +x
91113

92-
echo "[$(basename $0)] Generated static libraries for ExecuTorch:"
93-
find ${et_build_dir} -name "*.a" -exec ls -al {} \;
114+
if [[ ${is_linux_musl} -eq 1 ]]; then
115+
echo "[$(basename $0)] Built ExecuTorch targets in ${et_build_dir}"
116+
else
117+
echo "[$(basename $0)] Generated static libraries for ExecuTorch:"
118+
find ${et_build_dir} -name "*.a" -exec ls -al {} \;
119+
fi

backends/arm/scripts/toolchain_utils.sh

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,18 @@ function gcc_select_toolchain() {
2525
toolchain_url="https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz"
2626
toolchain_dir="arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi"
2727
toolchain_md5_checksum="0601a9588bc5b9c99ad2b56133b7f118"
28+
toolchain_archive="${toolchain_dir}.tar.xz"
2829
elif [[ "${ARCH}" == "aarch64" ]] || [[ "${ARCH}" == "arm64" ]] ; then
2930
if [[ "${OS}" == "Darwin" ]]; then
3031
toolchain_url="https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-darwin-arm64-arm-none-eabi.tar.xz"
3132
toolchain_dir="arm-gnu-toolchain-13.3.rel1-darwin-arm64-arm-none-eabi"
3233
toolchain_md5_checksum="f1c18320bb3121fa89dca11399273f4e"
34+
toolchain_archive="${toolchain_dir}.tar.xz"
3335
elif [[ "${OS}" == "Linux" ]]; then
3436
toolchain_url="https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-aarch64-arm-none-eabi.tar.xz"
3537
toolchain_dir="arm-gnu-toolchain-13.3.rel1-aarch64-arm-none-eabi"
3638
toolchain_md5_checksum="303102d97b877ebbeb36b3158994b218"
39+
toolchain_archive="${toolchain_dir}.tar.xz"
3740
fi
3841
else
3942
# This should never happen, it should be covered by setup.sh but catch it anyway
@@ -52,20 +55,41 @@ function zephyr_select_toolchain() {
5255
toolchain_url="https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/toolchain_linux-x86_64_arm-zephyr-eabi.tar.xz"
5356
toolchain_dir="arm-zephyr-eabi"
5457
toolchain_md5_checksum="68ae71edc0106c3093055b97aaa47017"
58+
toolchain_archive="${toolchain_dir}.tar.xz"
5559
elif [[ "${ARCH}" == "aarch64" ]] || [[ "${ARCH}" == "arm64" ]] ; then
5660
toolchain_url="https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.17.4/toolchain_linux-aarch64_arm-zephyr-eabi.tar.xz"
5761
toolchain_dir="arm-zephyr-eabi"
5862
toolchain_md5_checksum="d8a6dfd4314d55da713957d0b161d01f"
63+
toolchain_archive="${toolchain_dir}.tar.xz"
5964
else
6065
# This should never happen, it should be covered by setup.sh but catch it anyway
6166
log_step "toolchain" "Error: Unsupported architecture ${ARCH}"
6267
exit 1
6368
fi
6469
}
6570

71+
function musl_select_toolchain() {
72+
if [[ "${OS}" != "Linux" ]] ; then
73+
log_step "toolchain" "Error: Linux is required for musl toolchain support"
74+
exit 1
75+
fi
76+
77+
if [[ "${ARCH}" == "x86_64" ]] ; then
78+
toolchain_url="https://musl.cc/aarch64-linux-musl-cross.tgz"
79+
toolchain_dir="aarch64-linux-musl-cross"
80+
toolchain_md5_checksum="a6bb806af217a91cf575e15163e8b12b"
81+
toolchain_archive="${toolchain_dir}.tgz"
82+
else
83+
log_step "toolchain" "Error: Unsupported architecture ${ARCH} for musl toolchain"
84+
exit 1
85+
fi
86+
}
87+
6688
function select_toolchain() {
6789
if [[ "${target_toolchain}" == "zephyr" ]]; then
6890
zephyr_select_toolchain
91+
elif [[ "${target_toolchain}" == "linux-musl" ]]; then
92+
musl_select_toolchain
6993
else
7094
gcc_select_toolchain
7195
fi
@@ -76,18 +100,28 @@ function setup_toolchain() {
76100
# Download and install the arm toolchain (default is arm-none-eabi)
77101
# setting --target-toolchain to zephyr sets this to arm-zephyr-eabi
78102
cd "${root_dir}"
79-
if [[ ! -e "${toolchain_dir}.tar.xz" ]]; then
103+
if [[ -z "${toolchain_archive}" ]]; then
104+
log_step "toolchain" "Error: Toolchain archive not set"
105+
exit 1
106+
fi
107+
108+
if [[ ! -e "${toolchain_archive}" ]]; then
80109
log_step "toolchain" "Downloading ${toolchain_dir} toolchain"
81-
curl --output "${toolchain_dir}.tar.xz" -L "${toolchain_url}"
82-
verify_md5 ${toolchain_md5_checksum} "${toolchain_dir}.tar.xz" || exit 1
110+
curl --output "${toolchain_archive}" -L "${toolchain_url}"
111+
verify_md5 ${toolchain_md5_checksum} "${toolchain_archive}" || exit 1
83112
fi
84113

85114
log_step "toolchain" "Installing ${toolchain_dir} toolchain"
86115
rm -rf "${toolchain_dir}"
87-
tar xf "${toolchain_dir}.tar.xz"
116+
tar xf "${toolchain_archive}"
88117
}
89118

90119
function setup_path_toolchain() {
91120
toolchain_bin_path="$(cd ${toolchain_dir}/bin && pwd)"
92121
append_env_in_setup_path PATH ${toolchain_bin_path}
122+
123+
if [[ "${target_toolchain}" == "linux-musl" ]]; then
124+
local toolchain_root_path="$(cd ${toolchain_dir} && pwd)"
125+
set_env_in_setup_path MUSL_TOOLCHAIN_ROOT ${toolchain_root_path}
126+
fi
93127
}

backends/arm/scripts/utils.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
# Copyright 2025 Arm Limited and/or its affiliates.
2+
# Copyright 2025-2026 Arm Limited and/or its affiliates.
33
#
44
# This source code is licensed under the BSD-style license found in the
55
# LICENSE file in the root directory of this source tree.
@@ -138,6 +138,11 @@ function append_env_in_setup_path() {
138138
echo "set --path -agx $1 $2" >> ${setup_path_script}.fish
139139
}
140140

141+
function set_env_in_setup_path() {
142+
echo "export $1=$2" >> ${setup_path_script}.sh
143+
echo "set -gx $1 $2" >> ${setup_path_script}.fish
144+
}
145+
141146
function clear_setup_path() {
142147
# Clear setup_path_script
143148
echo "" > "${setup_path_script}.sh"

examples/arm/setup.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ enable_mlsdk_pip_install=1
3535
toolchain_url=""
3636
toolchain_dir=""
3737
toolchain_md5_checksum=""
38+
toolchain_archive=""
3839

3940
# Load logging helpers early so option parsing can emit status messages.
4041
source "$et_dir/backends/arm/scripts/utils.sh"
@@ -45,6 +46,7 @@ OPTION_LIST=(
4546
"--i-agree-to-the-contained-eula (required) Agree to the EULA"
4647
"--root-dir Path to scratch directory"
4748
"--enable-baremetal-toolchain Enable baremetal toolchain setup"
49+
"--target-toolchain Select toolchain: gnu (default), zephyr, or linux-musl"
4850
"--enable-fvps Enable FVP setup"
4951
"--enable-vela Enable VELA setup"
5052
"--enable-model-converter Enable MLSDK model converter setup"

0 commit comments

Comments
 (0)