前言
因为NDK在更新18版本以后就取消了GUN的支持,gnustl也被移除(参考https://github.com/android-ndk/ndk/wiki/Changelog-r18),而opencv的安卓版本默认是使用gunstl编译的(大家可以去看源码文件夹下platforms\android里的android.toolchain.cmake),所以在更新了NDK后,直接编译原来的工程会出现有的函数只有声明没有实现的情况。很多人都选择了降级NDK版本,但是强迫症表示忍不了不能用最新版本,果断升级。
我是在windows10下进行的,用的是opencv3.4.2(用着最“舒服”的版本)源码进行编译,别的版本暂时没有试过,应该是类似的,可以举一反三,我猜。
NDK更新后的剩下一个clang/clang++编译器,我们只需要用它重新编译一次opencv的源码即可。
参考文献:
Windows下编译opencv4android+opencv_contrib_Xiao19950820的博客-CSDN博客
Android NDK 18 OPENCV 升级问题_fff2666的专栏-CSDN博客
零、遇到的坑
我尝试使用NDK19去编译opencv3.4.2,在build到100%的时候会报错,但是同样的方法使用NDK17去编译就没问题,编译出的库放到NDK19下使用也不会报错。不知道是不是3.4.2不支持那么新的NDK。更新库以后如果原来的安卓工程编不过就clean一下、然后重新链接一次C++部分。
另外用clang编出的库非常大,不知道为什么,原来在10兆左右,这个编出来有100兆。我做了一个简单的demo发现库大小并没有影响APP大小,所以就暂且不管了吧。
然后就是,对于3.4.X版本(3.4.2和3.4.6都试过了),当勾选编译CXX版本后,在用install指令的时候会自动又用VS编译器重新build一次,这会导致一些文件找不到,但是编译4.1.0这个本身就是CXX版本的时候却没发现这个问题,这就很神奇了。
一、环境配置
这一步类似Windows下编译opencv4android+opencv_contrib_Xiao19950820的博客-CSDN博客这篇文章的内容,这里也不再赘述了(懒得再装一次环境)。总体来说,我们需要安装cmake、mingw、ant并配置好环境变量。
另外还有python和LLVM,因为我这里本身有安装这两样东西,所以我不太确定是否是必要的。这两个大家可以去官网下载:
Download Python | Python.org
LLVM Download Page
LLVM选择Pre-Built Binaries的对应版本即可,他们在安装的时候都会有是否添加进环境变量的设置,我选择了添加。
二、源码下载
下载源码方法很多,我是直接去github下载:https://github.com/opencv
注意,尽量不要下载master版本,选择我们需要的版本下载。
如果需要contrib库,需要与下载与opencv库相同的版本,否则编译会报错噢~
下载完后解压出来就完事了。
这是我的文件夹结构。
三、编译
值得注意的一点是,3.4.2版本只支持Android SDK Tools 版本为25.2.5。这个需要自行去下载(https://dl.google.com/android/repository/tools_r25.2.5-windows.zip)。别的OpenCV版本不知道有没有这样的问题。下载后直接替换掉(先删掉原来的,如果不放心请备份一份)SDK目录下的tools文件夹就可以了
首先,打开cmake-gui,图形化界面操作起来方便很多(我是这样认为的)。
在图中1处填入存放opencv 源码的路径,2处填入生成后的结果存放路径。
然后点击“add entry”添加一些标志位。
插一句,要添加哪些标志位由使用的工具链决定,大多数教程都会让我们使用opencv源码中的工具链,如果这样的话是无法适配最新的NDK的。所以我们这里要选择使用NDK中自带的工具链。工具链位于ndk-bundle\build\cmake\android.toolchain.cmake。
要添加的有ANDROID_ABI,这个根据需求添加自己需要的ABI
然后是ANDROID_STL,因为gunstl已经不被支持,这里使用c++_shared或c++_static都可以。
PS:如果Configure后提示没有Android SDK路径,那么再添加一个ANDROID_HOME ,值为SDK的路径,如:C:\software\Android_SDK
添加完后点击“Configure”按钮,选择mingw作为生成工具,然后选择使用工具链交叉编译,点击“Next”。
之后会出现选择工具链,这里我们选择NDK自带的工具链,它在NDK目录下的/build/cmake/android.toolchain.cmake。如果你使用的是Android Studio安装的SDK,NDK目录就是SDK目录下的ndk-bundle,其他的我就不太清楚了。然后点击Finish。
可以发现,cmake已经自动将编译器选择为clang了
PS:如果遇到下面这样的错误:
Android SDK: Can't build Android projects as requested by BUILD_ANDROID_PROJECTS=ON variable.
完整错误如下:
CMake Error at cmake/android/OpenCVDetectAndroidSDK.cmake:184 (message):
Android SDK: Can't build Android projects as requested by
BUILD_ANDROID_PROJECTS=ON variable.
Use BUILD_ANDROID_PROJECTS=OFF to prepare Android project files without
building them
Call Stack (most recent call first):
CMakeLists.txt:657 (include)
就在search一栏中搜索BUILD_ANDROID_PROJECTS,然后把钩去掉,或者去掉BUILD_JAVA和BUILD_ANDROID_EXAMPLES的钩即可。
后面选择自己需要的选项,然后点击“Configure”,直到没有红底的选项后,点击“Generate”。
最后进入命令行工具CMD,进入之前第三节中第一张图的红框2处填入的地址。
cd(空格)(第三节中第一张图的红框2处填入的地址)
ps:如果地址不是在c盘,需要先用盘符进入相应的盘,比如我的在d盘,就先输入d:回车,然后再用cd。
使用mingw32-make指令进行生成,这个过程有点久。
如果出现下面这样的错误,可能是NDK版本过高,降级NDK版本即可。
bionic/libc/include/bits/fortify/stdio.h:76: error: undefined reference to '__vsnprintf_chk'
bionic/libc/include/bits/fortify/unistd.h:159: error: undefined reference to '__read_chk'
bionic/libc/include/bits/fortify/unistd.h:174: error: undefined reference to '__write_chk'
bionic/libc/include/bits/fortify/unistd.h:174: error: undefined reference to '__write_chk'
之后再用mingw32-make install命令安装就完事了。
结果就在这个路径下的install/sdk/native文件夹里面,包括头文件和库文件。
至此,就完成了编译工作了。
第一次写文章,语言组织不好,请见谅。如果遇到什么问题欢迎咨询。