Skip to content

Commit dcacde0

Browse files
authored
Update docs on linkage and debugging.
Differential Revision: D66146395 Pull Request resolved: #6948
1 parent 709e739 commit dcacde0

File tree

1 file changed

+68
-33
lines changed

1 file changed

+68
-33
lines changed

docs/source/apple-runtime.md

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The ExecuTorch Runtime for iOS and macOS is distributed as a collection of prebu
88
* `backend_coreml` - Core ML backend
99
* `backend_mps` - MPS backend
1010
* `backend_xnnpack` - XNNPACK backend
11-
* `kernels_custom` - Custom kernels
11+
* `kernels_custom` - Custom kernels for LLMs
1212
* `kernels_optimized` - Optimized kernels
1313
* `kernels_portable` - Portable kernels (naive implementation used as a reference)
1414
* `kernels_quantized` - Quantized kernels
@@ -19,19 +19,6 @@ Link your binary with the ExecuTorch runtime and any backends or kernels used by
1919

2020
## Integration
2121

22-
### Setup
23-
24-
#### CMake
25-
26-
Building the Xcode project requires CMake. Installing via homebrew does not
27-
typically work; instead, install the packaged application and commandline tools
28-
globally:
29-
30-
1. Download the macOS `.dmg` installer from https://cmake.org/download
31-
2. Open the `.dmg`
32-
3. Drag the CMake app to the `/Applications` folder
33-
4. In a terminal, install the command line tools: `sudo /Applications/CMake.app/Contents/bin/cmake-gui --install`
34-
3522
### Swift Package Manager
3623

3724
The prebuilt ExecuTorch runtime, backend, and kernels are available as a [Swift PM](https://www.swift.org/documentation/package-manager/) package.
@@ -67,7 +54,7 @@ let package = Package(
6754
],
6855
dependencies: [
6956
// Use "swiftpm-0.4.0.<year_month_day>" branch name for a nightly build.
70-
.package(url: "https://github.com/pytorch/executorch.git", .branch("0.4.0"))
57+
.package(url: "https://github.com/pytorch/executorch.git", .branch("swiftpm-0.4.0"))
7158
],
7259
targets: [
7360
.target(
@@ -104,27 +91,19 @@ xcode-select --install
10491
2. Clone ExecuTorch:
10592

10693
```bash
107-
git clone https://github.com/pytorch/executorch.git --recursive --depth 1
108-
cd executorch
94+
git clone https://github.com/pytorch/executorch.git --depth 1 --recurse-submodules --shallow-submodules && cd executorch
10995
```
11096

11197
3. Set up [Python](https://www.python.org/downloads/macos/) 3.10+ and activate a virtual environment:
11298

11399
```bash
114-
python3 -m venv .venv
115-
source .venv/bin/activate
116-
```
117-
118-
4. Install [Cmake](https://cmake.org) and other helpful [PyPI](https://pypi.org) packages:
119-
120-
```bash
121-
pip install --upgrade cmake pip zstd
100+
python3 -m venv .venv && source .venv/bin/activate && pip install --upgrade pip
122101
```
123102

124-
5. Install the required dependencies, including those needed for the backends like [Core ML](build-run-coreml.md) or [MPS](build-run-mps.md), if you plan to build them as well:
103+
4. Install the required dependencies, including those needed for the backends like [Core ML](build-run-coreml.md) or [MPS](build-run-mps.md), if you plan to build them as well:
125104

126105
```bash
127-
./install_requirements.sh
106+
./install_requirements.sh --pybind coreml mps xnnpack
128107

129108
# Optional dependencies for Core ML backend.
130109
./backends/apple/coreml/scripts/install_requirements.sh
@@ -133,6 +112,14 @@ pip install --upgrade cmake pip zstd
133112
./backends/apple/mps/install_requirements.sh
134113
```
135114

115+
5. Install [CMake](https://cmake.org):
116+
117+
Download the macOS binary distribution from the [CMake website](https://cmake.org/download), open the `.dmg` file, move `CMake.app` to the `/Applications` directory, and then run the following command to install the CMake command-line tools:
118+
119+
```bash
120+
sudo /Applications/CMake.app/Contents/bin/cmake-gui --install
121+
```
122+
136123
6. Use the provided script to build .xcframeworks:
137124

138125
```bash
@@ -142,21 +129,52 @@ pip install --upgrade cmake pip zstd
142129
For example, the following invocation will build the ExecuTorch Runtime and all currently available kernels and backends for the Apple platform:
143130

144131
```bash
145-
./build/build_apple_frameworks.sh --coreml --custom --mps --optimized --portable --quantized --xnnpack
132+
./build/build_apple_frameworks.sh --coreml --mps --xnnpack --custom --optimized --portable --quantized
146133
```
147134

135+
Append a `--Debug` flag to the above command to build the binaries with debug symbols if needed.
136+
148137
After the build finishes successfully, the resulting frameworks can be found in the `cmake-out` directory.
149138
Copy them to your project and link them against your targets.
150139

140+
## Linkage
141+
142+
ExecuTorch initializes its backends and kernels (operators) during app startup by registering them in a static dictionary. If you encounter errors like "unregistered kernel" or "unregistered backend" at runtime, you may need to explicitly force-load certain components. Use the `-all_load` or `-force_load` linker flags in your Xcode build configuration to ensure components are registered early.
143+
144+
Here's an example of a Xcode configuration file (`.xcconfig`):
145+
146+
```
147+
OTHER_LDFLAGS[sdk=iphonesimulator*] = $(inherited) \
148+
-force_load $(BUILT_PRODUCTS_DIR)/libexecutorch-ios-release.a \
149+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_coreml-ios-release.a \
150+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_mps-ios-release.a \
151+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_xnnpack-ios-release.a
152+
153+
OTHER_LDFLAGS[sdk=iphoneos*] = $(inherited) \
154+
-force_load $(BUILT_PRODUCTS_DIR)/libexecutorch-ios-release.a \
155+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_coreml-ios-release.a \
156+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_mps-ios-release.a \
157+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_xnnpack-ios-release.a
158+
159+
OTHER_LDFLAGS[sdk=macos*] = $(inherited) \
160+
-force_load $(BUILT_PRODUCTS_DIR)/libexecutorch-ios-release.a \
161+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_coreml-ios-release.a \
162+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_mps-ios-release.a \
163+
-force_load $(BUILT_PRODUCTS_DIR)/libbackend_xnnpack-ios-release.a
164+
```
165+
166+
Replace `release` with `debug` in library file names for a Debug mode config respectively. You can assign such `.xcconfig` file to your target in Xcode: add it to your project, navigate to the project's Info tab, and select it in the build configuration for Debug and Release modes.
167+
151168
## Runtime API
152169

153-
Check out the [C++ Runtime API Tutorial](extension-module.md) to learn more about how to load and run an exported model. It is recommended to use the C++ API for macOS or iOS, wrapped with Objective-C++ and Swift code if needed to expose it for other components. Please refer to the [Demo App](demo-apps-ios.md) as an example of such a setup.
170+
Check out the [C++ Runtime API](extension-module.md) and [Tensors](extension-tensor.md) tutorials to learn more about how to load and run an exported model. It is recommended to use the C++ API for macOS or iOS, wrapped with Objective-C++ and Swift code if needed to expose it for other components. Please refer to the [Demo App](demo-apps-ios.md) as an example of such a setup.
154171

155172
Once linked against the `executorch` runtime framework, the target can now import all ExecuTorch public headers. For example, in Objective-C++:
156173

157174
```objectivecpp
158175
#import <ExecuTorch/ExecuTorch.h>
159176
#import <executorch/extension/module/module.h>
177+
#import <executorch/extension/tensor/tensor.h>
160178
```
161179

162180
Or in Swift:
@@ -167,6 +185,8 @@ import ExecuTorch
167185

168186
**Note:** Importing the ExecuTorch umbrella header (or ExecuTorch module in Swift) provides access to the logging API only. You still need to import the other runtime headers explicitly as needed, e.g., `module.h`. There is no support for other runtime APIs in Objective-C or Swift beyond logging described below.
169187

188+
**Note:** Logs are stripped in the release builds of ExecuTorch frameworks. To preserve logging, use debug builds during development.
189+
170190
### Logging
171191

172192
We provide extra APIs for logging in Objective-C and Swift as a lightweight wrapper of the internal ExecuTorch machinery. To use it, just import the main framework header in Objective-C. Then use the `ExecuTorchLog` interface (or the `Log` class in Swift) to subscribe your own implementation of the `ExecuTorchLogSink` protocol (or `LogSink` in Swift) to listen to log events.
@@ -268,16 +288,31 @@ extension MyClass: LogSink {
268288

269289
**Note:** In the example, the logs are intentionally stripped out when the code is not built for Debug mode, i.e., the `DEBUG` macro is not defined or equals zero.
270290

291+
## Debugging
292+
293+
If you are linking against a Debug build of the ExecuTorch frameworks, configure your debugger to map the source code correctly by using the following LLDB command in the debug session:
294+
295+
```
296+
settings append target.source-map /executorch <path_to_executorch_source_code>
297+
```
298+
271299
## Troubleshooting
272300

273-
### Missing operator or backend
301+
### Slow execution
302+
303+
Ensure the exported model is using an appropriate backend, such as XNNPACK, Core ML, or MPS. If the correct backend is invoked but performance issues persist, confirm that you are linking against the Release build of the backend runtime.
274304

275-
If after linking against a certain ExecuTorch library you still get an unregistered kernel or backend error at runtime, you may need to use the `-all_load` or `-force_load $(BUILT_PRODUCTS_DIR)/<library_name>` linker flags to forcefully register the corresponding components at app start, e.g., `-force_load $(BUILT_PRODUCTS_DIR)/libkernels_portable-ios-release.a`.
305+
For optimal performance, link the ExecuTorch runtime in Release mode too. If debugging is needed, you can keep the ExecuTorch runtime in Debug mode with minimal impact on performance, but preserve logging and debug symbols.
276306

277307
### Swift PM
278308

279-
If Swift PM complains about a checksum mismatch for the package contents, try cleaning the cache:
309+
If you encounter a checksum mismatch error with Swift PM, clear the package cache using the Xcode menu (`File > Packages > Reset Package Caches`) or the following command:
280310

281311
```bash
282-
rm -rf ~/Library/Caches/org.swift.swiftpm
312+
rm -rf <YouProjectName>.xcodeproj/project.xcworkspace/xcshareddata/swiftpm \
313+
~/Library/org.swift.swiftpm \
314+
~/Library/Caches/org.swift.swiftpm \
315+
~/Library/Caches/com.apple.dt.Xcode \
316+
~/Library/Developer/Xcode/DerivedData
283317
```
318+
**Note:** Ensure Xcode is fully quit before running the terminal command to avoid conflicts with active processes.

0 commit comments

Comments
 (0)