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
65 changes: 65 additions & 0 deletions extension/android/check_exported_symbols.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

# Verifies that the Android JNI shared library exports the curated
# EXECUTORCH_1_0 ABI defined in extension/android/jni/version_script.txt.
#
# External backend/kernel .so files rely on these symbols being visible in the
# core .so so that ELF symbol interposition gives them access to the
# process-wide backend/kernel registries at load time. If any of these symbols
# go missing (e.g. the version script is accidentally narrowed or stops being
# applied), split backends would silently register into a private registry and
# delegation would fail with "backend not found" at runtime. Fail the build
# instead.
#
# Usage: check_exported_symbols.sh <path-to-libexecutorch.so> [path-to-llvm-nm]

set -euo pipefail

SO_PATH="${1:?usage: check_exported_symbols.sh <libexecutorch.so> [llvm-nm]}"
NM="${2:-llvm-nm}"

# Demangled symbol fragments that must be exported by the core .so.
REQUIRED_SYMBOLS=(
# Backend registration (runtime/backend/interface.h)
"executorch::runtime::register_backend"
"executorch::runtime::get_backend_class"
# BackendInterface RTTI/vtable; external backends subclass it and the key
# function (the destructor) is emitted in the core .so.
"typeinfo for executorch::runtime::BackendInterface"
"vtable for executorch::runtime::BackendInterface"
# Kernel registration (runtime/kernel/operator_registry.h)
"executorch::runtime::register_kernels"
# exec_aten data model used by backend implementations (the portable Tensor
# is executorch::runtime::etensor::Tensor; executorch::aten::Tensor is a
# using-alias, so symbols carry the real namespace).
"executorch::runtime::etensor::Tensor"
"executorch::runtime::EValue"
# PAL hooks so backend .so files share process-wide logging
"et_pal_emit_log_message"
# JNI entry points (pre-existing export contract)
"JNI_OnLoad"
)

EXPORTED="$("${NM}" -D --defined-only -C "${SO_PATH}")"

missing=0
for sym in "${REQUIRED_SYMBOLS[@]}"; do
if ! grep -qF -- "${sym}" <<<"${EXPORTED}"; then
echo "ERROR: ${SO_PATH} does not export required ABI symbol: ${sym}" >&2
missing=1
fi
done

if [[ "${missing}" -ne 0 ]]; then
echo "The EXECUTORCH_1_0 ABI surface is incomplete." >&2
echo "See extension/android/jni/version_script.txt and" >&2
echo "https://github.com/pytorch/executorch/issues/10457 (milestone 1)." >&2
exit 1
fi

echo "OK: ${SO_PATH} exports the EXECUTORCH_1_0 ABI surface."
46 changes: 45 additions & 1 deletion extension/android/jni/version_script.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,51 @@
{
# Export map for the Android JNI shared library (libexecutorch_jni.so,
# repackaged as libexecutorch.so in the AAR).
#
# In addition to the JNI entry points, the EXECUTORCH_1_0 node exports the
# curated C++ runtime API surface that an external backend or kernel .so needs
# in order to self-register into this process's registries when it is loaded.
# This is milestone 1 of the hot-pluggable backends plan:
# https://github.com/pytorch/executorch/issues/10457
#
# The export boundary is namespace-scoped rather than symbol-by-symbol so that
# it stays maintainable as the public headers evolve:
# - executorch::runtime::* registration entry points (register_backend,
# get_backend_class, register_kernels), BackendInterface, EValue,
# MemoryManager / MemoryAllocator, FreeableBuffer, logging, and the rest of
# the public runtime API declared under runtime/.
# - executorch::aten::* the exec_aten data model (Tensor, EValue,
# Scalar, ...) that backend implementations are written against in
# portable (non-ATen) builds.
# - et_pal_* the platform abstraction layer C API, so backend
# .so files share the process-wide logging / allocation / time hooks.
#
# Everything else — runtime internals outside the public namespaces, backend
# implementation details, and kernel implementations — stays hidden, which
# preserves the linker's ability to strip and optimize them.
#
# Additive changes must go into a new version node (e.g. EXECUTORCH_1_1) so
# that external .so files can depend on a stable ABI tag. Never remove or
# narrow symbols from an existing node.
EXECUTORCH_1_0 {
global:
# JNI entry points.
JNI_OnLoad;
Java_*;

# Platform abstraction layer (extern "C" API).
et_pal_*;

extern "C++" {
"executorch::runtime::*";
"executorch::aten::*";
# RTTI and vtables for polymorphic public types (e.g. BackendInterface)
# whose key functions are emitted in this library; external .so files
# subclass these and need the symbols at link/load time.
"typeinfo for executorch::runtime::*";
"typeinfo for executorch::aten::*";
"vtable for executorch::runtime::*";
"vtable for executorch::aten::*";
};
local:
*;
};
6 changes: 6 additions & 0 deletions scripts/build_android_library.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ build_android_native_library() {
mkdir -p ${SO_STAGE_DIR}
cp "${CMAKE_OUT}"/extension/android/*.so "${SO_STAGE_DIR}/libexecutorch.so"

# Verify the curated EXECUTORCH_1_0 ABI surface is exported (milestone 1 of
# https://github.com/pytorch/executorch/issues/10457). Backend .so files
# loaded alongside the core .so depend on these symbols for self-registration.
NM_BIN=$(echo "${ANDROID_NDK}"/toolchains/llvm/prebuilt/*/bin/llvm-nm)
bash extension/android/check_exported_symbols.sh "${SO_STAGE_DIR}/libexecutorch.so" "${NM_BIN}"

# Copy QNN related so library
if [ -n "$QNN_SDK_ROOT" ] && [ "$ANDROID_ABI" == "arm64-v8a" ]; then
cp "${CMAKE_OUT}"/lib/executorch/backends/qualcomm/libqnn_executorch_backend.so ${SO_STAGE_DIR}
Expand Down
Loading