前言:
如果想借用TNN自己写一个库(比如exp.so), 通常我们选用TNN的静态库(libTNN.a),
因为使用静态库后自己生成的库文件就一个exp.so
如果使用动态库(libTNN.so)那么自己生成的库文件就有两个了: libTNN.so和exp.so
环境:
源码: https://github.com/Tencent/TNN/archive/refs/tags/v0.3.0.zip
c++编译器: "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
cmake: cmake-3.20.4-windows-x86_64.zip
android ndk: android-ndk-r20b-windows-x86_64.zip
1.解压/安装上面各个包
2.新建xxx.bat, 写入以下内容:(以下编译的是arm64-v8a, 静态库)
::功能: 在windows下编译tnn for android
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
::set VS_CL_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\Hostx86\x64
::set PATH=%PATH%;%VS_CL_PATH%
set TNN_ROOT=D:\code\TNN\TNN-0.3.0
set CMAKE_BIN=D:\development_kits\cmake-3.20.4-windows-x86_64\bin
set ANDROID_NDK=D:\development_kits\android-ndk-r20b
::set ABIA32=armeabi-v7a
set ABIA32=arm64-v8a
:: SHARED_LIB ON表示动态库, OFF表示静态库
set SHARED_LIB=OFF
set PATH=%PATH%;%CMAKE_BIN%
if "%SHARED_LIB%" == "ON" (
set MODE=share
) else if "%SHARED_LIB%" == "OFF" (
set MODE=static
) else (
echo unknown model with SHARED_LIB: %SHARED_LIB%. exit.
pause
exit
)
cd %TNN_ROOT%
mkdir build_android
cd build_android
mkdir %MODE%
cd %MODE%
mkdir %ABIA32%
cd %ABIA32%
cmake -G "Unix Makefiles" ^
-DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK%/build/cmake/android.toolchain.cmake ^
-DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%/prebuilt/windows-x86_64/bin/make.exe" ^
-DDEBUG:BOOL=OFF ^
-DANDROID_ABI="%ABIA32%" ^
-DANDROID_STL=c++_static ^
-DANDROID_NATIVE_API_LEVEL=android-14 ^
-DANDROID_TOOLCHAIN=clang ^
-DBUILD_FOR_ANDROID_COMMAND=true ^
-DTNN_CPU_ENABLE:BOOL=ON ^
-DTNN_ARM_ENABLE:BOOL=ON ^
-DTNN_HUAWEI_NPU_ENABLE:BOOL=OFF ^
-DTNN_OPENCL_ENABLE:BOOL=ON ^
-DTNN_BENCHMARK_MODE:BOOL=OFF ^
-DTNN_TEST_ENABLE:BOOL=ON ^
-DTNN_OPENMP_ENABLE:BOOL=ON ^
-DSHARING_MEM_WITH_OPENGL=0 ^
-DTNN_BUILD_SHARED:BOOL=%SHARED_LIB% %TNN_ROOT%
cmake --build . -j4
cmd.exe /k
3.双击编译成功
4.总结
1.用的是vs2019的c++编译器, vs2017 vs2013应该也行
2.cmake指令选项参考官方scripts/build_android.sh
3.目前只测试arm64-v8a成功, 对于armeabi-v7a平台(属于32位arm), 不知道能不能用, 可能需要搭配32位的vs编译器(vcvars32.bat)?
android studio环境
android studio: 4.2.2
buildToolsVersion “30.0.2”
ndkVersion "20.0.5594570"
以上buildToolsVersion和ndkVersion最好在build.gradle中指明:
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
// ndkVersion "21.4.7075529" // android studio 4.2 默认ndk版本, 搭配android-ndk-r20b生成的libTNN.a build成功报警告, run app失败
ndkVersion "20.0.5594570" // 搭配android-ndk-r20b生成的libTNN.a build成功报警告, run app成功
// ndkVersion "16.1.4479499" // 搭配android-ndk-r20b生成的libTNN.a build失败
...
}
1.新建android studio native c++工程
2.写好各种所需要的java和cpp代码
3.在CMakeLists.txt中加入对TNN链接库的链接和头文件引用
引用头文件:
include_directories(${TNN_ROOT}/include)
只针对arm64-v8a和armeabi-v7a平台(TNN android只编译了这两种平台):
if((ANDROID_ABISTREQUAL"arm64-v8a")OR(ANDROID_ABISTREQUAL"armeabi-v7a"))
导入TNN库:
#=== 导入TNN库libTNN.so/libTNN.a
add_library (tnn ${LIB_MODE} IMPORTED)
if("${LIB_MODE}" STREQUAL "SHARED")
set(LIB_TNN_FILE libTNN.so)
endif()
if("${LIB_MODE}" STREQUAL "STATIC")
set(LIB_TNN_FILE libTNN.a)
endif()
set_target_properties(tnn PROPERTIES IMPORTED_LOCATION ${TNN_ROOT}/build_android/${LIB_MODE}/${ANDROID_ABI}/${LIB_TNN_FILE})
链接TNN库:
#=== 将TNN库与目标文件链接. -fopenmp和-Wl,--whole-archive tnn -Wl,--no-whole-archive是gcc的编译选项
#=== 添加动态链接库jnigraphics解决AndroidBitmap_getInfo报错
#=== 添加fopenmp解决undefined reference to '__kmpc_fork_call错误 参考https://github.com/Tencent/ncnn/issues/292
if("${LIB_MODE}" STREQUAL "STATIC")
target_link_libraries( # Specifies the target library.
native-lib
-ljnigraphics
-fopenmp
-Wl,--whole-archive tnn -Wl,--no-whole-archive
tnn)
endif()
if("${LIB_MODE}" STREQUAL "SHARED")
target_link_libraries( # Specifies the target library.
native-lib
-ljnigraphics
tnn)
endif()
完整的CMakeLists.txt:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.10.2)
# Declares and names the project.
project("tnn")
set(TNN_ROOT D:/code/TNN/TNN-0.3.0)
include_directories(${TNN_ROOT}/include)
include_directories(${CMAKE_SOURCE_DIR}/)
set(LIB_MODE STATIC) # STATIC表示使用libTNN.a, SHARED表示使用libTNN.so
if((ANDROID_ABI STREQUAL "arm64-v8a") OR (ANDROID_ABI STREQUAL "armeabi-v7a"))
#=== 导入TNN库libTNN.so/libTNN.a
add_library (tnn ${LIB_MODE} IMPORTED)
if("${LIB_MODE}" STREQUAL "SHARED")
set(LIB_TNN_FILE libTNN.so)
endif()
if("${LIB_MODE}" STREQUAL "STATIC")
set(LIB_TNN_FILE libTNN.a)
endif()
set_target_properties(tnn PROPERTIES IMPORTED_LOCATION ${TNN_ROOT}/build_android/${LIB_MODE}/${ANDROID_ABI}/${LIB_TNN_FILE})
#=== 编译写好的接口, 生成链接文件
file(GLOB_RECURSE TNN_WRAPPER_SRCS ${CMAKE_SOURCE_DIR}/*.cc) # 包含TNN的代码
file(GLOB_RECURSE OTHER_SRCS ${CMAKE_SOURCE_DIR}/*.cpp) # 不包含TNN的代码
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${TNN_WRAPPER_SRCS} ${OTHER_SRCS})
#=== 将TNN库与目标文件链接. -fopenmp和-Wl,--whole-archive tnn -Wl,--no-whole-archive是gcc的编译选项
#=== 添加动态链接库jnigraphics解决AndroidBitmap_getInfo报错
#=== 添加fopenmp解决undefined reference to '__kmpc_fork_call错误 参考https://github.com/Tencent/ncnn/issues/292
if("${LIB_MODE}" STREQUAL "STATIC")
target_link_libraries( # Specifies the target library.
native-lib
-ljnigraphics
-fopenmp
-Wl,--whole-archive tnn -Wl,--no-whole-archive
tnn)
endif()
if("${LIB_MODE}" STREQUAL "SHARED")
target_link_libraries( # Specifies the target library.
native-lib
-ljnigraphics
tnn)
endif()
else()
#=== 编译不包含TNN的接口, 生成链接文件
file(GLOB_RECURSE OTHER_SRCS ${CMAKE_SOURCE_DIR}/native-lib.cpp) # 不包含TNN的代码
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${OTHER_SRCS})
endif()
#=== log-lib是工程建立后默认就有的
#=== 似乎用来在android中打印cpp代码的log
#=== 参考https://stackoverflow.com/questions/4629308/any-simple-way-to-log-in-android-ndk-code
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
关于android studio下调用tnn的so/a库详细内容可以看这里https://blog.csdn.net/ying86615791/article/details/119828457