如何告诉 CMake(通过 externalNativeBuild 调用)在哪里寻找库?
Posted
技术标签:
【中文标题】如何告诉 CMake(通过 externalNativeBuild 调用)在哪里寻找库?【英文标题】:How to tell CMake (invoked through externalNativeBuild) where to look for libraries? 【发布时间】:2021-05-26 02:52:06 【问题描述】:我正在开发一个支持 Linux 和 android 的多平台项目。代码多为C; Android 端口有一个用于特定平台部分的 Java 包装器,它调用本机代码部分来实现核心功能。
在 Linux 上,我们使用 CMake 构建此项目,然后使用 make。对于 Android,我们基本上使用 Gradle 并通过 externalNativeBuild
调用 CMake。 CMakeFile.txt
可以通过简单的if (ANDROID)
检测 Android 构建,让我们能够
该项目依赖于一些标准库,我们在CMakeLists.txt
中使用以下内容检测到:
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules ( FOO foo-42.0 )
if (FOO_FOUND)
set(HAVE_FOO 1)
include_directories($FOO_INCLUDE_DIRS)
# …
在为 Android 构建时,这不会为主机操作系统(位于 /usr/include/
下方)而不是为 Android (位于 $NDK/sysroot
下方)选择任何内容或库。 (注意$NDK
只是表示NDK路径,不一定是环境变量。)
根据this post,pkg-config
依赖于一堆环境变量来确定在哪里寻找库,即CMAKE_SYSROOT
、PKG_CONFIG_DIR
、PKG_CONFIG_LIBDIR
和PKG_CONFIG_SYSROOT_DIR
。我检查了它们,它们是空的(或未设置)。
使用 gradle/NDK/CMake 工具链,我怎样才能将正确的变量传递给 CMake,或者让它找到 NDK 为其提供标头的库?
【问题讨论】:
【参考方案1】:有两种选择:
-
如果预建库安装在托管操作系统上(例如,我们使用
docker image
,包括所有已编译和安装的预建库和其他先决条件 - SDK、NDK、AndroidStudio 等),您需要提供@987654323 @
libraries
、includes
和 cmake configs
的安装位置:
list(APPEND CMAKE_FIND_ROOT_PATH $THIRDPARTY_DIR/$THIRDPARTY_ANDROID_PLATFORM/$ANDROID_ABI/boost)
-
如果未安装预构建,您需要提供
Find<module>.cmake
,例如FindBoost.cmake
来服务find_package(Boost)
(这里有一个example 说明它的可能方式,这个项目也使用了多平台部件)。
【讨论】:
谢谢,但问题不在于捆绑预建库,而在于使用 Android 附带的库(例如标准 C 库)并确保 CMake 找到正确的头文件。 没关系,算法是一样的,所以Android(NDK)自带的库不提供*config.cmake
,所以要支持find_package()
,需要提供Find<>.cmake
无需支持,您可以使用 find_library
与 NDK 一起使用或直接链接所需的库,例如:target_link_libraries(native-lib log)
。【参考方案2】:
NDK 路径可用于 gradle 为 android.ndkDirectory
。像这样更新build.gradle
:
android
// ...
defaultConfig
// ...
externalNativeBuild
cmake
// amend existing list of arguments, if you have one
arguments '-DCMAKE_SYSROOT='+android.ndkDirectory+'/sysroot'
然后,在CMakeLists.txt
,在第一次使用pf pkg-config之前,添加:
if(ANDROID)
set(ENVPKG_CONFIG_DIR "")
set(ENVPKG_CONFIG_LIBDIR "$CMAKE_SYSROOT/usr/lib/pkgconfig:$CMAKE_SYSROOT/usr/share/pkgconfig")
set(ENVPKG_CONFIG_SYSROOT_DIR $CMAKE_SYSROOT)
endif(ANDROID)
【讨论】:
以上是关于如何告诉 CMake(通过 externalNativeBuild 调用)在哪里寻找库?的主要内容,如果未能解决你的问题,请参考以下文章