README.md
1# Android
2
3## Demo applications and tutorials
4
5Demo applications with code walk-through can be find in [this github repo](https://github.com/pytorch/android-demo-app).
6
7## Publishing
8
9##### Release
10Release artifacts are published to jcenter:
11
12```groovy
13repositories {
14 jcenter()
15}
16
17# lite interpreter build
18dependencies {
19 implementation 'org.pytorch:pytorch_android_lite:1.10.0'
20 implementation 'org.pytorch:pytorch_android_torchvision_lite:1.10.0'
21}
22
23# full jit build
24dependencies {
25 implementation 'org.pytorch:pytorch_android:1.10.0'
26 implementation 'org.pytorch:pytorch_android_torchvision:1.10.0'
27}
28```
29
30##### Nightly
31
32Nightly(snapshots) builds are published every night from `master` branch to [nexus sonatype snapshots repository](https://oss.sonatype.org/#nexus-search;quick~pytorch_android)
33
34To use them repository must be specified explicitly:
35```groovy
36repositories {
37 maven {
38 url "https://oss.sonatype.org/content/repositories/snapshots"
39 }
40}
41
42# lite interpreter build
43dependencies {
44 ...
45 implementation 'org.pytorch:pytorch_android_lite:1.12.0-SNAPSHOT'
46 implementation 'org.pytorch:pytorch_android_torchvision_lite:1.12.0-SNAPSHOT'
47 ...
48}
49
50# full jit build
51dependencies {
52 ...
53 implementation 'org.pytorch:pytorch_android:1.12.0-SNAPSHOT'
54 implementation 'org.pytorch:pytorch_android_torchvision:1.12.0-SNAPSHOT'
55 ...
56}
57```
58The current nightly(snapshots) version is the value of `VERSION_NAME` in `gradle.properties` in current folder, at this moment it is `1.8.0-SNAPSHOT`.
59
60## Building PyTorch Android from Source
61
62In some cases you might want to use a local build of pytorch android, for example you may build custom libtorch binary with another set of operators or to make local changes.
63
64For this you can use `./scripts/build_pytorch_android.sh` script.
65```bash
66git clone https://github.com/pytorch/pytorch.git
67cd pytorch
68git submodule update --init --recursive
69bash ./scripts/build_pytorch_android.sh
70```
71
72The workflow contains several steps:
73
741\. Build libtorch for android for all 4 android abis (armeabi-v7a, arm64-v8a, x86, x86_64)
75
762\. Create symbolic links to the results of those builds:
77`android/pytorch_android/src/main/jniLibs/${abi}` to the directory with output libraries
78`android/pytorch_android/src/main/cpp/libtorch_include/${abi}` to the directory with headers. These directories are used to build `libpytorch.so` library that will be loaded on android device.
79
803\. And finally run `gradle` in `android/pytorch_android` directory with task `assembleRelease`
81
82Script requires that Android SDK, Android NDK and gradle are installed.
83They are specified as environment variables:
84
85`ANDROID_HOME` - path to [Android SDK](https://developer.android.com/studio/command-line/sdkmanager.html)
86
87`ANDROID_NDK` - path to [Android NDK](https://developer.android.com/studio/projects/install-ndk). It's recommended to use NDK 21.x.
88
89`GRADLE_HOME` - path to [gradle](https://gradle.org/releases/)
90
91
92After successful build you should see the result as aar file:
93
94```bash
95$ find pytorch_android/build/ -type f -name *aar
96pytorch_android/build/outputs/aar/pytorch_android.aar
97pytorch_android_torchvision/build/outputs/aar/pytorch_android.aar
98```
99
100It can be used directly in android projects, as a gradle dependency:
101```groovy
102allprojects {
103 repositories {
104 flatDir {
105 dirs 'libs'
106 }
107 }
108}
109
110dependencies {
111 implementation(name:'pytorch_android', ext:'aar')
112 implementation(name:'pytorch_android_torchvision', ext:'aar')
113 ...
114 implementation 'com.facebook.soloader:nativeloader:0.10.5'
115 implementation 'com.facebook.fbjni:fbjni-java-only:0.2.2'
116}
117```
118We also have to add all transitive dependencies of our aars.
119As `pytorch_android` [depends](https://github.com/pytorch/pytorch/blob/master/android/pytorch_android/build.gradle#L76-L77) on `'com.facebook.soloader:nativeloader:0.10.5'` and `'com.facebook.fbjni:fbjni-java-only:0.2.2'`, we need to add them.
120(In case of using maven dependencies they are added automatically from `pom.xml`).
121
122You can check out [test app example](https://github.com/pytorch/pytorch/blob/master/android/test_app/app/build.gradle) that uses aars directly.
123
124## Linking to prebuilt libtorch library from gradle dependency
125
126In some cases, you may want to use libtorch from your android native build.
127You can do it without building libtorch android, using native libraries from PyTorch android gradle dependency.
128For that, you will need to add the next lines to your gradle build.
129```groovy
130android {
131...
132 configurations {
133 extractForNativeBuild
134 }
135...
136 compileOptions {
137 externalNativeBuild {
138 cmake {
139 arguments "-DANDROID_STL=c++_shared"
140 }
141 }
142 }
143...
144 externalNativeBuild {
145 cmake {
146 path "CMakeLists.txt"
147 }
148 }
149}
150
151dependencies {
152 extractForNativeBuild('org.pytorch:pytorch_android:1.10.0')
153}
154
155task extractAARForNativeBuild {
156 doLast {
157 configurations.extractForNativeBuild.files.each {
158 def file = it.absoluteFile
159 copy {
160 from zipTree(file)
161 into "$buildDir/$file.name"
162 include "headers/**"
163 include "jni/**"
164 }
165 }
166 }
167}
168
169tasks.whenTaskAdded { task ->
170 if (task.name.contains('externalNativeBuild')) {
171 task.dependsOn(extractAARForNativeBuild)
172 }
173}
174```
175
176pytorch_android aar contains headers to link in `headers` folder and native libraries in `jni/$ANDROID_ABI/`.
177As PyTorch native libraries use `ANDROID_STL` - we should use `ANDROID_STL=c++_shared` to have only one loaded binary of STL.
178
179The added task will unpack them to gradle build directory.
180
181In your native build you can link to them adding these lines to your CMakeLists.txt:
182
183
184```cmake
185# Relative path of gradle build directory to CMakeLists.txt
186set(build_DIR ${CMAKE_SOURCE_DIR}/build)
187
188file(GLOB PYTORCH_INCLUDE_DIRS "${build_DIR}/pytorch_android*.aar/headers")
189file(GLOB PYTORCH_LINK_DIRS "${build_DIR}/pytorch_android*.aar/jni/${ANDROID_ABI}")
190
191set(BUILD_SUBDIR ${ANDROID_ABI})
192target_include_directories(${PROJECT_NAME} PRIVATE
193 ${PYTORCH_INCLUDE_DIRS}
194)
195
196find_library(PYTORCH_LIBRARY pytorch_jni
197 PATHS ${PYTORCH_LINK_DIRS}
198 NO_CMAKE_FIND_ROOT_PATH)
199
200find_library(FBJNI_LIBRARY fbjni
201 PATHS ${PYTORCH_LINK_DIRS}
202 NO_CMAKE_FIND_ROOT_PATH)
203
204target_link_libraries(${PROJECT_NAME}
205 ${PYTORCH_LIBRARY})
206 ${FBJNI_LIBRARY})
207
208```
209If your CMakeLists.txt file is located in the same directory as your build.gradle, `set(build_DIR ${CMAKE_SOURCE_DIR}/build)` should work for you. But if you have another location of it, you may need to change it.
210
211After that, you can use libtorch C++ API from your native code.
212```cpp
213#include <string>
214#include <ATen/NativeFunctions.h>
215#include <torch/script.h>
216namespace pytorch_testapp_jni {
217namespace {
218 struct JITCallGuard {
219 c10::InferenceMode guard;
220 torch::jit::GraphOptimizerEnabledGuard no_optimizer_guard{false};
221 };
222}
223
224void loadAndForwardModel(const std::string& modelPath) {
225 JITCallGuard guard;
226 torch::jit::Module module = torch::jit::load(modelPath);
227 module.eval();
228 torch::Tensor t = torch::randn({1, 3, 224, 224});
229 c10::IValue t_out = module.forward({t});
230}
231}
232```
233
234To load torchscript model for mobile we need some special setup which is placed in `struct JITCallGuard` in this example. It may change in future, you can track the latest changes keeping an eye in our [pytorch android jni code]([https://github.com/pytorch/pytorch/blob/master/android/pytorch_android/src/main/cpp/pytorch_jni_jit.cpp#L28)
235
236[Example of linking to libtorch from aar](https://github.com/pytorch/pytorch/tree/master/android/test_app)
237
238## PyTorch Android API Javadoc
239
240You can find more details about the PyTorch Android API in the [Javadoc](https://pytorch.org/javadoc/).
241