1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// some new clippy::lint annotations are supported in latest Rust but not recognized by older versions
//! Unsafe bindings for ExecuTorch - On-device AI across mobile, embedded and edge for PyTorch.
//!
//! Provides a low level Rust bindings for the ExecuTorch library.
//! For the common use case, it is recommended to use the high-level API provided by the `executorch` crate, where
//! a more detailed documentation can be found.
//!
//!
//! To build the library, you need to build the C++ library yourself first.
//! Currently the supported Cpp executorch version is `1.1.0`.
//! The C++ library allow for great flexibility with many flags, customizing which modules, kernels, and extensions are
//! built.
//! Multiple static libraries are built, and the Rust library links to them.
//! In the following example we build the C++ library with the necessary flags to run example `hello_world`:
//! ```bash
//! # Clone the C++ library
//! cd ${EXECUTORCH_CPP_DIR}
//! git clone --depth 1 --branch v1.1.0 https://github.com/pytorch/executorch.git .
//! git submodule sync --recursive
//! git submodule update --init --recursive
//!
//! # Install requirements
//! ./install_requirements.sh
//!
//! # Build C++ library
//! mkdir cmake-out && cd cmake-out
//! cmake \
//! -DDEXECUTORCH_SELECT_OPS_LIST=aten::add.out \
//! -DEXECUTORCH_BUILD_EXECUTOR_RUNNER=OFF \
//! -DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=OFF \
//! -DEXECUTORCH_BUILD_PORTABLE_OPS=ON \
//! -DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
//! -DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
//! -DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON \
//! -DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
//! -DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
//! -DEXECUTORCH_ENABLE_PROGRAM_VERIFICATION=ON \
//! -DEXECUTORCH_ENABLE_LOGGING=ON \
//! ..
//! make -j
//!
//! # Run example
//! # We set EXECUTORCH_RS_EXECUTORCH_LIB_DIR to the path of the C++ build output
//! cd ${EXECUTORCH_RS_DIR}/examples/hello_world
//! python export_model.py
//! EXECUTORCH_RS_EXECUTORCH_LIB_DIR=${EXECUTORCH_CPP_DIR}/cmake-out cargo run
//! ```
//!
//! The `executorch` crate will always look for the following static libraries:
//! - `libexecutorch.a`
//! - `libexecutorch_core.a`
//!
//! Additional libs are required if feature flags are enabled.
//! For example the `libextension_data_loader.a` is required if the `data-loader` feature is enabled,
//! and `libextension_tensor.a` is required if the `tensor-ptr` feature is enabled.
//! See the feature flags section for more info.
//!
//! The static libraries of the kernels implementations are required only if your model uses them, and they should be
//! **linked manually** by the binary that uses the `executorch` crate.
//! For example, the `hello_world` example uses a model with a single addition operation, so it compile the C++
//! library with `DEXECUTORCH_SELECT_OPS_LIST=aten::add.out` and contain the following lines in its `build.rs`:
//! ```rust
//! println!("cargo::rustc-link-lib=static:+whole-archive=portable_kernels");
//! println!("cargo::rustc-link-lib=static:+whole-archive=portable_ops_lib");
//!
//! let libs_dir = std::env::var("EXECUTORCH_RS_EXECUTORCH_LIB_DIR").unwrap();
//! println!("cargo::rustc-link-search=native={libs_dir}/kernels/portable/");
//! ```
//! Note that the ops and kernels libs are linked with `+whole-archive` to ensure that all symbols are included in the
//! binary.
//!
//! The `EXECUTORCH_RS_EXECUTORCH_LIB_DIR` environment variable should be set to the path of the C++ build output.
//! If its not provided, its the responsibility of the binary to add the libs directories to the linker search path, and
//! the crate will just link to the static libraries using `cargo::rustc-link-lib=...`.
//!
//! If you want to link to executorch libs yourself, set the environment variable `EXECUTORCH_RS_LINK` to `0`, and
//! the crate will not link to any library and not modify the linker search path.
//!
//! The crate contains a small C/C++ bridge that uses the headers of the C++ library,
//! and it is compiled using the `cc` crate (and the `cxx` crate, that uses `cc` under the hood).
//! If custom compiler flags (for example `-DET_MIN_LOG_LEVEL=Debug`) are used when compiling the C++ library,
//! you should set the matching environment variables that `cc` reads during `cargo build`
//! (for example `CFLAGS=-DET_MIN_LOG_LEVEL=Debug CXXFLAGS=-DET_MIN_LOG_LEVEL=Debug`),
//! see the [cc docs](https://docs.rs/cc/latest/cc/).
//!
//!
//! ## Cargo Features
//! By default the `std` feature is enabled.
//! - `data-loader`:
//! Includes the [`FileDataLoader`] and [`MmapDataLoader`] structs. Without this feature the only available
//! data loader is [`BufferDataLoader`]. The `libextension_data_loader.a` static library is required, compile C++
//! `executorch` with `EXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON`.
//! - `module`:
//! Includes the `Module` struct, a high-level API for loading and executing PyTorch models. It is an alternative to
//! the lower-level `Program` API, which is more suitable for embedded systems.
//! The `libextension_module_static.a` static library is required, compile C++ `executorch` with
//! `EXECUTORCH_BUILD_EXTENSION_MODULE=ON`.
//! Also includes the `std`, `data-loader` and `flat-tensor` features.
//! - `tensor-ptr`:
//! Includes a few functions creating `cxx::SharedPtr<Tensor>` pointers, that manage the lifetime of the tensor
//! object alongside the lifetimes of the data buffer and additional metadata. The `libextension_tensor.a`
//! static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_TENSOR=ON`.
//! Also includes the `std` feature.
//! - `flat-tensor`:
//! Includes the `FlatTensorDataMap` struct that can read `.ptd` files with external tensors for models.
//! The `libextension_flat_tensor.a` static library is required,
//! compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON`.
//! - `etdump`:
//! Includes the `ETDumpGen` struct, an implementation of an `EventTracer`, used for debugging and profiling.
//! The `libetdump.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_DEVTOOLS=ON` and
//! `EXECUTORCH_ENABLE_EVENT_TRACER=ON`.
//! In addition, the `flatcc` (or `flatcc_d`) library is required, available at `{CMAKE_DIR}/third-party/flatcc_ep/lib/`,
//! and should be linked by the user.
//! - `std`:
//! Enable the standard library. This feature is enabled by default, but can be disabled to build `executorch` in a `no_std` environment.
//! NOTE: no_std is still WIP, see <https://github.com/pytorch/executorch/issues/4561>
//!
//! [`FileDataLoader`]: crate::FileDataLoader
//! [`MmapDataLoader`]: crate::MmapDataLoader
//! [`BufferDataLoader`]: crate::BufferDataLoader
//! [`Module`]: crate::Module
extern crate core as std;
extern crate link_cplusplus;
/// The version of the ExecuTorch C++ library that this crate is compatible and linked with.
pub const EXECUTORCH_CPP_VERSION: &str = "1.1.0";
pub use c_bridge::*;
pub use *;
/// Utility functions and structs.
// Re-export cxx
pub use cxx;