Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 117 additions & 52 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,59 +38,124 @@ jobs:
MacOS:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Conda Build
shell: bash -l {0}
run: >-
conda build --output-folder=conda/pkg conda/recipe &&
conda install tvm -c ./conda/pkg
- name: Build iOS RPC
run: |
IOS_VERSION="14.0"
CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_SYSTEM_VERSION=${IOS_VERSION} \
-DCMAKE_OSX_SYSROOT=iphonesimulator \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
-DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON \
-DUSE_IOS_RPC=ON"

mkdir build-ios-simulator
cd build-ios-simulator
cmake .. ${CMAKE_FLAGS}
cmake --build . --target ios_rpc
- name: Test
shell: bash -l {0}
run: >-
python -m pytest -v tests/python/all-platform-minimal-test
- name: Test iOS RPC
shell: bash -l {0}
run: >-
python -m pip install tornado psutil cloudpickle &&
export PYTHONPATH=tests/python/contrib:${PYTHONPATH} &&
export BUNDLE_ID=org.apache.tvmrpc &&
export BUNDLE_PATH=build-ios-simulator/apps/ios_rpc/ios_rpc/src/ios_rpc-build/Release-iphonesimulator/tvmrpc.app &&
python -m pytest -v tests/python/contrib/test_rpc_server_device.py
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Conda Build
shell: bash -l {0}
run: >-
conda build --output-folder=conda/pkg conda/recipe &&
conda install tvm -c ./conda/pkg
- name: Build iOS RPC
run: |
IOS_VERSION="14.0"
CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_SYSTEM_VERSION=${IOS_VERSION} \
-DCMAKE_OSX_SYSROOT=iphonesimulator \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
-DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON \
-DUSE_IOS_RPC=ON"
mkdir build-ios-simulator
cd build-ios-simulator
cmake .. ${CMAKE_FLAGS}
cmake --build . --target ios_rpc
- name: Test
shell: bash -l {0}
run: >-
python -m pytest -v tests/python/all-platform-minimal-test
- name: Test iOS RPC
shell: bash -l {0}
run: >-
python -m pip install tornado psutil cloudpickle &&
export PYTHONPATH=tests/python/contrib:${PYTHONPATH} &&
export BUNDLE_ID=org.apache.tvmrpc &&
export BUNDLE_PATH=build-ios-simulator/apps/ios_rpc/ios_rpc/src/ios_rpc-build/Release-iphonesimulator/tvmrpc.app &&
python -m pytest -v tests/python/contrib/test_rpc_server_device.py

Windows:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Conda Build
shell: cmd /C call {0}
run: >-
conda build --output-folder=conda/pkg conda/recipe &&
conda install tvm -c ./conda/pkg
- name: Test
shell: cmd /C call {0}
run: >-
python -m pytest -v tests/python/all-platform-minimal-test
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Conda Build
shell: cmd /C call {0}
run: >-
conda build --output-folder=conda/pkg conda/recipe &&
conda install tvm -c ./conda/pkg
- name: Test
shell: cmd /C call {0}
run: >-
python -m pytest -v tests/python/all-platform-minimal-test

Android:
runs-on: Ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Set up java
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
- name: Build TVM
shell: bash -l {0}
run: |
mkdir build
cd build
../tests/scripts/task_config_build_jvm.sh .
cmake ..
make
- name: Build TVM4J
run: |
make jvmpkg
- name: Build android_rpc
working-directory: apps/android_rpc
run: |
export PATH="${ANDROID_NDK_HOME}:$PATH"
gradle clean build
- name: Upload android_rpc APK
uses: actions/upload-artifact@v2
with:
name: android_rpc-debug.apk
path: ./apps/android_rpc/app/build/outputs/apk/debug/app-debug.apk
- name: Build android_deploy
working-directory: apps/android_deploy
run: |
export PATH="${ANDROID_NDK_HOME}:$PATH"
gradle clean build
- name: Upload android_deploy APK
uses: actions/upload-artifact@v2
with:
name: android_deploy-debug.apk
path: ./apps/android_deploy/app/build/outputs/apk/debug/app-debug.apk
- name: Build android_camera
working-directory: apps/android_camera
run: |
mkdir -p app/src/main/assets/models/
export TVM_NDK_CC=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang++
export TVM_HOME=~/work/tvm/tvm
export PYTHONPATH=$TVM_HOME/python:${PYTHONPATH}
python3 ${TVM_HOME}/python/gen_requirements.py
pip3 install -r ${TVM_HOME}/python/requirements/core.txt
cd models
pip3 install -r requirements.txt
python3 prepare_model.py
cd ..
export PATH="${ANDROID_NDK_HOME}:$PATH"
gradle clean build
- name: Upload android_camera APK
uses: actions/upload-artifact@v2
with:
name: android_camera-debug.apk
path: ./apps/android_camera/app/build/outputs/apk/debug/app-debug.apk
129 changes: 104 additions & 25 deletions apps/android_camera/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,107 @@
[//]: # Licensed to the Apache Software Foundation (ASF) under one
[//]: # or more contributor license agreements. See the NOTICE file
[//]: # distributed with this work for additional information
[//]: # regarding copyright ownership. The ASF licenses this file
[//]: # to you under the Apache License, Version 2.0 (the
[//]: # "License"); you may not use this file except in compliance
[//]: # with the License. You may obtain a copy of the License at
[//]: #
[//]: # http://www.apache.org/licenses/LICENSE-2.0
[//]: #
[//]: # Unless required by applicable law or agreed to in writing,
[//]: # software distributed under the License is distributed on an
[//]: # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
[//]: # KIND, either express or implied. See the License for the
[//]: # specific language governing permissions and limitations
[//]: # under the License.

Android Camera Demo Sample App
==============================

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.

Converting Models
-----------------
<!--- Licensed to the Apache Software Foundation (ASF) under one -->
<!--- or more contributor license agreements. See the NOTICE file -->
<!--- distributed with this work for additional information -->
<!--- regarding copyright ownership. The ASF licenses this file -->
<!--- to you under the Apache License, Version 2.0 (the -->
<!--- "License"); you may not use this file except in compliance -->
<!--- with the License. You may obtain a copy of the License at -->

<!--- http://www.apache.org/licenses/LICENSE-2.0 -->

<!--- Unless required by applicable law or agreed to in writing, -->
<!--- software distributed under the License is distributed on an -->
<!--- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -->
<!--- KIND, either express or implied. See the License for the -->
<!--- specific language governing permissions and limitations -->
<!--- under the License. -->


# Android Camera Demo Sample App

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.

You will need JDK, [Android NDK](https://developer.android.com/ndk) and an Android device to use this.

## Build and Installation

### <a name="preparemodels">Prepare Models</a>

The `models/prepare_models.py` script provides a example flow for dumping model
parameter files for use by the app.

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++]`
2. Switch to the script directory: `cd models`
3. Run script: `python3 prepare_model.py`

#### Sample output
```
mobilenet_v2
getting model...
building...
dumping lib...
dumping graph...
dumping params...
dumping labels...
resnet18_v1
getting model...
building...
dumping lib...
dumping graph...
dumping params...
dumping labels...
```

### <a name="buildapk">Build APK</a>

We use [Gradle](https://gradle.org) to build. Please follow [the installation instruction](https://gradle.org/install) for your operating system.

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.

```
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation('androidx.test.espresso:espresso-core:3.2.0', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.google.android.material:material:1.5.0'
implementation 'org.apache.tvm:tvm4j-core:0.0.1-SNAPSHOT'
testImplementation 'junit:junit:4.13.2'

implementation "androidx.concurrent:concurrent-futures:1.0.0"
implementation "androidx.camera:camera-core:1.0.0-beta01"
implementation "androidx.camera:camera-camera2:1.0.0-beta01"
implementation "androidx.camera:camera-view:1.0.0-alpha08"
implementation "androidx.camera:camera-extensions:1.0.0-alpha08"
implementation "androidx.camera:camera-lifecycle:1.0.0-beta01"
}
```

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.

```bash
export ANDROID_HOME=[Path to your Android SDK, e.g., ~/Android/sdk]
cd apps/android_camera
gradle clean build
```

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`.

Upload `tv8mdemo-release.apk` to your Android device and install it:

```bash
$ANDROID_HOME/platform-tools/adb install app/build/outputs/apk/release/tv8mdemo-release.apk
```

If you see error:

adb: failed to install app/build/outputs/apk/release/tv8mdemo-release.apk:
Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE:
Package ml.apache.tvm.android.androidcamerademo signatures do not match the previously installed version; ignoring!]

Run uninstall first:

```bash
$ANDROID_HOME/platform-tools/adb uninstall ml.apache.tvm.android.androidcamerademo
```
52 changes: 41 additions & 11 deletions apps/android_camera/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,47 @@

apply plugin: 'com.android.application'

task generateJniHeaders(type: Exec, description: 'Generate JNI Headers') {
def headerPath = "${project.projectDir}/src/main/jni"
def classPath = "${project.projectDir}/../../../jvm/core/target/*"
def filePath = "${project.projectDir}/../../../jvm/core/src/main/java/org/apache/tvm/LibInfo.java"
commandLine "javac", "-h", headerPath, "-classpath", classPath, filePath
doLast {
file("${headerPath}/org_apache_tvm_LibInfo.h").renameTo(file("${headerPath}/org_apache_tvm_native_c_api.h"))
}
}

task copyFiles(type: Copy, description: 'Copy Sources for ndk-build') {
dependsOn "generateJniHeaders"
def ndkFilesPath = "${project.projectDir}/../../../jvm/native/src/main/native"
def srcPath = "${project.projectDir}/src/main/jni/"

from "${ndkFilesPath}/org_apache_tvm_native_c_api.cc", "${ndkFilesPath}/jni_helper_func.h"
into srcPath
}

task deleteLibs(type: Delete, description: "Delete Compiled Libraries") {
dependsOn "copyFiles"
def libsPath = "${project.projectDir}/src/main/libs"
delete libsPath
}

task buildJni(type: Exec, description: 'Build JNI libs') {
commandLine 'sh', 'src/main/jni/build.sh'
dependsOn "deleteLibs"
def buildPath = "${project.projectDir}/src/main/jni"
commandLine "ndk-build", "--directory", buildPath
}

tasks.withType(JavaCompile) {
//compileTask -> compileTask.dependsOn buildJni
compileTask -> compileTask.dependsOn buildJni
}

android {
compileSdkVersion 29
compileSdkVersion 31
defaultConfig {
applicationId "ml.apache.tvm.android.androidcamerademo"
minSdkVersion 24
targetSdkVersion 29
targetSdkVersion 26
renderscriptTargetApi 18
renderscriptSupportModeEnabled true
versionCode 1
Expand All @@ -53,21 +80,24 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildToolsVersion = '29.0.3'

lintOptions {
disable "Instantiatable" // MainActivity and RPCActivity must extend android.app.Activity
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation('androidx.test.espresso:espresso-core:3.2.0', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0'
implementation 'org.apache.tvm:tvm4j-core:0.0.1-SNAPSHOT'
testImplementation 'junit:junit:4.13'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.google.android.material:material:1.5.0'
implementation files('../../../jvm/core/target/tvm4j-core-0.0.1-SNAPSHOT.jar')
testImplementation 'junit:junit:4.13.2'

implementation("androidx.concurrent:concurrent-futures:1.0.0")
implementation "androidx.concurrent:concurrent-futures:1.0.0"
implementation "androidx.camera:camera-core:1.0.0-beta01"
implementation "androidx.camera:camera-camera2:1.0.0-beta01"
// If you want to use the CameraX View class
Expand Down
Loading