Skip to content

Commit 9540746

Browse files
authored
Provide the ESP-NN delegate and esp_nn:: op library in the ESP-IDF component
The component now vendors the ESP-NN delegate runtime (backends/espressif/espnn_runtime) and the esp_nn:: op library (backends/espressif/ops), depends on espressif/esp-nn (or a project's own components/esp-nn), and carries the delegate's Kconfig options in its menu. The op library is a fourth kernel library for gen_kernels.py, after portable, quantized and Cadence generic. The delegate is linked only when the kernel bundle records a model that uses EspNNBackend, or when the project calls executorch_add_backend(EspNNBackend): a small source defines an anchor that references register_espnn_backend, so -u on that anchor pulls in espnn_backend.cpp and its static registration from a library that is otherwise never linked. Only espnn_backend.h is public. The smoke consumer now embeds any number of models, each with the test case that split_bundled_program.py extracts from its bundled program, and compares every output with the reference on the device. CI runs four images on the emulator. An ESP32-S3 image runs the smoke model on portable kernels, a quantized mul on esp_nn::quantized_mul_int8 and the conv-act-pool-linear ESP-NN delegate program together. An ESP32-C6 image runs the first two and must not contain EspNNBackend. Two more ESP32-S3 images run the delegate alone, one from a bundle with no kernel libraries and one from executorch_add_backend with no bundle. The empty-app size check still passes with esp-nn compiled in. Authored with Claude Code.
1 parent 64553bc commit 9540746

14 files changed

Lines changed: 492 additions & 130 deletions

File tree

‎.ci/scripts/test_espressif_idf_component.sh‎

Lines changed: 121 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
# This source code is licensed under the BSD-style license found in the
66
# LICENSE file in the root directory of this source tree.
77

8-
# Generates the ExecuTorch ESP-IDF component and a kernel bundle for the smoke
9-
# model, builds the idf_component_smoke consumer for ESP32-C6 with that bundle,
10-
# plus the Cadence kernels, and for ESP32-S3 with one the build generates
11-
# itself, and runs the ESP32-S3 build on the emulator. Also checks that stale or
12-
# mismatched bundles fail at configure time, and that an app declaring nothing
13-
# links to the same size as one without the component.
8+
# Generates the ExecuTorch ESP-IDF component and runs the idf_component_smoke
9+
# consumer on the emulator with three models: the portable-kernel smoke model, a
10+
# mul on the esp_nn:: op library and an ESP-NN delegate program. An ESP32-S3
11+
# build runs all three with a kernel bundle the build makes itself; an ESP32-C6
12+
# build runs the first two, with the Cadence kernels too, and must not link the
13+
# delegate; two more ESP32-S3 builds run the delegate alone, from a bundle with
14+
# no kernel libraries and from executorch_add_backend with no bundle. Also
15+
# checks that stale or mismatched bundles fail at configure time, and that an
16+
# app declaring nothing links to the same size as one without the component.
1417

1518
set -euo pipefail
1619

@@ -39,16 +42,38 @@ bash examples/espressif/setup.sh --minimal --targets=esp32s3,esp32c6 2>&1 \
3942
# shellcheck source=/dev/null
4043
source "${ESPRESSIF_TOOLS_DIR}/setup_path.sh"
4144

42-
python examples/espressif/export_smoke_model.py \
43-
--output "${build_dir}/smoke.bpte" --pte-output "${build_dir}/smoke.pte" \
45+
python examples/espressif/export_smoke_model.py --output "${build_dir}/smoke.bpte" \
4446
2>&1 | tee "${build_dir}/export.log"
47+
python examples/espressif/idf_component_smoke/export_op_library_model.py \
48+
--output "${build_dir}/mul.bpte" 2>&1 | tee -a "${build_dir}/export.log"
49+
python examples/espressif/export_espnn_test_programs.py --output-dir "${build_dir}/espnn" \
50+
--only conv-act-pool-linear 2>&1 | tee -a "${build_dir}/export.log"
51+
cp "${build_dir}/espnn/conv-act-pool-linear.bpte" "${build_dir}/delegate.bpte"
52+
split=examples/espressif/idf_component_smoke/split_bundled_program.py
53+
python "${split}" "${build_dir}/smoke.bpte" --atol 0 --rtol 0
54+
# The tolerance test_mul.py uses.
55+
python "${split}" "${build_dir}/mul.bpte" --atol 0 --rtol 1.2e-7
56+
read -r atol rtol < <(python -c '
57+
import json, sys
58+
(entry,) = json.load(open(sys.argv[1]))
59+
print(entry["atol"], entry["rtol"])
60+
' "${build_dir}/espnn/manifest.json")
61+
python "${split}" "${build_dir}/delegate.bpte" --atol "${atol}" --rtol "${rtol}"
62+
cpu_models="${build_dir}/smoke.pte;${build_dir}/mul.pte"
63+
models="${cpu_models};${build_dir}/delegate.pte"
4564

4665
component_dir="${build_dir}/components/executorch"
4766
kernels_dir="${build_dir}/smoke_kernels"
4867
bash examples/espressif/build_idf_component.sh --out "${component_dir}" \
4968
2>&1 | tee "${build_dir}/generate.log"
50-
python "${component_dir}/tools/gen_kernels.py" --pte "${build_dir}/smoke.pte" \
51-
--out "${kernels_dir}" 2>&1 | tee "${build_dir}/gen_kernels.log"
69+
gen_kernels() {
70+
local out=$1
71+
shift
72+
python "${component_dir}/tools/gen_kernels.py" "$@" --out "${out}" \
73+
2>&1 | tee -a "${build_dir}/gen_kernels.log"
74+
}
75+
gen_kernels "${kernels_dir}" --pte "${build_dir}/smoke.pte" --pte "${build_dir}/mul.pte" \
76+
--pte "${build_dir}/delegate.pte"
5277
# The ESP32-C6 build also registers the ops of a Cadence-quantized streaming
5378
# wake word model, so CI compiles and links the Cadence generic kernels.
5479
wakeword_ops=aten::_softmax.out,aten::_to_copy.out,aten::cat.out,aten::copy_
@@ -58,9 +83,17 @@ wakeword_ops+=,cadence::dequantize_per_tensor.out,cadence::quantize_per_tensor.o
5883
wakeword_ops+=,cadence::quantized_conv2d_nhwc.per_tensor_out
5984
wakeword_ops+=,cadence::quantized_fully_connected.per_tensor_out
6085
wakeword_ops+=,cadence::quantized_relu.per_tensor_out
61-
python "${component_dir}/tools/gen_kernels.py" --pte "${build_dir}/smoke.pte" \
62-
--ops "${wakeword_ops}" --out "${build_dir}/wakeword_kernels" \
63-
2>&1 | tee -a "${build_dir}/gen_kernels.log"
86+
gen_kernels "${build_dir}/cpu_kernels" --pte "${build_dir}/smoke.pte" \
87+
--pte "${build_dir}/mul.pte" --ops "${wakeword_ops}"
88+
gen_kernels "${build_dir}/delegate_kernels" --pte "${build_dir}/delegate.pte"
89+
python - "${build_dir}/delegate_kernels/kernels.json" <<'PY'
90+
import json
91+
import sys
92+
93+
libraries = json.load(open(sys.argv[1]))["libraries"]
94+
if libraries:
95+
sys.exit(f"FAIL: the delegate-only bundle has kernel libraries {sorted(libraries)}")
96+
PY
6497

6598
project=examples/espressif/idf_component_smoke
6699

@@ -94,7 +127,8 @@ mkdir -p "${build_dir}/stale"
94127
cp "${build_dir}/smoke.pte" "${build_dir}/stale/smoke.pte"
95128
printf '\0' >> "${build_dir}/stale/smoke.pte"
96129
expect_configure_error stale-model "smoke.pte: changed since the bundle was made" \
97-
-DET_SMOKE_PTE="${build_dir}/stale/smoke.pte" -DET_SMOKE_KERNELS="${kernels_dir}"
130+
-DET_SMOKE_MODELS="${build_dir}/stale/smoke.pte;${build_dir}/mul.pte;${build_dir}/delegate.pte" \
131+
-DET_SMOKE_KERNELS="${kernels_dir}"
98132

99133
rm -rf "${build_dir}/mismatch_kernels"
100134
cp -r "${kernels_dir}" "${build_dir}/mismatch_kernels"
@@ -107,7 +141,7 @@ bundle["component_version"] = "0.0.0"
107141
json.dump(bundle, open(sys.argv[1], "w"))
108142
PY
109143
expect_configure_error version-mismatch component_version \
110-
-DET_SMOKE_PTE="${build_dir}/smoke.pte" \
144+
-DET_SMOKE_MODELS="${models}" \
111145
-DET_SMOKE_KERNELS="${build_dir}/mismatch_kernels"
112146

113147
# A bundle made by a component of the same version from another commit, as two
@@ -123,23 +157,23 @@ bundle["component_commit"] = "0" * 40
123157
json.dump(bundle, open(sys.argv[1], "w"))
124158
PY
125159
expect_configure_error commit-mismatch component_commit \
126-
-DET_SMOKE_PTE="${build_dir}/smoke.pte" \
160+
-DET_SMOKE_MODELS="${models}" \
127161
-DET_SMOKE_KERNELS="${build_dir}/mismatch_kernels"
128162

129163
# Without an ExecuTorch Python to generate one, a missing bundle is an error.
130164
python -m venv --without-pip --clear "${build_dir}/bare_python"
131165
EXECUTORCH_PYTHON="${build_dir}/bare_python/bin/python" expect_configure_error \
132-
no-bundle "cannot import executorch" -DET_SMOKE_PTE="${build_dir}/smoke.pte"
166+
no-bundle "cannot import executorch" -DET_SMOKE_MODELS="${models}"
133167
expect_configure_error relative-python "must be the absolute path" \
134-
-DET_SMOKE_PTE="${build_dir}/smoke.pte" -DEXECUTORCH_PYTHON=python
168+
-DET_SMOKE_MODELS="${models}" -DEXECUTORCH_PYTHON=python
135169

136170
# A kernel registry smaller than the bundle; the emulator run below uses one
137171
# larger than it.
138172
printf 'CONFIG_ET_MAX_KERNEL_NUM=1\n' > "${build_dir}/small_registry.defaults"
139173
printf 'CONFIG_ET_MAX_KERNEL_NUM=64\n' > "${build_dir}/large_registry.defaults"
140174
expect_configure_error small-registry "CONFIG_ET_MAX_KERNEL_NUM=1 is below" \
141175
"-DSDKCONFIG_DEFAULTS=sdkconfig.defaults;${build_dir}/small_registry.defaults" \
142-
-DET_SMOKE_PTE="${build_dir}/smoke.pte" -DET_SMOKE_KERNELS="${kernels_dir}"
176+
-DET_SMOKE_MODELS="${models}" -DET_SMOKE_KERNELS="${kernels_dir}"
143177

144178
# An app that declares nothing must not grow because the component is in the
145179
# build. The baseline swaps the component for an empty one of the same name.
@@ -170,34 +204,80 @@ PY
170204
printf 'CONFIG_LIBC_NEWLIB=y\nCONFIG_LIBC_NEWLIB_NANO_FORMAT=y\n' > "${build_dir}/nano.defaults"
171205
consumer nano esp32s3 -DET_COMPONENT_DIR="${component_dir}" \
172206
"-DSDKCONFIG_DEFAULTS=sdkconfig.defaults;${build_dir}/nano.defaults" \
173-
-DET_SMOKE_PTE="${build_dir}/smoke.pte" -DET_SMOKE_KERNELS="${kernels_dir}" reconfigure
207+
-DET_SMOKE_MODELS="${models}" -DET_SMOKE_KERNELS="${kernels_dir}" reconfigure
174208
if ! tr -s ' \n' ' ' < "${build_dir}/firmware-nano.log" \
175209
| grep -qF "ExecuTorch logging is DISABLED"; then
176210
echo "FAIL: no nano printf warning; see ${build_dir}/firmware-nano.log" >&2
177211
exit 1
178212
fi
179213

180-
consumer smoke-esp32c6 esp32c6 -DET_COMPONENT_DIR="${component_dir}" \
181-
-DET_SMOKE_PTE="${build_dir}/smoke.pte" -DET_SMOKE_KERNELS="${build_dir}/wakeword_kernels" build
214+
# Runs a build on the emulator and checks its output: build name, chip, then
215+
# the per-model markers.
216+
run_firmware() {
217+
local name=$1 chip=$2
218+
shift 2
219+
local firmware_dir="${build_dir}/firmware-${name}"
220+
IDF_TARGET="${chip}" idf.py -C "${project}" -B "${firmware_dir}" merge-bin \
221+
> "${build_dir}/merge-${name}.log" 2>&1
222+
timeout 130s esp-emu --chip "${chip}" \
223+
--firmware "${firmware_dir}/merged-binary.bin" \
224+
--elf "${firmware_dir}/et_component_smoke.elf" \
225+
--net user --timeout 120s --exit-on 'Program complete.' \
226+
2>&1 | tee "${build_dir}/emulator-${name}.log"
227+
for marker in "$@" "ET_COMPONENT_SMOKE: PASS" "Program complete."; do
228+
if ! grep -qF "${marker}" "${build_dir}/emulator-${name}.log"; then
229+
echo "FAIL: ${name} printed no '${marker}'; see emulator-${name}.log" >&2
230+
exit 1
231+
fi
232+
done
233+
echo "OK: ${name} passed on the ${chip} emulator"
234+
}
235+
182236
# No bundle declared: the build makes one with its own Python, which has
183237
# executorch here, and it must match the one gen_kernels.py made above.
184-
consumer smoke-esp32s3 esp32s3 -DET_COMPONENT_DIR="${component_dir}" \
238+
consumer all-esp32s3 esp32s3 -DET_COMPONENT_DIR="${component_dir}" \
185239
"-DSDKCONFIG_DEFAULTS=sdkconfig.defaults;${build_dir}/large_registry.defaults" \
186-
-DET_SMOKE_PTE="${build_dir}/smoke.pte" build
187-
diff -r "${build_dir}/firmware-smoke-esp32s3/executorch_kernels" "${kernels_dir}"
188-
189-
firmware_dir="${build_dir}/firmware-smoke-esp32s3"
190-
idf.py -C "${project}" -B "${firmware_dir}" merge-bin \
191-
2>&1 | tee "${build_dir}/firmware-merge.log"
192-
timeout 130s esp-emu --chip esp32s3 \
193-
--firmware "${firmware_dir}/merged-binary.bin" \
194-
--elf "${firmware_dir}/et_component_smoke.elf" \
195-
--net user --timeout 120s --exit-on 'Program complete.' \
196-
2>&1 | tee "${build_dir}/emulator.log"
197-
for marker in "ET_COMPONENT_SMOKE: PASS" "Program complete."; do
198-
if ! grep -qF "${marker}" "${build_dir}/emulator.log"; then
199-
echo "FAIL: missing '${marker}'; see ${build_dir}/emulator.log" >&2
200-
exit 1
201-
fi
202-
done
203-
echo "PASS: generated ESP-IDF component ran the smoke model on the ESP32-S3 emulator."
240+
-DET_SMOKE_MODELS="${models}" build
241+
diff -r "${build_dir}/firmware-all-esp32s3/executorch_kernels" "${kernels_dir}"
242+
run_firmware all-esp32s3 esp32s3 "smoke: PASS" "mul: PASS" "delegate: PASS"
243+
244+
# A project may provide esp-nn as its own component instead of the managed one.
245+
local_project="${build_dir}/local-esp-nn"
246+
rm -rf "${local_project}"
247+
mkdir -p "${local_project}/components"
248+
cp -r "${project}/CMakeLists.txt" "${project}/main" "${project}/sdkconfig.defaults" \
249+
"${local_project}/"
250+
cp -r "${project}/managed_components/espressif__esp-nn" "${local_project}/components/esp-nn"
251+
project="${local_project}" consumer local-esp-nn esp32s3 -DET_COMPONENT_DIR="${component_dir}" \
252+
-DET_SMOKE_MODELS="${build_dir}/delegate.pte" \
253+
-DET_SMOKE_KERNELS="${build_dir}/delegate_kernels" reconfigure
254+
echo "OK: a project with its own components/esp-nn configures"
255+
256+
consumer cpu-esp32c6 esp32c6 -DET_COMPONENT_DIR="${component_dir}" \
257+
-DET_SMOKE_MODELS="${cpu_models}" -DET_SMOKE_KERNELS="${build_dir}/cpu_kernels" build
258+
# The esp_nn:: op library must not pull in the delegate.
259+
if riscv32-esp-elf-nm -C "${build_dir}/firmware-cpu-esp32c6/et_component_smoke.elf" \
260+
| grep -q EspNNBackend; then
261+
echo "FAIL: cpu-esp32c6 links EspNNBackend, which none of its models uses" >&2
262+
exit 1
263+
fi
264+
run_firmware cpu-esp32c6 esp32c6 "smoke: PASS" "mul: PASS"
265+
266+
consumer delegate-esp32s3 esp32s3 -DET_COMPONENT_DIR="${component_dir}" \
267+
-DET_SMOKE_MODELS="${build_dir}/delegate.pte" \
268+
-DET_SMOKE_KERNELS="${build_dir}/delegate_kernels" build
269+
run_firmware delegate-esp32s3 esp32s3 "delegate: PASS"
270+
271+
# Models not known at build time: only the delegate is declared.
272+
consumer backend-esp32s3 esp32s3 -DET_COMPONENT_DIR="${component_dir}" \
273+
-DET_SMOKE_MODELS="${build_dir}/delegate.pte" -DET_SMOKE_BACKENDS=EspNNBackend build
274+
run_firmware backend-esp32s3 esp32s3 "delegate: PASS"
275+
# Without a bundle nothing registers kernels, so the registry reserves no room.
276+
registry=$(xtensa-esp32s3-elf-nm -S -C "${build_dir}/firmware-backend-esp32s3/et_component_smoke.elf" \
277+
| awk '/registered_kernels_data/ {print $2}')
278+
if (( 16#${registry:-0} > 64 )); then
279+
echo "FAIL: backend-esp32s3 reserves $((16#${registry})) B for kernels it never registers" >&2
280+
exit 1
281+
fi
282+
283+
echo "PASS: generated ESP-IDF component ran every build on the emulator."

‎examples/espressif/README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ component from sources in this repository:
2121

2222
The output is a registry-shaped component (`idf_component.yml`,
2323
`CMakeLists.txt`, `Kconfig`, `VERSION`) containing the runtime, the
24-
portable, quantized and Cadence generic kernel libraries, the shared
24+
portable, quantized, Cadence generic and `esp_nn::` kernel libraries,
25+
the ESP-NN delegate, the shared
2526
ESP-IDF PAL from `platform/esp_pal.cpp` (ESP_LOG + `esp_timer` timing),
2627
and a C inference API (`et_model.h`, flash-XIP model bytes with
2728
internal/PSRAM arena placement). Only the kernels a project's models

‎examples/espressif/build_idf_component.sh‎

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
#
1616
# Derived from examples/arduino/build_arduino_library.sh with an ESP-IDF
1717
# output layout and the shared ESP-IDF PAL. The component vendors every
18-
# kernel source of its kernel libraries (portable, quantized and the
19-
# Cadence backend's generic kernels) but registers none of them: a
18+
# kernel source of its kernel libraries (portable, quantized, the Cadence
19+
# backend's generic kernels and the esp_nn:: op library) and the ESP-NN
20+
# delegate, but registers none of them: a
2021
# project's kernel bundle, made by the component's tools/gen_kernels.py
2122
# from its models, selects the kernels at build time.
2223
#
@@ -204,15 +205,24 @@ copy_srcs() { # ET_ROOT-relative paths on stdin; $1 = list file to append to
204205

205206
: > "$SCRATCH/core_srcs.txt"
206207
: > "$SCRATCH/kernel_srcs.txt"
208+
: > "$SCRATCH/espnn_srcs.txt"
207209
bzl_list EXECUTORCH_CORE_SRCS | copy_srcs "$SCRATCH/core_srcs.txt"
208210
# register_prim_ops.cpp is compiled by the build, with the bundle's prim
209211
# selection, only when a project has a kernel bundle.
210212
bzl_list EXECUTORCH_SRCS | grep -v '/register_prim_ops\.cpp$' \
211213
| copy_srcs "$SCRATCH/kernel_srcs.txt"
212214
echo "kernels/prim_ops/register_prim_ops.cpp" | copy_srcs "$SCRATCH/prim_src.txt"
213215
( cd "$ET_ROOT" && find kernels/portable/cpu kernels/quantized/cpu \
214-
backends/cadence/generic -name '*.cpp' -not -path '*/test*/*' | sort ) \
216+
backends/cadence/generic backends/espressif/ops -name '*.cpp' \
217+
-not -path '*/test*/*' | sort ) \
215218
| copy_srcs "$SCRATCH/kernel_srcs.txt"
219+
# The ESP-NN delegate runtime, an ESP-IDF component of its own in-tree.
220+
ESPNN_RUNTIME="$ET_ROOT/backends/espressif/espnn_runtime"
221+
mkdir -p "$OUT_DIR/src/espnn"
222+
for f in "$ESPNN_RUNTIME"/src/*.cpp; do
223+
cp "$f" "$OUT_DIR/src/espnn/"
224+
echo "src/espnn/$(basename "$f")" >> "$SCRATCH/espnn_srcs.txt"
225+
done
216226

217227
echo "[2/5] Runtime, extension and kernel sources copied"
218228

@@ -271,6 +281,10 @@ cp "$ET_ROOT/kernels/prim_ops/selective_build_prim_ops.h" \
271281
mkdir -p "$OUT_DIR/priv_include"
272282
cp -r "$ET_ROOT/third-party/flatbuffers/include/flatbuffers" \
273283
"$OUT_DIR/priv_include/flatbuffers"
284+
# Only espnn_backend.h is the delegate's API; the rest is internal to it.
285+
cp -r "$ESPNN_RUNTIME/include/espnn" "$OUT_DIR/priv_include/espnn"
286+
mkdir -p "$OUT_DIR/include/espnn"
287+
mv "$OUT_DIR/priv_include/espnn/espnn_backend.h" "$OUT_DIR/include/espnn/"
274288

275289
echo "[3/5] Headers and third-party code copied"
276290

@@ -283,6 +297,7 @@ LIBRARIES=(
283297
"portable kernels/portable/functions.yaml"
284298
"quantized kernels/quantized/quantized.yaml"
285299
"cadence backends/cadence/aot/functions.yaml"
300+
"esp_nn backends/espressif/ops/operators.yaml"
286301
)
287302
mkdir -p "$OUT_DIR/tools/libraries" "$OUT_DIR/tools/codegen"
288303
cp "$TEMPLATE_DIR/tools/gen_kernels.py" "$OUT_DIR/tools/"
@@ -315,7 +330,7 @@ cp "$TEMPLATE_DIR/CMakeLists.txt" "$TEMPLATE_DIR/project_include.cmake" \
315330
"$TEMPLATE_DIR/README.md" "$OUT_DIR/"
316331
cp "$TEMPLATE_DIR/include/et_model.h" "$OUT_DIR/include/"
317332
mkdir -p "$OUT_DIR/src/platform"
318-
cp "$TEMPLATE_DIR/src/et_model.cpp" "$OUT_DIR/src/"
333+
cp "$TEMPLATE_DIR/src/et_model.cpp" "$TEMPLATE_DIR/src/espnn_anchor.cpp" "$OUT_DIR/src/"
319334
cp "$ESP_PAL_SRC" "$OUT_DIR/src/platform/"
320335
cp "$ET_ROOT/LICENSE" "$OUT_DIR/LICENSE"
321336

@@ -349,9 +364,13 @@ NOTICE
349364
sort -u "$SCRATCH/kernel_srcs.txt" | sed 's/.*/ "&"/'
350365
echo ")"
351366
echo "set(ET_PRIM_OPS_SRC \"$(cat "$SCRATCH/prim_src.txt")\")"
367+
echo "set(ET_ESPNN_SRCS"
368+
sed 's/.*/ "&"/' "$SCRATCH/espnn_srcs.txt"
369+
echo ")"
352370
} > "$OUT_DIR/et_generated.cmake"
353371

354-
cat > "$OUT_DIR/Kconfig" <<'KCONFIG'
372+
{
373+
cat <<'KCONFIG'
355374
# GENERATED by examples/espressif/build_idf_component.sh -- do not edit.
356375
menu "ExecuTorch"
357376
@@ -413,8 +432,12 @@ menu "ExecuTorch"
413432
Raise this when the application registers its own kernels.
414433
Must not be below the kernel bundle's kernel count.
415434
416-
endmenu
417435
KCONFIG
436+
# The ESP-NN delegate's options, as a submenu.
437+
sed -n '/^menu /,/^endmenu/p' "$ESPNN_RUNTIME/Kconfig" | sed 's/^./ &/'
438+
echo ""
439+
echo "endmenu"
440+
} > "$OUT_DIR/Kconfig"
418441

419442
sed "s/@ET_COMPONENT_VERSION@/$ET_COMPONENT_VERSION/" \
420443
"$TEMPLATE_DIR/idf_component.yml.in" > "$OUT_DIR/idf_component.yml"

‎examples/espressif/idf_component_smoke/CMakeLists.txt‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66

77
# Minimal ESP-IDF consumer of the generated ExecuTorch component, used by
88
# .ci/scripts/test_espressif_idf_component.sh. Pass the generated component
9-
# directory as ET_COMPONENT_DIR, the plain smoke .pte from export_smoke_model.py
10-
# as ET_SMOKE_PTE, and optionally its kernel bundle from the component's
11-
# tools/gen_kernels.py as ET_SMOKE_KERNELS; without one the build makes it.
12-
# Without ET_SMOKE_PTE it builds an app that does not use ExecuTorch, for size
13-
# comparisons.
9+
# directory as ET_COMPONENT_DIR and the .pte files that split_bundled_program.py
10+
# made as the ET_SMOKE_MODELS list; each runs on its bundled test case. Pass a
11+
# kernel bundle from the component's tools/gen_kernels.py as ET_SMOKE_KERNELS,
12+
# or leave it out to have the build make one. With ET_SMOKE_BACKENDS, the models
13+
# are embedded but not declared and only those delegates are, as for models
14+
# delivered over the air. Without ET_SMOKE_MODELS it builds an app that does not
15+
# use ExecuTorch, for size comparisons.
1416

1517
cmake_minimum_required(VERSION 3.16)
1618

0 commit comments

Comments
 (0)