如何告诉 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 post,pkg-config
依赖于一堆环境变量来确定在哪里寻找库,即CMAKE_SYSROOT
、PKG_CONFIG_DIR
、PKG_CONFIG_LIBDIR
和 PKG_CONFIG_SYSROOT_DIR
。我检查了它们,它们是空的(或未设置)。
使用 gradle/NDK/CMake 工具链,我怎样才能将正确的变量传递给 CMake,或者让它找到 NDK 提供的库 headers?
有两种选择:
- 如果预构建库安装在托管 OS 上(例如,我们使用的
docker image
包括所有已编译和安装的预构建和其他先决条件 - SDK、NDK、AndroidStudio 等。 ), 你需要提供 CMAKE_FIND_ROOT_PATH
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 如何实现,此项目还使用了多平台部分)。
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)
我正在开发一个 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 post,pkg-config
依赖于一堆环境变量来确定在哪里寻找库,即CMAKE_SYSROOT
、PKG_CONFIG_DIR
、PKG_CONFIG_LIBDIR
和 PKG_CONFIG_SYSROOT_DIR
。我检查了它们,它们是空的(或未设置)。
使用 gradle/NDK/CMake 工具链,我怎样才能将正确的变量传递给 CMake,或者让它找到 NDK 提供的库 headers?
有两种选择:
- 如果预构建库安装在托管 OS 上(例如,我们使用的
docker image
包括所有已编译和安装的预构建和其他先决条件 - SDK、NDK、AndroidStudio 等。 ), 你需要提供CMAKE_FIND_ROOT_PATH
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 如何实现,此项目还使用了多平台部分)。
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)