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

How to tell CMake (invoked through externalNativeBuild) where to look for libraries?

我正在开发一个 multi-platform 项目,该项目支持 Linux 和 Android。代码主要是C; Android 端口有一个 Java 包装器用于 platform-specific 部分,它调用核心功能的本机代码部分。

在 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 构建时,这不会为主机 OS(在 /usr/include/ 下面的某个地方)而不是为 Android(这会位于 $NDK/sysroot 下方的某处)。 (注意$NDK只是表示NDK路径,不一定是环境变量。)

根据this postpkg-config依赖于一堆环境变量来确定在哪里寻找库,即CMAKE_SYSROOTPKG_CONFIG_DIRPKG_CONFIG_LIBDIRPKG_CONFIG_SYSROOT_DIR。我检查了它们,它们是空的(或未设置)。

使用 gradle/NDK/CMake 工具链,我怎样才能将正确的变量传递给 CMake,或者让它找到 NDK 提供的库 headers?

有两种选择:

  1. 如果预构建库安装在托管 OS 上(例如,我们使用的 docker image 包括所有已编译和安装的预构建和其他先决条件 - SDK、NDK、AndroidStudio 等。 ), 你需要提供 CMAKE_FIND_ROOT_PATH librariesincludescmake configs 安装位置:
list(APPEND CMAKE_FIND_ROOT_PATH ${THIRDPARTY_DIR}/${THIRDPARTY_ANDROID_PLATFORM}/${ANDROID_ABI}/boost)
  1. 如果未安装预构建,您需要提供 Find<module>.cmake,例如 FindBoost.cmake 来为 find_package(Boost) 提供服务(这里是 example 如何实现,此项目还使用了多平台部分)。

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(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)