如何告诉 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_SYSROOTPKG_CONFIG_DIRPKG_CONFIG_LIBDIRPKG_CONFIG_SYSROOT_DIR。我检查了它们,它们是空的(或未设置)。

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

【问题讨论】:

【参考方案1】:

有两种选择:

    如果预建库安装在托管操作系统上(例如,我们使用docker image,包括所有已编译和安装的预建库和其他先决条件 - SDK、NDK、AndroidStudio 等),您需要提供@987654323 @ librariesincludescmake 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 调用)在哪里寻找库?的主要内容,如果未能解决你的问题,请参考以下文章

如何告诉 cmake 在哪里输出其构建数据?

我如何告诉 cmake 将解决方案和项目分开?

CMAKE 如何告诉 makefile 链接库?

如何“告诉”CMake 3.9+ 我想使用 NVIDIA 的 OpenCL 库?

如何将 cpplint.py 检查添加到 CMake 中?

如何构建一个CMake项目(译)