如何告诉CMake(通过externalNativeBuild调用)在哪里寻找库?



我正在做一个多平台项目,其中支持Linux和Android。代码主要是C语言;Android移植有一个Java包装器用于平台特定的部分,它调用核心功能的本机代码部分。

在Linux上,我们使用CMake,然后是make来构建这个项目。对于Android,我们基本上使用Gradle并通过externalNativeBuild调用CMake。CMakeFile.txt可以检测Android构建与一个简单的if (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路径,不一定是环境变量。)

根据这篇文章,pkg-config依赖于一堆环境变量来确定在哪里寻找库,即CMAKE_SYSROOT,PKG_CONFIG_DIR,PKG_CONFIG_LIBDIRPKG_CONFIG_SYSROOT_DIR。我检查了它们,它们是空的(或未设置)。

使用gradle/NDK/CMake工具链,我如何将正确的变量传递给CMake,或者让它找到NDK提供头的库?

有两个选项:

  1. 如果预构建库安装在宿主操作系统上(例如,我们使用docker image,包括所有编译和安装的预构建和其他先决条件- SDK, NDK, AndroidStudio等),您需要提供CMAKE_FIND_ROOT_PATHlibraries,includescmake configs的安装位置:
list(APPEND CMAKE_FIND_ROOT_PATH ${THIRDPARTY_DIR}/${THIRDPARTY_ANDROID_PLATFORM}/${ANDROID_ABI}/boost)
  1. 如果未安装预构建,则需要提供Find<module>.cmake,例如FindBoost.cmake来服务find_package(Boost)(这里是如何实现的示例,该项目也使用多平台部件)。

gradle的NDK路径为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中,第一次使用pkg-config之前,添加:

if(ANDROID)
set(ENV{PKG_CONFIG_DIR} "")
set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig")
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
endif(ANDROID)

最新更新