在 android 交叉编译的时候使用 find_lirary 搜索三方库的时候无法找到对应的so文件,但是对应的path中是有的。
ind_library(ORT_LIB onnxruntime ${ORT_LIB_PATH} NO_DEFAULT_PATH)
写了下面的单侧,是可以正常找到so的。但是用的是Linux的编译环境,非Android ndk 交叉编译。
cmake_minimum_required(VERSION 3.23)
project(test)
find_library(
METADX1_LIB
NAMES libmdx1host.so.2
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/meta-dx1/sdk/builds/debug/
PATH_SUFFIXES lib
NO_DEFAULT_PATH
)
message(STATUS "METADX1\_LIB = ${METADX1\_LIB}")
指定so的绝对路径是可以work,linux编译也可以work,那这个时候就想如何debug呢?
这里先说下解决方法,在CMakeLists.txt 中加入:
if(ANDROID)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
endif()
有兴趣的可以看下后面的详细内容。
CMAKE_FIND_DEBUG_MODE
The CMAKE_FIND_DEBUG_MODE variable was introduced to print extra find call information during the cmake run to standard error. Output is designed for human consumption and not for parsing.
注意 CMake 3.17 后才支持
So you pass either -DCMAKE_FIND_DEBUG_MODE=ON or --debug-find to your CMake command.
Here is an example output when searching for libFOO:
find_library considered the following locations:
/usr/local/lib64/(lib)FOO(\.so|\.a)
/usr/local/lib/(lib)FOO(\.so|\.a)
/usr/local/lib64/(lib)FOO(\.so|\.a)
/usr/local/lib/(lib)FOO(\.so|\.a)
/usr/local/lib64/(lib)FOO(\.so|\.a)
/usr/local/(lib)FOO(\.so|\.a)
/usr/lib64/(lib)FOO(\.so|\.a)
/usr/lib/(lib)FOO(\.so|\.a)
/usr/lib64/(lib)FOO(\.so|\.a)
/usr/lib/(lib)FOO(\.so|\.a)
/usr/lib64/(lib)FOO(\.so|\.a)
/usr/(lib)FOO(\.so|\.a)
/lib64/(lib)FOO(\.so|\.a)
/lib/(lib)FOO(\.so|\.a)
/opt/(lib)FOO(\.so|\.a)
先升级下cmake的版本
pip install cmake
配置上-DCMAKE_FIND_DEBUG_MODE=ON并用ndk交叉编译,log如下:
VAR: ORT_LIB
NAMES: "onnxruntime"
Documentation: Path to a library.
Framework
Only Search Frameworks: 0
Search Frameworks Last: 0
Search Frameworks First: 0
AppBundle
Only Search AppBundle: 0
Search AppBundle Last: 0
Search AppBundle First: 0
NO_DEFAULT_PATH Enabled
find_library considered the following locations:
/workspace/android-sdk/android-ndk-r25c/workspace//paddle/FastDeploy/build/Android/arm64-v8a-api-21/third\_libs/install/onnxruntime/lib/(lib)onnxruntime(\.so|\.a)
/workspace//android-sdk/android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86\_64/sysroot/workspace//paddle/FastDeploy/build/Android/arm64-v8a-api-21/third\_libs/install/onnxruntime/lib/(lib)onnxruntime(\.so|\.a)
可以看到搜索的路径带上了ndk的路径prefix,即/workspace/android-sdk/android-ndk-r25c。
因为是交叉编译,必须告诉CMake,它允许在工具链指定的其他地方使用库(在例子中,在Android SDK目录之外的其他地方)。
可以这样做:
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
Cross Compiling for Linux
https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
一个典型的Linux交叉编译工具链包含如下内容:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSROOT /home/devel/rasp-pi-rootfs)
set(CMAKE_STAGING_PREFIX /home/devel/stage)
set(tools /home/devel/gcc-4.7-linaro-rpi-gnueabihf)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
- CMAKE_SYSTEM_NAME
是构建目标平台的CMake-identifier。
- CMAKE_SYSTEM_PROCESSOR
是目标架构的CMake-identifier。
- CMAKE_SYSROOT
是可选的,如果有sysroot可用,可以指定。
- CMAKE_STAGING_PREFIX
也是可选的。它可以用于指定要安装到的主机上的路径。CMAKE_INSTALL_PREFIX始终是运行时安装位置,即使在交叉编译时也是如此。
- CMAKE__COMPILER
变量可以设置为完整路径,或者设置为在标准位置搜索的编译器名称。对于不支持链接没有自定义标志或脚本的二进制文件的工具链,可以将CMAKE_TRY_COMPILE_TARGET_TYPE变量设置为STATIC_LIBRARY,告诉CMake在检查时不要尝试链接可执行文件。
在所有情况下,CMake find_*命令会在sysroot和CMAKE_FIND_ROOT_PATH条目中查找,以及在主机系统根前缀中查找。虽然这可以根据具体情况进行控制,但在交叉编译时,排除在宿主或目标中查找特定工件是有用的 。
通常 includes, libraries 和 packages应该在目标系统前缀中找到,而必须作为构建的一部分运行的可执行文件应该只在主机上找到,而不是在目标上。这就是CMAKE_FIND_ROOT_PATH_MODE_*变量的作用。
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
这个变量控制CMAKE_FIND_ROOT_PATH和CMAKE_SYSROOT是否被find_library()使用。
- 如果设置为
ONLY,则只搜索CMAKE_FIND_ROOT_PATH中的根。 - 如果设置为
NEVER,则CMAKE_FIND_ROOT_PATH中的根将被忽略,只使用主机系统根。 - 如果设置为
BOTH,则搜索主机系统路径和CMAKE_FIND_ROOT_PATH中的路径。
参考文献
- https://stackoverflow.com/questions/49431342/debug-cmake-find-library
- https://stackoverflow.com/questions/46055431/cmake-on-android-find-library-fail-to-find-with-custom-path
- https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
- https://cmake.org/cmake/help/latest/variable/CMAKE\_FIND\_ROOT\_PATH\_MODE\_LIBRARY.html?highlight=cmake\_find\_root\_path\_mode\_library
