Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -738,9 +738,6 @@ endif()

if(EXECUTORCH_BUILD_PYBIND)

# Add codegen tools subdirectory for selective_build pybind module
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/codegen/tools)

if(NOT EXECUTORCH_BUILD_EXTENSION_DATA_LOADER)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/extension/data_loader)
endif()
Expand All @@ -749,6 +746,9 @@ if(EXECUTORCH_BUILD_PYBIND)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/devtools)
endif()

# Add codegen tools subdirectory for selective_build pybind module
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/codegen/tools)

# Create bundled_module target only for pybindings when bundled_program exists
# This target has hard dependencies on devtools generated headers
if(TARGET bundled_program)
Expand Down
5 changes: 5 additions & 0 deletions codegen/tools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
# Copyright 2025 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.
Expand Down Expand Up @@ -28,6 +29,10 @@ target_compile_options(
)

# Link against required libraries
if(TARGET bundled_program)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you check EXECUTORCH_BUILD_DEVTOOLS?

Something like

if (EXECUTORCH_BUILD_DEVTOOLS and TARGET bundled_program)
   ... 

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with this since it is done that way on L754 in top-level CMakeLists.txt. Is there a benefit in additionally checking the flag or just to be on the safe side?

target_compile_definitions(selective_build PRIVATE -DET_BUNDLE_IO)
target_link_libraries(selective_build PRIVATE bundled_program)
Comment on lines +42 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also wanna change the targets.bzl file too

I added a CI to build buck target for selective_build

#14499

For future reference, here's how you can download buck:

python tools/cmake/resolve_buck.py --cache_dir==/tmp/
# it will download and output a buck executable file within /tmp/ file

Once you have the buck file, you can do something like this:

/tmp/buck2 build //codegen/tools/... 
# build all targets within //codegen/tools/...
/tmp/buck2 build codegen/tools:selective_build
# build all targets

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a look and the bundled_program seems to have multiple targets runtime and runtime_aten, depending on some get_aten_mode_options(). I need some assistance to figure this out. From what I can tell, if I add the different targets to selective_build that target is also split which means that targets depending on it will also split and so on... That doesn't sound right.

Copy link
Contributor

@mergennachin mergennachin Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Erik-Lundell -- no need to bifurcate on aten vs not. You can add dependency on "//executorch/devtools/bundled_program:runtime

Historically, runtime_aten is mainly for internal customers when portable ops coverage was low. That's not the case, so you should be able to just depend on "//executorch/devtools/bundled_program:runtime directly

endif()
target_link_libraries(selective_build PRIVATE executorch_core program_schema)

# Install the module
Expand Down
42 changes: 39 additions & 3 deletions codegen/tools/selective_build.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
* Copyright 2025 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.
*/

#include <executorch/runtime/platform/assert.h>
#include <executorch/schema/program_generated.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <executorch/runtime/platform/assert.h>
#include <executorch/schema/program_generated.h>
#ifdef ET_BUNDLE_IO
#include <executorch/devtools/bundled_program/bundled_program.h>
#include <stdexcept>
#endif

namespace py = pybind11;

Expand Down Expand Up @@ -186,8 +191,39 @@ get_kernel_tensor_metadatas_from_execution_plan(

const executorch_flatbuffer::Program* _get_program_from_buffer(
const py::bytes& buffer) {
// Access the Python bytes without copying and get raw pointer/size.
const std::string_view sv = buffer.cast<std::string_view>();
#ifdef ET_BUNDLE_IO
void* buf_ptr = const_cast<void*>(static_cast<const void*>(sv.data()));
const size_t buf_len = sv.size();

// If this is a bundled program, extract the inner ExecuTorch program bytes.
if (executorch::bundled_program::is_bundled_program(buf_ptr, buf_len)) {
const void* program_data = nullptr;
size_t program_size = 0;

const auto status = executorch::bundled_program::get_program_data(
buf_ptr, // serialized BundledProgram start
buf_len, // total size of the BundledProgram blob
&program_data, // [out] pointer to inner .pte bytes
&program_size // [out] size of inner .pte bytes
);

if (status != ::executorch::runtime::Error::Ok || program_data == nullptr ||
program_size == 0) {
throw std::runtime_error(
"bundled_program::get_program_data() failed or returned empty data");
}

// program_data points directly at the flatbuffer-encoded Program region.
return executorch_flatbuffer::GetProgram(
reinterpret_cast<const uint8_t*>(program_data));
}
#endif
// Otherwise treat the buffer as a raw .pte (flatbuffer Program with optional
// extended header).
return executorch_flatbuffer::GetProgram(
buffer.cast<std::string_view>().data());
reinterpret_cast<const uint8_t*>(sv.data()));
}

py::list _get_program_operators(const executorch_flatbuffer::Program* program) {
Expand Down
3 changes: 1 addition & 2 deletions docs/source/backends-arm-ethos-u.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,7 @@ You can see how this coupling between the memory mode and runtime application i

The arm_executor_runner supports [bundled-io](https://docs.pytorch.org/executorch/0.4/bundled-io.html) and [ETdump](https://docs.pytorch.org/executorch/stable/etdump.html) debugging tools.

To enable bundled-io, set `EXECUTORCH_BUILD_DEVTOOLS` when building Executorch and `DET_BUNDLE_IO` when building the executor_runner. Currently using bundled-io requires specifying your
non delegated Aten ops manually by setting `EXECUTORCH_SELECT_OPS_LIST`. To enable ETdump, set `EXECUTORCH_BUILD_ARM_ETDUMP` when building Executorch and `DEXECUTORCH_ENABLE_EVENT_TRACER`
To enable bundled-io, set `EXECUTORCH_BUILD_DEVTOOLS` when building Executorch and `DET_BUNDLE_IO` when building the executor_runner. To enable ETdump, set `EXECUTORCH_BUILD_ARM_ETDUMP` when building Executorch and `DEXECUTORCH_ENABLE_EVENT_TRACER`
when building the executor_runner.


Expand Down
13 changes: 4 additions & 9 deletions examples/arm/executor_runner/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,10 @@ list(
-Map=arm_executor_runner.map
)

# Prefer to generate kernel bindings from model file if possible, which is when
# 1. Not building for semihosting 2. Not building with bundleio If that is not
# the case, fallback to select_ops_list If the model file does not contain any
# aten ops, a workaround is currently needed to avoid crashing.
# Figure out which ops to include: For semihosting build, use
# (user-set)SELECT_OPS_MODEL variable. For normal build, use
# EXECUTORCH_SELECT_OPS_MODEL to include ops automatically. If the pte contains
# no undelegated ops, use neither.
execute_process(
COMMAND
python "${ET_DIR_PATH}/codegen/tools/gen_oplist.py"
Expand All @@ -264,11 +264,6 @@ elseif(${FOUND_OPS_IN_FILE})
message(
"gen_oplist: EXECUTORCH_SELECT_OPS_MODEL=${ET_PTE_FILE_PATH} is used to auto generate ops from"
)
elseif(NOT ${FOUND_OPS_IN_FILE} AND ${ET_BUNDLE_IO})
set(EXECUTORCH_SELECT_OPS_MODEL "")
message(
"gen_oplist: Building with ET_BUNDLE_IO and .bpte is not supported to auto generate ops from will use EXECUTORCH_SELECT_OPS_LIST=${EXECUTORCH_SELECT_OPS_LIST}"
)
else()
set(EXECUTORCH_SELECT_OPS_LIST "")
set(EXECUTORCH_SELECT_OPS_MODEL "")
Expand Down
4 changes: 2 additions & 2 deletions examples/arm/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ function help() {
echo " --no_delegate Do not delegate the model (can't override builtin models)"
echo " --no_quantize Do not quantize the model (can't override builtin models)"
echo " --portable_kernels=<OPS> TO BE DEPRECATED: Alias to select_ops_list."
echo " --select_ops_list=<OPS> Comma separated list of portable (non delegated) kernels to include Default: ${select_ops_list}"
echo " NOTE: This is used when select_ops_model is not possible to use, e.g. for semihosting or bundleio."
echo " --select_ops_list=<OPS> Comma separated list of portable (non delagated) kernels to include Default: ${select_ops_list}"
echo " NOTE: This is only used when building for semihosting."
echo " See https://docs.pytorch.org/executorch/stable/kernel-library-selective-build.html for more information."
echo " --target=<TARGET> Target to build and run for Default: ${target}"
echo " --output=<FOLDER> Target build output folder Default: ${output_folder}"
Expand Down
Loading