diff --git a/CMakeLists.txt b/CMakeLists.txt index b299d14a27f..ce4ee1a737c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1222,17 +1222,16 @@ if(EXECUTORCH_BUILD_EXECUTOR_RUNNER) if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") target_link_options_gc_sections(executor_runner) endif() - target_link_libraries(executor_runner ${_executor_runner_libs}) + target_link_libraries(executor_runner PRIVATE ${_executor_runner_libs}) target_compile_options(executor_runner PUBLIC ${_common_compile_options}) if(EXECUTORCH_BUILD_ARM_ETHOSU_LINUX) - target_sources( - executor_runner - PRIVATE - ${CMAKE_SOURCE_DIR}/examples/arm/executor_runner/ethosu_link_helper.cpp - ) target_compile_definitions( executor_runner PRIVATE EXECUTORCH_BUILD_ARM_ETHOSU_LINUX=1 ) + target_link_libraries( + executor_runner + PRIVATE $ + ) # Wrap static linking like the delegate_runner to keep images # self-contained. target_link_options( diff --git a/backends/arm/runtime/EthosUBackend.cpp b/backends/arm/runtime/EthosUBackend.cpp index 642cc063f26..d83b04f0e8e 100644 --- a/backends/arm/runtime/EthosUBackend.cpp +++ b/backends/arm/runtime/EthosUBackend.cpp @@ -412,22 +412,11 @@ Backend EthosUBackend_id{"EthosUBackend", &EthosUBackend_backend}; static executorch::runtime::Error EthosUBackend_registered = register_backend(EthosUBackend_id); -/** - * This function serves as a linker force-include mechanism to ensure the - * EthosU backend module gets properly linked into the final executable, - * even when it might otherwise be optimized out by the linker due to - * linker options that remove unused code or data for example - * if you link with --gc-sections - * This function can be called from your runner to force the inclusion of - * the EthosU backend module. As a bonus it will return the status of the - * backend registration, so you can also check if the registration was - * successful. - */ - -// Warning: This should not be considered to be an API and might get removed -// without notice in a future release if a better way to solve this is -// implemented. -extern "C" executorch::runtime::Error +// DEPRECATED in Executorch 1.2 +// Remove it from your code and make sure to add this to your CMAKE rules +// instead: +// executorch_target_link_options_shared_lib(executorch_delegate_ethos_u) +extern "C" ET_DEPRECATED executorch::runtime::Error executorch_delegate_EthosUBackend_registered() { return EthosUBackend_registered; } diff --git a/examples/arm/executor_runner/CMakeLists.txt b/examples/arm/executor_runner/CMakeLists.txt index 01da4b2045f..c169f5d447a 100644 --- a/examples/arm/executor_runner/CMakeLists.txt +++ b/examples/arm/executor_runner/CMakeLists.txt @@ -77,6 +77,7 @@ set(ET_DIR_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../.." CACHE PATH "Path to ExecuTorch dir" ) +include(${ET_DIR_PATH}/tools/cmake/Utils.cmake) set(ET_BUILD_DIR_PATH "${ET_DIR_PATH}/cmake-out-arm" CACHE PATH "Path to ExecuTorch build/install dir" @@ -223,6 +224,12 @@ execute_process( ) target_link_options(arm_executor_runner PRIVATE "-T" "${LINK_FILE_OUT}") +# Apply whole-archive helper where available to keep static initializers. +executorch_target_link_options_shared_lib(executorch_delegate_ethos_u) +executorch_target_link_options_shared_lib(quantized_kernels) +executorch_target_link_options_shared_lib(cortex_m_kernels) +executorch_target_link_options_shared_lib(portable_kernels) + set(arm_executor_runner_link) list( APPEND @@ -232,12 +239,10 @@ list( executorch quantized_ops_lib cortex_m_ops_lib - "-Wl,--whole-archive" executorch_delegate_ethos_u quantized_kernels cortex_m_kernels portable_kernels - "-Wl,--no-whole-archive" -Xlinker -Map=arm_executor_runner.map ) diff --git a/examples/arm/executor_runner/ethosu_link_helper.cpp b/examples/arm/executor_runner/ethosu_link_helper.cpp deleted file mode 100644 index 3130dfbd78b..00000000000 --- a/examples/arm/executor_runner/ethosu_link_helper.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 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. - */ - -// Helper to force-link the Ethos-U backend when building the portable runner. - -#if defined(EXECUTORCH_BUILD_ARM_ETHOSU_LINUX) -#include - -extern "C" ::executorch::runtime::Error -executorch_delegate_EthosUBackend_registered(); - -namespace { -struct EthosULinkHook { - EthosULinkHook() { - // Force linker to keep the Ethos-U backend object file. - (void)executorch_delegate_EthosUBackend_registered(); - } -}; - -static EthosULinkHook g_link_hook; -} // namespace -#endif // EXECUTORCH_BUILD_ARM_ETHOSU_LINUX diff --git a/examples/arm/image_classification_example/runtime/CMakeLists.txt b/examples/arm/image_classification_example/runtime/CMakeLists.txt index 60bfd896a4b..9d9f0645bd5 100644 --- a/examples/arm/image_classification_example/runtime/CMakeLists.txt +++ b/examples/arm/image_classification_example/runtime/CMakeLists.txt @@ -95,11 +95,11 @@ target_link_libraries( cortex_m_ops_lib ) -# We need to include whole archive for the EthosUBackend -target_link_libraries( - img_class_example PUBLIC "-Wl,--whole-archive" executorch_delegate_ethos_u - "-Wl,--no-whole-archive" -) +# Apply whole-archive helper where available to keep static initializers. +include(${ET_DIR_PATH}/tools/cmake/Utils.cmake) +executorch_target_link_options_shared_lib(executorch_delegate_ethos_u) + +target_link_libraries(img_class_example PUBLIC executorch_delegate_ethos_u) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(LINK_FILE_EXT ld) diff --git a/examples/arm/zephyr/CMakeLists.txt b/examples/arm/zephyr/CMakeLists.txt index 9d0f7e53f60..ca266ead811 100644 --- a/examples/arm/zephyr/CMakeLists.txt +++ b/examples/arm/zephyr/CMakeLists.txt @@ -124,6 +124,7 @@ endif() # Set EXECUTORCH_ROOT for the Codegen.cmake file set(EXECUTORCH_ROOT ${EXECUTORCH_DIR}) +include(${EXECUTORCH_DIR}/tools/cmake/Utils.cmake) # Ensure the portable kernels target exists even when portable ops are disabled # in the global build. @@ -137,7 +138,6 @@ if(NOT TARGET portable_kernels) endif() set(EXECUTORCH_OPS_LIB "") if(_EXECUTORCH_GEN_ZEPHYR_PORTABLE_OPS) - include(${EXECUTORCH_DIR}/tools/cmake/Utils.cmake) include(${EXECUTORCH_DIR}/tools/cmake/Codegen.cmake) if(NOT DEFINED EXECUTORCH_ENABLE_DTYPE_SELECTIVE_BUILD) set(EXECUTORCH_ENABLE_DTYPE_SELECTIVE_BUILD "") @@ -237,10 +237,20 @@ if(CONFIG_CPU_CORTEX_M) target_link_libraries(app PRIVATE cortex_m_ops_lib) endif() if(TARGET cortex_m_kernels) + executorch_target_link_options_shared_lib(cortex_m_kernels) target_link_libraries(app PRIVATE cortex_m_kernels) endif() endif() +if(TARGET quantized_kernels) + executorch_target_link_options_shared_lib(quantized_kernels) + target_link_libraries(app PRIVATE quantized_kernels) +endif() +if(TARGET portable_kernels) + executorch_target_link_options_shared_lib(portable_kernels) + target_link_libraries(app PRIVATE portable_kernels) +endif() if(TARGET executorch_delegate_ethos_u) + executorch_target_link_options_shared_lib(executorch_delegate_ethos_u) target_link_libraries(app PRIVATE executorch_delegate_ethos_u) endif() if(TARGET ethosu_core_driver) diff --git a/examples/arm/zephyr/src/arm_executor_runner.cpp b/examples/arm/zephyr/src/arm_executor_runner.cpp index 1d45d9a953b..029a568c427 100644 --- a/examples/arm/zephyr/src/arm_executor_runner.cpp +++ b/examples/arm/zephyr/src/arm_executor_runner.cpp @@ -58,11 +58,6 @@ using executorch::runtime::Span; using executorch::runtime::Tag; using executorch::runtime::TensorInfo; -#if defined(CONFIG_ETHOS_U) -extern "C" executorch::runtime::Error -executorch_delegate_EthosUBackend_registered(void); -#endif - /** * The method_allocation_pool should be large enough to fit the setup, input * used and other data used like the planned memory pool (e.g. memory-planned @@ -214,14 +209,6 @@ int main(int argc, const char* argv[]) { (void)argc; (void)argv; -#if defined(CONFIG_ETHOS_U) - if (executorch_delegate_EthosUBackend_registered() != Error::Ok) { - ET_LOG( - Error, - "Ethos-U backend registration failed; model execution cannot continue"); - return 1; - } -#endif executorch::runtime::runtime_init(); std::vector> input_buffers; size_t pte_size = sizeof(model_pte);