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