Skip to content

Commit 014208e

Browse files
authored
[Android] Update gradle version and other changes in android apps, CI modification to auto-build Android apps and upload artifacts (#11241)
* Update gradle version in android_rpc app * Support latest gradle, bump versions, replace ndk build script with gradle tasks * [android_rpc] Fix linter errors, disable weird ones * [android_deploy] Support latest gradle, bump versions, fix linter errors, disable some of them * [android_camera] Support latest gradle, bump versions, rewrite readme * [android_camera] Fix linter errors * Fix sanity check errors * Add Android jobs for Github Actions * Add python requirements for TVM and android_camera, use preinstalled NDK * Revert to build with make * Add minrpc include (PR #11232) * Remove relative paths
1 parent 3f53e7a commit 014208e

File tree

36 files changed

+497
-251
lines changed

36 files changed

+497
-251
lines changed

.github/workflows/main.yml

Lines changed: 117 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -38,59 +38,124 @@ jobs:
3838
MacOS:
3939
runs-on: macOS-latest
4040
steps:
41-
- uses: actions/checkout@v2
42-
with:
43-
submodules: 'recursive'
44-
- name: Set up environment
45-
uses: ./.github/actions/setup
46-
- name: Conda Build
47-
shell: bash -l {0}
48-
run: >-
49-
conda build --output-folder=conda/pkg conda/recipe &&
50-
conda install tvm -c ./conda/pkg
51-
- name: Build iOS RPC
52-
run: |
53-
IOS_VERSION="14.0"
54-
CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release \
55-
-DCMAKE_SYSTEM_NAME=iOS \
56-
-DCMAKE_SYSTEM_VERSION=${IOS_VERSION} \
57-
-DCMAKE_OSX_SYSROOT=iphonesimulator \
58-
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
59-
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
60-
-DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON \
61-
-DUSE_IOS_RPC=ON"
62-
63-
mkdir build-ios-simulator
64-
cd build-ios-simulator
65-
cmake .. ${CMAKE_FLAGS}
66-
cmake --build . --target ios_rpc
67-
- name: Test
68-
shell: bash -l {0}
69-
run: >-
70-
python -m pytest -v tests/python/all-platform-minimal-test
71-
- name: Test iOS RPC
72-
shell: bash -l {0}
73-
run: >-
74-
python -m pip install tornado psutil cloudpickle &&
75-
export PYTHONPATH=tests/python/contrib:${PYTHONPATH} &&
76-
export BUNDLE_ID=org.apache.tvmrpc &&
77-
export BUNDLE_PATH=build-ios-simulator/apps/ios_rpc/ios_rpc/src/ios_rpc-build/Release-iphonesimulator/tvmrpc.app &&
78-
python -m pytest -v tests/python/contrib/test_rpc_server_device.py
41+
- uses: actions/checkout@v2
42+
with:
43+
submodules: 'recursive'
44+
- name: Set up environment
45+
uses: ./.github/actions/setup
46+
- name: Conda Build
47+
shell: bash -l {0}
48+
run: >-
49+
conda build --output-folder=conda/pkg conda/recipe &&
50+
conda install tvm -c ./conda/pkg
51+
- name: Build iOS RPC
52+
run: |
53+
IOS_VERSION="14.0"
54+
CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release \
55+
-DCMAKE_SYSTEM_NAME=iOS \
56+
-DCMAKE_SYSTEM_VERSION=${IOS_VERSION} \
57+
-DCMAKE_OSX_SYSROOT=iphonesimulator \
58+
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
59+
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
60+
-DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON \
61+
-DUSE_IOS_RPC=ON"
62+
63+
mkdir build-ios-simulator
64+
cd build-ios-simulator
65+
cmake .. ${CMAKE_FLAGS}
66+
cmake --build . --target ios_rpc
67+
- name: Test
68+
shell: bash -l {0}
69+
run: >-
70+
python -m pytest -v tests/python/all-platform-minimal-test
71+
- name: Test iOS RPC
72+
shell: bash -l {0}
73+
run: >-
74+
python -m pip install tornado psutil cloudpickle &&
75+
export PYTHONPATH=tests/python/contrib:${PYTHONPATH} &&
76+
export BUNDLE_ID=org.apache.tvmrpc &&
77+
export BUNDLE_PATH=build-ios-simulator/apps/ios_rpc/ios_rpc/src/ios_rpc-build/Release-iphonesimulator/tvmrpc.app &&
78+
python -m pytest -v tests/python/contrib/test_rpc_server_device.py
7979
8080
Windows:
8181
runs-on: windows-2019
8282
steps:
83-
- uses: actions/checkout@v2
84-
with:
85-
submodules: 'recursive'
86-
- name: Set up environment
87-
uses: ./.github/actions/setup
88-
- name: Conda Build
89-
shell: cmd /C call {0}
90-
run: >-
91-
conda build --output-folder=conda/pkg conda/recipe &&
92-
conda install tvm -c ./conda/pkg
93-
- name: Test
94-
shell: cmd /C call {0}
95-
run: >-
96-
python -m pytest -v tests/python/all-platform-minimal-test
83+
- uses: actions/checkout@v2
84+
with:
85+
submodules: 'recursive'
86+
- name: Set up environment
87+
uses: ./.github/actions/setup
88+
- name: Conda Build
89+
shell: cmd /C call {0}
90+
run: >-
91+
conda build --output-folder=conda/pkg conda/recipe &&
92+
conda install tvm -c ./conda/pkg
93+
- name: Test
94+
shell: cmd /C call {0}
95+
run: >-
96+
python -m pytest -v tests/python/all-platform-minimal-test
97+
98+
Android:
99+
runs-on: Ubuntu-20.04
100+
steps:
101+
- uses: actions/checkout@v2
102+
with:
103+
submodules: 'recursive'
104+
- name: Set up environment
105+
uses: ./.github/actions/setup
106+
- name: Set up java
107+
uses: actions/setup-java@v3
108+
with:
109+
distribution: 'zulu'
110+
java-version: '11'
111+
- name: Build TVM
112+
shell: bash -l {0}
113+
run: |
114+
mkdir build
115+
cd build
116+
../tests/scripts/task_config_build_jvm.sh .
117+
cmake ..
118+
make
119+
- name: Build TVM4J
120+
run: |
121+
make jvmpkg
122+
- name: Build android_rpc
123+
working-directory: apps/android_rpc
124+
run: |
125+
export PATH="${ANDROID_NDK_HOME}:$PATH"
126+
gradle clean build
127+
- name: Upload android_rpc APK
128+
uses: actions/upload-artifact@v2
129+
with:
130+
name: android_rpc-debug.apk
131+
path: ./apps/android_rpc/app/build/outputs/apk/debug/app-debug.apk
132+
- name: Build android_deploy
133+
working-directory: apps/android_deploy
134+
run: |
135+
export PATH="${ANDROID_NDK_HOME}:$PATH"
136+
gradle clean build
137+
- name: Upload android_deploy APK
138+
uses: actions/upload-artifact@v2
139+
with:
140+
name: android_deploy-debug.apk
141+
path: ./apps/android_deploy/app/build/outputs/apk/debug/app-debug.apk
142+
- name: Build android_camera
143+
working-directory: apps/android_camera
144+
run: |
145+
mkdir -p app/src/main/assets/models/
146+
export TVM_NDK_CC=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang++
147+
export TVM_HOME=~/work/tvm/tvm
148+
export PYTHONPATH=$TVM_HOME/python:${PYTHONPATH}
149+
python3 ${TVM_HOME}/python/gen_requirements.py
150+
pip3 install -r ${TVM_HOME}/python/requirements/core.txt
151+
cd models
152+
pip3 install -r requirements.txt
153+
python3 prepare_model.py
154+
cd ..
155+
export PATH="${ANDROID_NDK_HOME}:$PATH"
156+
gradle clean build
157+
- name: Upload android_camera APK
158+
uses: actions/upload-artifact@v2
159+
with:
160+
name: android_camera-debug.apk
161+
path: ./apps/android_camera/app/build/outputs/apk/debug/app-debug.apk

apps/android_camera/README.md

Lines changed: 104 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,107 @@
1-
[//]: # Licensed to the Apache Software Foundation (ASF) under one
2-
[//]: # or more contributor license agreements. See the NOTICE file
3-
[//]: # distributed with this work for additional information
4-
[//]: # regarding copyright ownership. The ASF licenses this file
5-
[//]: # to you under the Apache License, Version 2.0 (the
6-
[//]: # "License"); you may not use this file except in compliance
7-
[//]: # with the License. You may obtain a copy of the License at
8-
[//]: #
9-
[//]: # http://www.apache.org/licenses/LICENSE-2.0
10-
[//]: #
11-
[//]: # Unless required by applicable law or agreed to in writing,
12-
[//]: # software distributed under the License is distributed on an
13-
[//]: # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14-
[//]: # KIND, either express or implied. See the License for the
15-
[//]: # specific language governing permissions and limitations
16-
[//]: # under the License.
17-
18-
Android Camera Demo Sample App
19-
==============================
20-
21-
The Android Camera Demo Sample App provides a basic implementation of an Android
22-
app that uses the tvm runtime to perform image classification in real time.
23-
24-
Converting Models
25-
-----------------
1+
<!--- Licensed to the Apache Software Foundation (ASF) under one -->
2+
<!--- or more contributor license agreements. See the NOTICE file -->
3+
<!--- distributed with this work for additional information -->
4+
<!--- regarding copyright ownership. The ASF licenses this file -->
5+
<!--- to you under the Apache License, Version 2.0 (the -->
6+
<!--- "License"); you may not use this file except in compliance -->
7+
<!--- with the License. You may obtain a copy of the License at -->
8+
9+
<!--- http://www.apache.org/licenses/LICENSE-2.0 -->
10+
11+
<!--- Unless required by applicable law or agreed to in writing, -->
12+
<!--- software distributed under the License is distributed on an -->
13+
<!--- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -->
14+
<!--- KIND, either express or implied. See the License for the -->
15+
<!--- specific language governing permissions and limitations -->
16+
<!--- under the License. -->
17+
18+
19+
# Android Camera Demo Sample App
20+
21+
The Android Camera Demo Sample App provides a basic implementation of an Android app that uses the tvm runtime to perform image classification in real time.
22+
23+
You will need JDK, [Android NDK](https://developer.android.com/ndk) and an Android device to use this.
24+
25+
## Build and Installation
26+
27+
### <a name="preparemodels">Prepare Models</a>
2628

2729
The `models/prepare_models.py` script provides a example flow for dumping model
2830
parameter files for use by the app.
31+
32+
1. Set path to the NDK CC: `export TVM_NDK_CC=[Path to CC, e.g. /opt/android-toolchain-arm64/bin/aarch64-linux-android-g++]`
33+
2. Switch to the script directory: `cd models`
34+
3. Run script: `python3 prepare_model.py`
35+
36+
#### Sample output
37+
```
38+
mobilenet_v2
39+
getting model...
40+
building...
41+
dumping lib...
42+
dumping graph...
43+
dumping params...
44+
dumping labels...
45+
resnet18_v1
46+
getting model...
47+
building...
48+
dumping lib...
49+
dumping graph...
50+
dumping params...
51+
dumping labels...
52+
```
53+
54+
### <a name="buildapk">Build APK</a>
55+
56+
We use [Gradle](https://gradle.org) to build. Please follow [the installation instruction](https://gradle.org/install) for your operating system.
57+
58+
Before you build the Android application, please refer to [TVM4J Installation Guide](https://github.com/apache/tvm/blob/main/jvm/README.md) and install tvm4j-core to your local maven repository. You can find tvm4j dependency declare in `app/build.gradle`. Modify it if it is necessary.
59+
60+
```
61+
dependencies {
62+
implementation fileTree(dir: 'libs', include: ['*.jar'])
63+
androidTestImplementation('androidx.test.espresso:espresso-core:3.2.0', {
64+
exclude group: 'com.android.support', module: 'support-annotations'
65+
})
66+
implementation 'androidx.appcompat:appcompat:1.4.0'
67+
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
68+
implementation 'com.google.android.material:material:1.5.0'
69+
implementation 'org.apache.tvm:tvm4j-core:0.0.1-SNAPSHOT'
70+
testImplementation 'junit:junit:4.13.2'
71+
72+
implementation "androidx.concurrent:concurrent-futures:1.0.0"
73+
implementation "androidx.camera:camera-core:1.0.0-beta01"
74+
implementation "androidx.camera:camera-camera2:1.0.0-beta01"
75+
implementation "androidx.camera:camera-view:1.0.0-alpha08"
76+
implementation "androidx.camera:camera-extensions:1.0.0-alpha08"
77+
implementation "androidx.camera:camera-lifecycle:1.0.0-beta01"
78+
}
79+
```
80+
81+
Now use Gradle to compile JNI, resolve Java dependencies and build the Android application together with tvm4j. Run following script to generate the apk file.
82+
83+
```bash
84+
export ANDROID_HOME=[Path to your Android SDK, e.g., ~/Android/sdk]
85+
cd apps/android_camera
86+
gradle clean build
87+
```
88+
89+
In `app/build/outputs/apk` you'll find `app-release-unsigned.apk`, use `dev_tools/gen_keystore.sh` to generate a signature and use `dev_tools/sign_apk.sh` to get the signed apk file `app/build/outputs/apk/release/tv8mdemo-release.apk`.
90+
91+
Upload `tv8mdemo-release.apk` to your Android device and install it:
92+
93+
```bash
94+
$ANDROID_HOME/platform-tools/adb install app/build/outputs/apk/release/tv8mdemo-release.apk
95+
```
96+
97+
If you see error:
98+
99+
adb: failed to install app/build/outputs/apk/release/tv8mdemo-release.apk:
100+
Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE:
101+
Package ml.apache.tvm.android.androidcamerademo signatures do not match the previously installed version; ignoring!]
102+
103+
Run uninstall first:
104+
105+
```bash
106+
$ANDROID_HOME/platform-tools/adb uninstall ml.apache.tvm.android.androidcamerademo
107+
```

apps/android_camera/app/build.gradle

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,47 @@
1717

1818
apply plugin: 'com.android.application'
1919

20+
task generateJniHeaders(type: Exec, description: 'Generate JNI Headers') {
21+
def headerPath = "${project.projectDir}/src/main/jni"
22+
def classPath = "${project.projectDir}/../../../jvm/core/target/*"
23+
def filePath = "${project.projectDir}/../../../jvm/core/src/main/java/org/apache/tvm/LibInfo.java"
24+
commandLine "javac", "-h", headerPath, "-classpath", classPath, filePath
25+
doLast {
26+
file("${headerPath}/org_apache_tvm_LibInfo.h").renameTo(file("${headerPath}/org_apache_tvm_native_c_api.h"))
27+
}
28+
}
29+
30+
task copyFiles(type: Copy, description: 'Copy Sources for ndk-build') {
31+
dependsOn "generateJniHeaders"
32+
def ndkFilesPath = "${project.projectDir}/../../../jvm/native/src/main/native"
33+
def srcPath = "${project.projectDir}/src/main/jni/"
34+
35+
from "${ndkFilesPath}/org_apache_tvm_native_c_api.cc", "${ndkFilesPath}/jni_helper_func.h"
36+
into srcPath
37+
}
38+
39+
task deleteLibs(type: Delete, description: "Delete Compiled Libraries") {
40+
dependsOn "copyFiles"
41+
def libsPath = "${project.projectDir}/src/main/libs"
42+
delete libsPath
43+
}
44+
2045
task buildJni(type: Exec, description: 'Build JNI libs') {
21-
commandLine 'sh', 'src/main/jni/build.sh'
46+
dependsOn "deleteLibs"
47+
def buildPath = "${project.projectDir}/src/main/jni"
48+
commandLine "ndk-build", "--directory", buildPath
2249
}
2350

2451
tasks.withType(JavaCompile) {
25-
//compileTask -> compileTask.dependsOn buildJni
52+
compileTask -> compileTask.dependsOn buildJni
2653
}
2754

2855
android {
29-
compileSdkVersion 29
56+
compileSdkVersion 31
3057
defaultConfig {
3158
applicationId "ml.apache.tvm.android.androidcamerademo"
3259
minSdkVersion 24
33-
targetSdkVersion 29
60+
targetSdkVersion 26
3461
renderscriptTargetApi 18
3562
renderscriptSupportModeEnabled true
3663
versionCode 1
@@ -53,21 +80,24 @@ android {
5380
sourceCompatibility JavaVersion.VERSION_1_8
5481
targetCompatibility JavaVersion.VERSION_1_8
5582
}
56-
buildToolsVersion = '29.0.3'
83+
84+
lintOptions {
85+
disable "Instantiatable" // MainActivity and RPCActivity must extend android.app.Activity
86+
}
5787
}
5888

5989
dependencies {
6090
implementation fileTree(dir: 'libs', include: ['*.jar'])
6191
androidTestImplementation('androidx.test.espresso:espresso-core:3.2.0', {
6292
exclude group: 'com.android.support', module: 'support-annotations'
6393
})
64-
implementation 'androidx.appcompat:appcompat:1.1.0'
65-
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
66-
implementation 'com.google.android.material:material:1.1.0'
67-
implementation 'org.apache.tvm:tvm4j-core:0.0.1-SNAPSHOT'
68-
testImplementation 'junit:junit:4.13'
94+
implementation 'androidx.appcompat:appcompat:1.4.0'
95+
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
96+
implementation 'com.google.android.material:material:1.5.0'
97+
implementation files('../../../jvm/core/target/tvm4j-core-0.0.1-SNAPSHOT.jar')
98+
testImplementation 'junit:junit:4.13.2'
6999

70-
implementation("androidx.concurrent:concurrent-futures:1.0.0")
100+
implementation "androidx.concurrent:concurrent-futures:1.0.0"
71101
implementation "androidx.camera:camera-core:1.0.0-beta01"
72102
implementation "androidx.camera:camera-camera2:1.0.0-beta01"
73103
// If you want to use the CameraX View class

0 commit comments

Comments
 (0)