CMake无法找到OpenSSL:Android NDK工具链引发的问题排查
核心原因
Android NDK的android.toolchain.cmake会配置交叉编译环境,修改CMake的查找根路径规则,导致默认的FindOpenSSL.cmake优先在NDK的sysroot中查找,忽略了你指定的OPENSSL_ROOT_DIR;同时BoringSSL与官方OpenSSL的目录结构存在差异,进一步干扰了自动查找逻辑。
具体解决思路
1. 确保BoringSSL是针对目标Android架构编译的
交叉编译环境下,BoringSSL的编译产物必须和你要构建的Android ABI(如arm64-v8a、armeabi-v7a)完全匹配,不能用x86/x86_64平台的编译结果。编译BoringSSL时需指定NDK工具链,示例命令(以arm64-v8a为例):
export ANDROID_NDK=/path/to/ndk/25.1.8937393 export TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/darwin-x86_64 export TARGET=aarch64-linux-android export API=24 # 目标Android API版本 export AR=$TOOLCHAIN/bin/llvm-ar export CC=$TOOLCHAIN/bin/$TARGET$API-clang export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++ mkdir build-arm64 && cd build-arm64 cmake ../boringssl-source/ \ -DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_VERSION=$API \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_NDK=$ANDROID_NDK \ -DCMAKE_C_COMPILER=$CC \ -DCMAKE_CXX_COMPILER=$CXX \ -DCMAKE_INSTALL_PREFIX=/path/to/boringssl-install/arm64-v8a make install
2. 手动指定OpenSSL变量,绕过自动查找
既然find_package(OpenSSL)自动查找失效,直接在CMakeLists.txt中手动设置所需变量,放在find_package(OpenSSL REQUIRED)之前:
# 根据你的BoringSSL安装路径和目标ABI调整 set(OPENSSL_ROOT_DIR "/path/to/boringssl-install/${CMAKE_ANDROID_ABI}") set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include") set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/libcrypto.a") set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/libssl.a") set(OPENSSL_FOUND TRUE) find_package(OpenSSL REQUIRED)
如果BoringSSL库按ABI分目录存放,${CMAKE_ANDROID_ABI}会自动匹配当前编译目标。
3. 自定义FindBoringSSL模块
由于BoringSSL与官方OpenSSL结构有差异,可编写自定义FindBoringSSL.cmake模块,放在项目的cmake/Modules目录下,让CMake优先使用这个模块:
# cmake/Modules/FindBoringSSL.cmake find_path(BORINGSSL_INCLUDE_DIR NAMES openssl/ssl.h openssl/crypto.h PATHS "${OPENSSL_ROOT_DIR}/include" NO_CMAKE_FIND_ROOT_PATH # 跳过sysroot查找,直接用指定路径 ) find_library(BORINGSSL_CRYPTO_LIBRARY NAMES crypto PATHS "${OPENSSL_ROOT_DIR}/lib/${CMAKE_ANDROID_ABI}" NO_CMAKE_FIND_ROOT_PATH ) find_library(BORINGSSL_SSL_LIBRARY NAMES ssl PATHS "${OPENSSL_ROOT_DIR}/lib/${CMAKE_ANDROID_ABI}" NO_CMAKE_FIND_ROOT_PATH ) set(OPENSSL_INCLUDE_DIR ${BORINGSSL_INCLUDE_DIR}) set(OPENSSL_CRYPTO_LIBRARY ${BORINGSSL_CRYPTO_LIBRARY}) set(OPENSSL_SSL_LIBRARY ${BORINGSSL_SSL_LIBRARY}) set(OPENSSL_FOUND TRUE) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(BoringSSL DEFAULT_MSG BORINGSSL_INCLUDE_DIR BORINGSSL_CRYPTO_LIBRARY BORINGSSL_SSL_LIBRARY )
然后在主CMakeLists.txt中添加模块路径并查找:
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" ${CMAKE_MODULE_PATH}) find_package(BoringSSL REQUIRED)
4. 调整CMake查找根路径规则
NDK工具链默认设置CMAKE_FIND_ROOT_PATH_MODE_INCLUDE和CMAKE_FIND_ROOT_PATH_MODE_LIBRARY为ONLY,即只在sysroot中查找。可修改这两个变量,让CMake同时在指定路径查找:
# 在find_package之前设置 set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) set(OPENSSL_ROOT_DIR "/path/to/boringssl-install") find_package(OpenSSL REQUIRED)
注意:该设置会影响所有依赖的查找逻辑,可能导致其他系统库查找出现问题,需测试验证。
内容的提问来源于stack exchange,提问作者Kostya Vasilyev

