diff --git a/backends/arm/scripts/build_executor_runner.sh b/backends/arm/scripts/build_executor_runner.sh index f2ffd2e27a7..cd65c687023 100755 --- a/backends/arm/scripts/build_executor_runner.sh +++ b/backends/arm/scripts/build_executor_runner.sh @@ -9,6 +9,9 @@ set -eu script_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) et_root_dir=$(cd ${script_dir}/../../.. && pwd) et_root_dir=$(realpath ${et_root_dir}) +runner_source_dir=${et_root_dir}/examples/arm/executor_runner +runner_source_dir=$(realpath ${runner_source_dir}) +preset_file=${et_root_dir}/tools/cmake/preset/arm_baremetal.cmake toolchain=arm-none-eabi-gcc setup_path_script=${et_root_dir}/examples/arm/arm-scratch/setup_path.sh _setup_msg="please refer to ${et_root_dir}/examples/arm/setup.sh to properly install necessary tools." @@ -101,6 +104,9 @@ toolchain_cmake=$(realpath ${toolchain_cmake}) source ${setup_path_script} +[[ -f ${preset_file} ]] \ + || { echo "Missing ${preset_file}. ${_setup_msg}"; exit 1; } + if [[ ${pte_file} == "semihosting" ]]; then pte_data="-DSEMIHOSTING=ON" else @@ -122,13 +128,9 @@ else fi fi ethosu_tools_dir=$(realpath ${ethosu_tools_dir}) -ethos_u_root_dir="$ethosu_tools_dir/ethos-u" +ethos_u_root_dir="${ethosu_tools_dir}/ethos-u" mkdir -p "${ethos_u_root_dir}" -ethosu_tools_dir=$(realpath ${ethos_u_root_dir}) - -et_build_dir=${et_build_root}/cmake-out -mkdir -p ${et_build_dir} -et_build_dir=$(realpath ${et_build_dir}) +ethos_u_root_dir=$(realpath ${ethos_u_root_dir}) if [[ ${system_config} == "" ]] then @@ -160,34 +162,46 @@ echo "-------------------------------------------------------------------------- echo "Build Arm ${toolchain/-gcc/} executor_runner for ${target} PTE: ${pte_file} using ${system_config} ${memory_mode} ${extra_build_flags} to '${output_folder}'" echo "--------------------------------------------------------------------------------" -cd ${et_root_dir}/examples/arm/executor_runner - if [ "$bundleio" = true ] ; then build_bundleio_flags=" -DET_BUNDLE_IO=ON " + candidate_build_dir="${et_build_root}/cmake-out" + if [[ -d "${candidate_build_dir}" ]]; then + candidate_build_dir=$(realpath "${candidate_build_dir}") + build_bundleio_flags+=" -DET_BUILD_DIR_PATH=${candidate_build_dir} " + fi + if [[ -n "${BUNDLED_PROGRAM_LIBRARY_DIR:-}" ]]; then + build_bundleio_flags+=" -DBUNDLED_PROGRAM_LIBRARY_DIR=${BUNDLED_PROGRAM_LIBRARY_DIR} " + fi fi if [ "$build_with_etdump" = true ] ; then build_with_etdump_flags=" -DEXECUTORCH_ENABLE_EVENT_TRACER=ON -DET_DUMP_INTERMEDIATE_OUTPUTS=ON " fi +devtools_flags="" +if [ "$bundleio" = true ] || [ "$build_with_etdump" = true ] ; then + devtools_flags=" -DEXECUTORCH_BUILD_DEVTOOLS=ON " +fi -echo "Building with BundleIO/etdump/extra flags: ${build_bundleio_flags} ${build_with_etdump_flags} ${extra_build_flags}" +echo "Building with BundleIO/etdump/extra flags: ${build_bundleio_flags} ${build_with_etdump_flags} ${devtools_flags} ${extra_build_flags}" cmake \ - -DCMAKE_BUILD_TYPE=${build_type} \ - -DCMAKE_TOOLCHAIN_FILE=${toolchain_cmake} \ - -DTARGET_CPU=${target_cpu} \ - -DET_DIR_PATH:PATH=${et_root_dir} \ - -DET_BUILD_DIR_PATH:PATH=${et_build_dir} \ - -DETHOS_SDK_PATH:PATH=${ethos_u_root_dir} \ - -DETHOSU_TARGET_NPU_CONFIG=${target} \ - ${pte_data} \ - ${build_bundleio_flags} \ - ${build_with_etdump_flags} \ - -DPYTHON_EXECUTABLE=$(which python3) \ - -DSYSTEM_CONFIG=${system_config} \ - -DMEMORY_MODE=${memory_mode} \ + -S ${runner_source_dir} \ + -B ${output_folder} \ + -DEXECUTORCH_ROOT=${et_root_dir} \ + -DCMAKE_BUILD_TYPE=${build_type} \ + -DCMAKE_TOOLCHAIN_FILE=${toolchain_cmake} \ + -DTARGET_CPU=${target_cpu} \ + -DETHOSU_TARGET_NPU_CONFIG=${target} \ + -DEXECUTORCH_BUILD_PRESET_FILE=${preset_file} \ + -DEXECUTORCH_BAREMETAL_SKIP_INSTALL=OFF \ + ${pte_data} \ + ${build_bundleio_flags} \ + ${build_with_etdump_flags} \ + ${devtools_flags} \ + -DSYSTEM_CONFIG=${system_config} \ + -DMEMORY_MODE=${memory_mode} \ -DEXECUTORCH_SELECT_OPS_LIST="${select_ops_list}" \ - ${extra_build_flags} \ - -B ${output_folder} + -DETHOS_SDK_PATH:PATH=${ethos_u_root_dir} \ + ${extra_build_flags} echo "[${BASH_SOURCE[0]}] Configured CMAKE" diff --git a/examples/arm/executor_runner/CMakeLists.txt b/examples/arm/executor_runner/CMakeLists.txt index c169f5d447a..0a8f218257f 100644 --- a/examples/arm/executor_runner/CMakeLists.txt +++ b/examples/arm/executor_runner/CMakeLists.txt @@ -3,8 +3,142 @@ # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. -cmake_minimum_required(VERSION 3.20) -project(arm_executor_runner) +set(_arm_executor_runner_standalone FALSE) +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + cmake_minimum_required(VERSION 3.20) + project(arm_executor_runner LANGUAGES C CXX) + set(_arm_executor_runner_standalone TRUE) +endif() + +if(_arm_executor_runner_standalone) + set(ARM_EXECUTOR_RUNNER_STANDALONE + ${_arm_executor_runner_standalone} + CACHE + BOOL + "Indicates arm_executor_runner was configured as a standalone project" + FORCE + ) +endif() + +# Derive the ExecuTorch checkout root by walking upward until we find the shared +# tooling directory rather than assuming a fixed relative depth. +set(_candidate_executorch_root "${CMAKE_CURRENT_LIST_DIR}") +set(_default_executorch_root "") +while(TRUE) + if(EXISTS "${_candidate_executorch_root}/tools/cmake/common/preset.cmake") + set(_default_executorch_root "${_candidate_executorch_root}") + break() + endif() + get_filename_component(_parent_dir "${_candidate_executorch_root}" DIRECTORY) + if(_parent_dir STREQUAL "${_candidate_executorch_root}") + break() + endif() + set(_candidate_executorch_root "${_parent_dir}") +endwhile() + +if(_default_executorch_root STREQUAL "") + message( + FATAL_ERROR + "Unable to locate an ExecuTorch checkout near ${CMAKE_CURRENT_LIST_DIR}. Please rerun CMake with -DEXECUTORCH_ROOT=." + ) +endif() + +if(NOT DEFINED EXECUTORCH_ROOT) + set(EXECUTORCH_ROOT + "${_default_executorch_root}" + CACHE PATH "Path to an ExecuTorch checkout" + ) +endif() + +set(ET_DIR_PATH + "${EXECUTORCH_ROOT}" + CACHE PATH "Kept for backward compatibility; synonym for EXECUTORCH_ROOT" +) + +if(NOT EXISTS "${EXECUTORCH_ROOT}/CMakeLists.txt") + if(EXISTS "${_default_executorch_root}/CMakeLists.txt") + message( + WARNING + "EXECUTORCH_ROOT (${EXECUTORCH_ROOT}) does not contain an ExecuTorch CMake project. Falling back to ${_default_executorch_root}." + ) + set(EXECUTORCH_ROOT + "${_default_executorch_root}" + CACHE PATH "Path to an ExecuTorch checkout" FORCE + ) + set(ET_DIR_PATH + "${EXECUTORCH_ROOT}" + CACHE PATH + "Kept for backward compatibility; synonym for EXECUTORCH_ROOT" + FORCE + ) + else() + message( + FATAL_ERROR + "EXECUTORCH_ROOT (${EXECUTORCH_ROOT}) does not contain an ExecuTorch CMake project." + ) + endif() +endif() + +if(_arm_executor_runner_standalone) + # Load the preset helper so standalone builds inherit the same defaults as the + # superbuild (toolchains, delegated targets, devtools options, etc.). + set(_executorch_preset_cmake + "${EXECUTORCH_ROOT}/tools/cmake/common/preset.cmake" + ) + if(EXISTS "${_executorch_preset_cmake}") + include("${_executorch_preset_cmake}") + if(NOT DEFINED EXECUTORCH_BUILD_PRESET_FILE) + set(EXECUTORCH_BUILD_PRESET_FILE + "${EXECUTORCH_ROOT}/tools/cmake/preset/arm_baremetal.cmake" + CACHE PATH "Preset used when configuring the standalone runner" + ) + endif() + load_build_preset() + endif() + include(${EXECUTORCH_ROOT}/tools/cmake/Utils.cmake) + + # Configure the standalone runner’s cache defaults and pull ExecuTorch in-tree + # so all required targets are built from this checkout. + option(ARM_EXECUTOR_RUNNER_SKIP_INSTALL_RULES + "Skip install() rules for standalone arm_executor_runner builds" ON + ) + if(DEFINED CMAKE_SKIP_INSTALL_RULES) + set(_arm_runner_skip_install_rules "${CMAKE_SKIP_INSTALL_RULES}") + endif() + if(ARM_EXECUTOR_RUNNER_SKIP_INSTALL_RULES) + set(CMAKE_SKIP_INSTALL_RULES ON) + endif() + foreach( + _opt + EXECUTORCH_BUILD_ARM_BAREMETAL EXECUTORCH_BUILD_CORTEX_M + EXECUTORCH_BUILD_KERNELS_QUANTIZED EXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL + ) + if(NOT DEFINED ${_opt}) + set(${_opt} + ON + CACHE BOOL "" FORCE + ) + endif() + endforeach() + set(EXECUTORCH_SKIP_ARM_EXECUTOR_RUNNER + ON + CACHE BOOL "" FORCE + ) + # When configured on its own, pull ExecuTorch in-tree so all required targets + # (delegates, kernels, runner util, etc.) are built from the same checkout. + # The preset above (or manual cache overrides) must configure any top-level + # ExecuTorch options a superbuild would normally supply. + add_subdirectory( + ${EXECUTORCH_ROOT} ${CMAKE_BINARY_DIR}/executorch EXCLUDE_FROM_ALL + ) + if(ARM_EXECUTOR_RUNNER_SKIP_INSTALL_RULES) + if(DEFINED _arm_runner_skip_install_rules) + set(CMAKE_SKIP_INSTALL_RULES "${_arm_runner_skip_install_rules}") + else() + unset(CMAKE_SKIP_INSTALL_RULES) + endif() + endif() +endif() option( ET_MODEL_PTE_ADDR @@ -21,6 +155,12 @@ option(ET_LOG_DUMP_INPUT "Dump input in log" OFF) option(ET_LOG_DUMP_OUTPUT "Dump output in log" ON) option(ET_BUNDLE_IO "Set to compile in BundleIO support" OFF) +set(BUNDLED_PROGRAM_LIBRARY_DIR + "" + CACHE + PATH + "Optional directory that contains a prebuilt libbundled_program.a when ET_BUNDLE_IO is enabled without building devtools." +) set(ET_ATOL "0.01" CACHE STRING "Set atol to use for BundleIO testing (Requires ET_BUNDLE_IO)" @@ -154,13 +294,8 @@ message( add_corstone_subdirectory(${SYSTEM_CONFIG} ${ETHOS_SDK_PATH}) configure_timing_adapters(${SYSTEM_CONFIG} ${MEMORY_MODE}) -# Dependencies from the ExecuTorch build -find_package( - executorch REQUIRED HINTS "${ET_BUILD_DIR_PATH}/lib/cmake/ExecuTorch" -) - # Convert pte to header -if(NOT ${ET_MODEL_PTE_ADDR} AND NOT SEMIHOSTING) +if(NOT "${ET_MODEL_PTE_ADDR}" AND NOT SEMIHOSTING) add_custom_target( gen_model_header DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/model_pte.h ) @@ -333,7 +468,50 @@ if(EXECUTORCH_ENABLE_EVENT_TRACER) endif() if(ET_BUNDLE_IO) - list(APPEND arm_executor_runner_link bundled_program) + if(TARGET bundled_program) + list(APPEND arm_executor_runner_link bundled_program) + target_link_directories( + arm_executor_runner PRIVATE $ + ) + else() + set(_bundled_program_library "") + set(_bundled_program_search_paths "") + if(ET_BUILD_DIR_PATH) + list( + APPEND + _bundled_program_search_paths + "${ET_BUILD_DIR_PATH}" + "${ET_BUILD_DIR_PATH}/lib" + "${ET_BUILD_DIR_PATH}/devtools/bundled_program" + "${ET_BUILD_DIR_PATH}/devtools/bundled_program/lib" + ) + endif() + if(BUNDLED_PROGRAM_LIBRARY_DIR) + list(APPEND _bundled_program_search_paths + "${BUNDLED_PROGRAM_LIBRARY_DIR}" + ) + endif() + if(_bundled_program_search_paths) + list(REMOVE_DUPLICATES _bundled_program_search_paths) + find_library( + _bundled_program_library + NAMES bundled_program + PATHS ${_bundled_program_search_paths} + NO_DEFAULT_PATH + ) + endif() + if(NOT _bundled_program_library) + find_library(_bundled_program_library NAMES bundled_program) + endif() + if(_bundled_program_library) + list(APPEND arm_executor_runner_link ${_bundled_program_library}) + else() + message( + FATAL_ERROR + "ET_BUNDLE_IO enabled but bundled_program is unavailable. Either configure this build with EXECUTORCH_BUILD_DEVTOOLS=ON so the target exists or set BUNDLED_PROGRAM_LIBRARY_DIR/ET_BUILD_DIR_PATH to a build directory that contains libbundled_program.a." + ) + endif() + endif() endif() # Need whole-archive to ensure C++ ctor's are called - this may be wasteful for @@ -386,7 +564,7 @@ target_compile_definitions( arm_executor_runner PRIVATE C10_USING_CUSTOM_GENERATED_MACROS ) -if(NOT ${ET_MODEL_PTE_ADDR} AND NOT SEMIHOSTING) +if(NOT "${ET_MODEL_PTE_ADDR}" AND NOT SEMIHOSTING) add_dependencies(arm_executor_runner gen_model_header) endif() diff --git a/examples/arm/executor_runner/pte_to_header.py b/examples/arm/executor_runner/pte_to_header.py index 65213bc729e..8656ac5abdf 100644 --- a/examples/arm/executor_runner/pte_to_header.py +++ b/examples/arm/executor_runner/pte_to_header.py @@ -1,6 +1,7 @@ +#!/usr/bin/env python3 # Copyright (c) Meta Platforms, Inc. and affiliates. # All rights reserved. -# Copyright 2023-2025 Arm Limited and/or its affiliates. +# Copyright 2023-2026 Arm Limited and/or its affiliates. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree.