TVM RPC Android 部署踩坑
##
先说结论
环境:Ubuntu 18.04 LTS (非虚拟机)
手机:Xiaomi Mi 5s, 3GB RAM, 64GB ROM
系统:原生 Android 10
遇到问题:android_rpc 无法编译部署
解决方法:核心思路是分析 gradle task 执行顺序,分析相关脚本,检查环境变量。这个问题需要具体情况具体分析,请仔细查看本文【问题解决】部分的相关描述。
##
部署 android_rpc
按照官方教程来走,先是基于源代码安装 TVM 库,安装之前要把 LLVM 装好。
然后安装 Gradle,Maven
然后编译 TVM4J
编译好之后我开始按照官方教程尝试部署 apps/android_rpc 这个项目
因为上次部署 TVM 的经验教训让我知道了严格按照官方教程走的重要性。
只可惜,这次就算按照官方教程来部署,得到的结果依然是:
失败。
##
踩坑
Gradle 版本不对,Ubuntu 18.04 默认给安装的是 3.x 版本,后来添加的源,upgrade 一下才可以。
然后又遇到了你懂的特色互联网防火墙的问题:Maven 下载速度特别慢。
解决了网络的问题之后,我心想能不能把项目丢到 AndroidStudio 里面跑啊,然后我就试了一下
于是
,
给自己带来了另一个坑
Android Studio 推荐我更新 Gradle
我手贱点了更新
然后版本号对不上了
搞了半天踩意识到是自己手贱更新了Gradle。
。
。
。
折腾了好长一段时间,遇到了新的问题:
cannot find class file 'org.apache.tvm.LibInfo'
叼,烦死了。
。
我无论怎么 make clean
都不行,
然后我重新把 TVM 编译了一遍(我真是傻逼)
clean 了一下,make 了一下,编译完了
依!然!报!错!
折腾了好长一段时间,到了晚上12点,用官方提供的工具怎么也解决不了问题,
Google 了一次又一次,全是失败告终。
##
灵机一动
配置这么大型的项目,而且网上没有多少参考资料,搜索也几乎很难找到结果。手中的设备千差万别,想要真正部署起来真的太麻烦了。在我快疯了的时候,突然想到:草!我干嘛不看看他的脚本怎么写的呢?
说干就干,我在src/main/jni/build.sh
这个脚本里发现了这么一段话:
javah -o $CURR_DIR/org_apache_tvm_native_c_api.h -cp "$ROOT_DIR/jvm/core/target/*" org.apache.tvm.LibInfo exit -1
没错,就是这句话⬆️执行失败导致 exit -1
,在这句话前面还设置了一堆环境变量:
PATH="$PATH:/usr/local/bin"
CURR_DIR=$(cd `dirname $0`; pwd)
ROOT_DIR="$CURR\_DIR/../../../../../.."
我把脚本里的命令都打到 bash 里,然后一步步运行,
你猜怎么着?
,
,
,
报错了!(草)
然后我就查这个 jni 的用法,查到了之后,发现,还是报错
为什么呢?环境变量有问题吗
果然有问题。
##
问题解决
(上面的那些就是发发牢骚,这里才是解决问题的部分)
我不想继续描述我是怎么发现这个问题的了,就是作出假设 -> 一步步的推翻自己的假设 -> 反馈思考 -> 做出新的假设
重复上面的过程直到问题解决或者我放弃思考。
到处翻,发现 android_rpc 项目中的 build.gradle 里面指定了一个 task:(其实是报错给我说的这个 build.gradle 出了错)
task buildJni(type: Exec, description: 'Build JNI libs') {
commandLine 'sh', 'src/main/jni/build.sh'
}
这个 task 的意思是执行 build.sh
这个 script (刚才我们发现问题的那个脚本)
,
但是这个 script 里面的 javah 那句话(JNI的命令)会提示找不到 class file ‘org.apache.tvm.LibInfo’
奇怪的是 jar 包里有 LibInfo.class
这个文件,而且我去看了一下 tvm/jvm/core
文件夹里面,也是有 LibInfo.java
的,所以不应该是我们的包的问题,应该是路径什么的出了错。
把 build.sh
里面的变量打印出来发现,如果我在 tvm/apps/android_rpc/
这个工作目录里,执行 gradle clean build
的话,$ROOT_DIR 的值并不是它应该有的值,$ROOT_DIR的值应该是 tvm/apps/android_rpc, 也就是这个项目的路径。然而我把这个值打印出来发现, $ROOT_DIR
的值是系统的根目录,在根目录里肯定找不到 LibInfo 啊!
在 android_rpc/app/src/main/jni
这个工作目录执行的话, ROOT\DIR="$CURR_DIR/../../../../../.."
正好跳到 android_rpc 里
然后我手工执行了这个sh,在 build.gradle 里把这个行为给注释掉了
成功!
##
总结
其实一开始,在 android_rpc 这个目录里执行 gradle clean build
是可以成功编译出文件的,但是在后面签名的时候给我报了个无法找到什么什么类的错误,然后我决定编译 android_deploy 试试,发现成功了,签名也正常,在 Android 10 手机上也可以正常运行,我就觉得肯定是这个项目的问题。
后来我再次尝试编译 android_rpc 的时候,出现了文章中描述的问题,技艺不精,导致这么长时间才解决这个问题,期间也查阅了大量的资料,中途也想过放弃,但是还是坚持下来了。最终把问题分析过程以及思路整理成这篇文章,希望后人遇到相关问题可以通过这篇文章节约大量时间。