Skip to content

Commit 9f86cf0

Browse files
authored
JavaScript bindings for module API (#12571)
### Summary The next step for building Executorch for the web is to write JavaScript bindings for the API. Added bindidngs that would allow for loading modules and executing methods in JavaScript, along with a few functions to create tensors and read its data. ### Test plan Assuming you already have Emscripten and Node.js version >= 17, you also need Jest as the testing framework. That can be installed with `npm install --save-dev jest` To build and run the tests, run the commands ``` # Build the library and unit tests bash extension/wasm/build_wasm.sh # Navigate to the testing output directory cd cmake-out-wasm/extension/wasm/test/ # Run unit tests npm test ``` Added CI for unit tests.
1 parent 0c8879e commit 9f86cf0

File tree

9 files changed

+1253
-0
lines changed

9 files changed

+1253
-0
lines changed

.ci/scripts/setup-emscripten.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77

88
set -ex
99

10+
# need version >= 17
11+
install_node() {
12+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
13+
source "$HOME/.nvm/nvm.sh"
14+
nvm install 22
15+
}
16+
1017
install_emscripten() {
1118
git clone https://github.com/emscripten-core/emsdk.git
1219
pushd emsdk || return
@@ -16,4 +23,5 @@ install_emscripten() {
1623
popd || return
1724
}
1825

26+
install_node
1927
install_emscripten

.github/workflows/pull.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,41 @@ jobs:
764764
# Test selective build
765765
PYTHON_EXECUTABLE=python bash examples/wasm/test_build_wasm.sh
766766
767+
unittest-wasm-bindings:
768+
name: unittest-wasm-bindings
769+
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
770+
permissions:
771+
id-token: write
772+
contents: read
773+
strategy:
774+
fail-fast: false
775+
with:
776+
runner: linux.2xlarge
777+
docker-image: ci-image:executorch-ubuntu-22.04-clang12
778+
submodules: 'recursive'
779+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
780+
timeout: 90
781+
script: |
782+
# The generic Linux job chooses to use base env, not the one setup by the image
783+
CONDA_ENV=$(conda env list --json | jq -r ".envs | .[-1]")
784+
conda activate "${CONDA_ENV}"
785+
786+
BUILD_TOOL="cmake"
787+
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-linux.sh --build-tool "${BUILD_TOOL}"
788+
789+
# Install Node.js and Emscripten
790+
source .ci/scripts/setup-emscripten.sh
791+
792+
# Test selective build
793+
bash scripts/build_wasm_tests.sh
794+
795+
# Install Jest
796+
cd cmake-out-wasm/extension/wasm/test
797+
npm install --save-dev jest
798+
799+
# Run unit test
800+
npm test
801+
767802
unittest-nxp-neutron:
768803
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
769804
permissions:

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,10 @@ if(EXECUTORCH_BUILD_PYBIND)
771771
)
772772
endif()
773773

774+
if(EXECUTORCH_BUILD_WASM)
775+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/extension/wasm)
776+
endif()
777+
774778
if(EXECUTORCH_BUILD_EXTENSION_TRAINING)
775779
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/extension/training)
776780
list(APPEND _executorch_extensions extension_training)

extension/wasm/CMakeLists.txt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
# Please this file formatted by running:
8+
# ~~~
9+
# cmake-format -i CMakeLists.txt
10+
# ~~~
11+
12+
cmake_minimum_required(VERSION 3.29)
13+
14+
project(executorch_wasm)
15+
16+
if(NOT CMAKE_CXX_STANDARD)
17+
set(CMAKE_CXX_STANDARD 17)
18+
endif()
19+
20+
if(NOT EMSCRIPTEN)
21+
message(FATAL_ERROR "Emscripten is required to build this target")
22+
endif()
23+
24+
# Source root directory for executorch.
25+
if(NOT EXECUTORCH_ROOT)
26+
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
27+
endif()
28+
29+
include(${EXECUTORCH_ROOT}/tools/cmake/Utils.cmake)
30+
set(_common_compile_options -Wno-deprecated-declarations -fPIC -Wall -Werror)
31+
set(_common_include_directories ${EXECUTORCH_ROOT}/..)
32+
33+
set(link_libraries)
34+
list(
35+
APPEND
36+
link_libraries
37+
embind
38+
executorch_core
39+
extension_data_loader
40+
portable_ops_lib
41+
extension_module_static
42+
extension_tensor
43+
extension_runner_util
44+
)
45+
46+
add_library(executorch_wasm OBJECT wasm_bindings.cpp)
47+
48+
target_compile_options(executorch_wasm PUBLIC ${_common_compile_options})
49+
target_include_directories(
50+
executorch_wasm PUBLIC ${_common_include_directories}
51+
)
52+
target_link_libraries(executorch_wasm PUBLIC ${link_libraries})
53+
54+
if(EXECUTORCH_BUILD_WASM_TESTS)
55+
add_subdirectory(test)
56+
endif()

extension/wasm/test/CMakeLists.txt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
# Please this file formatted by running:
8+
# ~~~
9+
# cmake-format -i CMakeLists.txt
10+
# ~~~
11+
12+
set(MODELS_DIR ${CMAKE_CURRENT_BINARY_DIR}/models/)
13+
14+
add_custom_command(
15+
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/models/add_mul.pte
16+
${CMAKE_CURRENT_BINARY_DIR}/models/add.pte
17+
COMMAND ${CMAKE_COMMAND} -E make_directory "${MODELS_DIR}"
18+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../..
19+
COMMAND python3 -m examples.portable.scripts.export --model_name="add_mul"
20+
--output_dir="${MODELS_DIR}"
21+
COMMAND python3 -m examples.portable.scripts.export --model_name="add"
22+
--output_dir="${MODELS_DIR}"
23+
)
24+
25+
add_custom_target(
26+
executorch_wasm_test_models DEPENDS ${MODELS_DIR}/add_mul.pte
27+
${MODELS_DIR}/add.pte
28+
)
29+
30+
add_custom_command(
31+
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/package.json
32+
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/package.json
33+
${CMAKE_CURRENT_BINARY_DIR}/package.json
34+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/package.json
35+
COMMENT "Copying package.json to build output directory"
36+
)
37+
38+
add_custom_target(
39+
executorch_wasm_test_package_json
40+
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/package.json
41+
)
42+
43+
add_executable(executorch_wasm_tests)
44+
target_link_libraries(executorch_wasm_tests PUBLIC executorch_wasm)
45+
target_link_options(
46+
executorch_wasm_tests
47+
PUBLIC
48+
--embed-file
49+
"${MODELS_DIR}@/"
50+
--post-js
51+
${CMAKE_CURRENT_SOURCE_DIR}/unittests.js
52+
-sASSERTIONS=2
53+
)
54+
set_target_properties(
55+
executorch_wasm_tests PROPERTIES OUTPUT_NAME "executorch_wasm.test"
56+
)
57+
set_property(
58+
TARGET executorch_wasm_tests
59+
APPEND
60+
PROPERTY LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/unittests.js
61+
)
62+
add_dependencies(
63+
executorch_wasm_tests executorch_wasm_test_models
64+
executorch_wasm_test_package_json
65+
)

extension/wasm/test/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"scripts": {
3+
"test": "jest"
4+
}
5+
}

0 commit comments

Comments
 (0)