Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
24 changes: 16 additions & 8 deletions .ci/scripts/test_espressif_idf_component.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
# LICENSE file in the root directory of this source tree.

# Generates the ExecuTorch ESP-IDF component and a kernel bundle for the smoke
# model, builds the idf_component_smoke consumer for ESP32-S3 and, with the
# Cadence kernels too, for ESP32-C6, and runs the ESP32-S3 build on the
# emulator. Also checks that stale or mismatched bundles fail at configure time,
# and that an app declaring nothing links to the same size as one without the
# component.
# model, builds the idf_component_smoke consumer for ESP32-C6 with that bundle,
# plus the Cadence kernels, and for ESP32-S3 with one the build generates
# itself, and runs the ESP32-S3 build on the emulator. Also checks that stale or
# mismatched bundles fail at configure time, and that an app declaring nothing
# links to the same size as one without the component.

set -euo pipefail

Expand Down Expand Up @@ -126,7 +126,12 @@ expect_configure_error commit-mismatch component_commit \
-DET_SMOKE_PTE="${build_dir}/smoke.pte" \
-DET_SMOKE_KERNELS="${build_dir}/mismatch_kernels"

expect_configure_error no-bundle "no kernel bundle is" -DET_SMOKE_PTE="${build_dir}/smoke.pte"
# Without an ExecuTorch Python to generate one, a missing bundle is an error.
python -m venv --without-pip --clear "${build_dir}/bare_python"
EXECUTORCH_PYTHON="${build_dir}/bare_python/bin/python" expect_configure_error \
no-bundle "cannot import executorch" -DET_SMOKE_PTE="${build_dir}/smoke.pte"
expect_configure_error relative-python "must be the absolute path" \
-DET_SMOKE_PTE="${build_dir}/smoke.pte" -DEXECUTORCH_PYTHON=python

# A model the bundle was not made from, declared instead of the one it was.
mkdir -p "${build_dir}/other"
Expand Down Expand Up @@ -211,11 +216,14 @@ if ! tr -s ' \n' ' ' < "${build_dir}/firmware-nano.log" \
exit 1
fi

consumer smoke-esp32s3 esp32s3 -DET_COMPONENT_DIR="${component_dir}" \
-DET_SMOKE_PTE="${build_dir}/smoke.pte" -DET_SMOKE_KERNELS="${kernels_dir}" build
consumer smoke-esp32c6 esp32c6 -DET_COMPONENT_DIR="${component_dir}" \
"-DSDKCONFIG_DEFAULTS=sdkconfig.defaults;${build_dir}/large_registry.defaults" \
-DET_SMOKE_PTE="${build_dir}/smoke.pte" -DET_SMOKE_KERNELS="${build_dir}/wakeword_kernels" build
# No bundle declared: the build makes one with its own Python, which has
# executorch here, and it must match the one gen_kernels.py made above.
consumer smoke-esp32s3 esp32s3 -DET_COMPONENT_DIR="${component_dir}" \
-DET_SMOKE_PTE="${build_dir}/smoke.pte" build
diff -r "${build_dir}/firmware-smoke-esp32s3/executorch_kernels" "${kernels_dir}"

firmware_dir="${build_dir}/firmware-smoke-esp32s3"
idf.py -C "${project}" -B "${firmware_dir}" merge-bin \
Expand Down
8 changes: 4 additions & 4 deletions examples/espressif/idf_component_smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
# Minimal ESP-IDF consumer of the generated ExecuTorch component, used by
# .ci/scripts/test_espressif_idf_component.sh. Pass the generated component
# directory as ET_COMPONENT_DIR, the plain smoke .pte from export_smoke_model.py
# as ET_SMOKE_PTE, and its kernel bundle from the component's
# tools/gen_kernels.py as ET_SMOKE_KERNELS. ET_SMOKE_UNDECLARED runs the model
# without declaring it. Without ET_SMOKE_PTE it builds an app that does not use
# ExecuTorch, for size comparisons.
# as ET_SMOKE_PTE, and optionally its kernel bundle from the component's
# tools/gen_kernels.py as ET_SMOKE_KERNELS; without one the build makes it.
# ET_SMOKE_UNDECLARED runs the model without declaring it. Without ET_SMOKE_PTE
# it builds an app that does not use ExecuTorch, for size comparisons.

cmake_minimum_required(VERSION 3.16)

Expand Down
8 changes: 8 additions & 0 deletions examples/espressif/idf_component_template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ executorch_add_model(PTE "${CMAKE_CURRENT_SOURCE_DIR}/model.pte")
executorch_add_kernels(DIR "${CMAKE_CURRENT_SOURCE_DIR}/et_kernels")
```

If the Python ESP-IDF builds with can import `executorch` (or you
point `EXECUTORCH_PYTHON` at one that can, with `-D` or in the
environment, for example
`idf.py -DEXECUTORCH_PYTHON=$HOME/venvs/et/bin/python build`), you can
leave out `executorch_add_kernels`: the build then makes the bundle in
its build directory from the declared models, with the same result as
running `gen_kernels.py` yourself.

The build fails at configure time if the bundle doesn't match the
declared models (a model was re-exported, added or removed) or was
made for another version of this component, and prints the
Expand Down
64 changes: 58 additions & 6 deletions examples/espressif/idf_component_template/project_include.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
# executorch_add_model(PTE <path.pte> [PTE ...]) # models this firmware runs
# executorch_add_kernels(DIR <bundle-dir>) # from tools/gen_kernels.py
#
# Calls are unioned across the project; a project has one kernel bundle.
# Calls are unioned across the project; a project has one kernel bundle. With
# models but no bundle, the build makes one if EXECUTORCH_PYTHON (-D or the
# environment; default: the build's Python) can import executorch.

function(executorch_add_model)
cmake_parse_arguments(_arg "" "" "PTE" ${ARGN})
Expand Down Expand Up @@ -71,20 +73,70 @@ function(__executorch_finalize)
list(REMOVE_DUPLICATES _models)
set(_command "python \"${_dir}/tools/gen_kernels.py\"")
set(_pte_args "")
set(_gen_args "")
foreach(_pte IN LISTS _models)
if(NOT EXISTS "${_pte}")
message(FATAL_ERROR "ExecuTorch: declared model ${_pte} does not exist")
endif()
string(APPEND _pte_args " --pte \"${_pte}\"")
list(APPEND _gen_args --pte "${_pte}")
endforeach()
if(NOT _bundle)
if(NOT EXECUTORCH_PYTHON)
set(EXECUTORCH_PYTHON "$ENV{EXECUTORCH_PYTHON}")
endif()
if(NOT EXECUTORCH_PYTHON)
idf_build_get_property(EXECUTORCH_PYTHON PYTHON)
elseif(NOT IS_ABSOLUTE "${EXECUTORCH_PYTHON}" OR NOT EXISTS
"${EXECUTORCH_PYTHON}"
)
message(
FATAL_ERROR
"ExecuTorch: EXECUTORCH_PYTHON must be the absolute path of a "
"python, not ${EXECUTORCH_PYTHON}"
)
endif()
string(
CONCAT
_manual
"Make the bundle with the Python environment the models were exported "
"with:\n ${_command}${_pte_args} --out <bundle-dir>\nthen call "
"executorch_add_kernels(DIR <bundle-dir>), or set EXECUTORCH_PYTHON to "
"that environment's python."
)
execute_process(
COMMAND "${EXECUTORCH_PYTHON}" -c
"import executorch.codegen.tools.selective_build"
RESULT_VARIABLE _no_executorch
OUTPUT_QUIET
ERROR_VARIABLE _probe_error
)
if(_no_executorch)
message(
FATAL_ERROR
"ExecuTorch: models are declared but no kernel bundle is, and "
"${EXECUTORCH_PYTHON} cannot import executorch to make one:\n"
"${_probe_error}${_manual}"
)
endif()
set(_bundle "${CMAKE_BINARY_DIR}/executorch_kernels")
message(
FATAL_ERROR
"ExecuTorch: models are declared but no kernel bundle is. Make one "
"with the Python environment the models were exported with:\n"
" ${_command}${_pte_args} --out <bundle-dir>\n"
"then call executorch_add_kernels(DIR <bundle-dir>)."
STATUS "ExecuTorch: making the kernel bundle with ${EXECUTORCH_PYTHON}"
)
execute_process(
COMMAND "${EXECUTORCH_PYTHON}" "${_dir}/tools/gen_kernels.py" ${_gen_args}
--out "${_bundle}"
RESULT_VARIABLE _failed
OUTPUT_VARIABLE _output
ERROR_VARIABLE _output
)
if(_failed)
message(
FATAL_ERROR
"ExecuTorch: ${EXECUTORCH_PYTHON} failed to make the kernel bundle:\n"
"${_output}${_manual}"
)
endif()
endif()

set(_manifest "${_bundle}/kernels.json")
Expand Down
Loading