You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android平台CMake引入BoringSSL依赖时链接失败排查及方案咨询

问题描述

我用C++和CMake开发Android平台的库,尝试引入BoringSSL作为依赖,当前代码实现如下:

add_library(mylib STATIC
    foo.cpp bar.cpp .....)

ExternalProject_Add(
        boringssl
        GIT_REPOSITORY "https://github.com/google/boringssl.git"
        GIT_TAG "origin/master"
        SOURCE_DIR "external/boringssl"
        STEP_TARGETS crypto ssl
        CMAKE_ARGS "-DOPENSSL_SMALL=TRUE"
)

add_dependencies(mylib boringssl)

target_link_directories(mylib PRIVATE
    "${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/install/lib")
target_link_libraries(mylib PRIVATE
    crypto ssl)

链接mylib时出现错误:ld.lld: error: unable to find library -lcrypto 和 -lssl,奇怪的是,虽然用了target_link_directories,但链接命令行里并没有包含.../boringssl/install/lib目录。该目录在配置阶段不存在(因为ExternalProject_Add在构建阶段运行),但这应该不是问题吧?

我肯定哪里操作错了,问题出在哪?

延伸问题

想把BoringSSL作为我的库的依赖项,除了ExternalProject_Add之外,最优的实现方式是什么?

编辑补充

以下是链接命令行(我的库名为srtc),可以看到缺少指定的链接目录:

--target=aarch64-none-linux-android29 --sysroot=/mnt/android/sdk/ndk/27.2.12479018/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security  -fno-exceptions -fno-rtti -fno-limit-debug-info  -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libsrtctest.so -o /home/kman/Android/proj-srtc/build/intermediates/cxx/Debug/5963472j/obj/arm64-v8a/libsrtctest.so CMakeFiles/srtctest.dir/jni_class_map.cpp.o CMakeFiles/srtctest.dir/jni_error.cpp.o CMakeFiles/srtctest.dir/jni_util.cpp.o CMakeFiles/srtctest.dir/jni_peer_connection.cpp.o CMakeFiles/srtctest.dir/srtctest_main.cpp.o  srtc/libsrtc.a  -landroid  -llog  -lcrypto  -lssl  -latomic -lm && :
  ld.lld: error: unable to find library -lcrypto
  ld.lld: error: unable to find library -lssl

解决方案

一、当前链接错误的原因

  1. target_link_directories时机问题:CMake在配置阶段会解析该命令,但此时BoringSSL的安装目录尚未生成,CMake会直接忽略这个不存在的路径,导致链接阶段找不到库目录。
  2. ExternalProject_Add配置缺失:没有指定安装路径和安装命令,BoringSSL默认不会将编译好的库输出到你指定的install/lib目录;同时STEP_TARGETS未正确关联到库的安装流程,依赖关系不完整。
  3. 未建立导入目标:直接使用crypto和ssl作为链接目标,但CMake没有感知到这两个库的实际路径,无法自动添加链接目录。

修复当前代码的步骤

修改ExternalProject_Add配置,补充安装相关参数,通过导入目标的方式让CMake识别BoringSSL的库文件:

add_library(mylib STATIC
    foo.cpp bar.cpp .....)

ExternalProject_Add(
        boringssl
        GIT_REPOSITORY "https://github.com/google/boringssl.git"
        GIT_TAG "master"
        SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/boringssl"
        BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/boringssl"
        INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/install"
        CMAKE_ARGS 
            "-DOPENSSL_SMALL=TRUE"
            "-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>"
            "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}"  # 传递Android工具链配置
            "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
        STEP_TARGETS install
)

# 获取BoringSSL的安装路径,并导入静态库目标
ExternalProject_Get_Property(boringssl INSTALL_DIR)
add_library(crypto STATIC IMPORTED GLOBAL)
set_target_properties(crypto PROPERTIES
    IMPORTED_LOCATION "${INSTALL_DIR}/lib/libcrypto.a"
    INTERFACE_INCLUDE_DIRECTORIES "${INSTALL_DIR}/include"
)
add_library(ssl STATIC IMPORTED GLOBAL)
set_target_properties(ssl PROPERTIES
    IMPORTED_LOCATION "${INSTALL_DIR}/lib/libssl.a"
    INTERFACE_INCLUDE_DIRECTORIES "${INSTALL_DIR}/include"
)

# 确保导入目标在BoringSSL安装完成后才可用
add_dependencies(crypto boringssl_install)
add_dependencies(ssl boringssl_install)

# 关联依赖
target_link_libraries(mylib PRIVATE crypto ssl)

修改后:

  • 明确指定安装目录,BoringSSL会将编译好的库和头文件输出到目标路径
  • 通过IMPORTED目标让CMake感知到库的实际位置,避免target_link_directories的时机问题
  • 建立了严格的依赖链,确保BoringSSL安装完成后再链接你的库

二、除ExternalProject_Add之外的最优实现方式

1. 使用CMake FetchContent(推荐)

CMake 3.11+支持的FetchContent模块可以在配置阶段下载并构建依赖,直接集成到主构建流程,比ExternalProject_Add更简洁:

include(FetchContent)

FetchContent_Declare(
    boringssl
    GIT_REPOSITORY https://github.com/google/boringssl.git
    GIT_TAG master
)

FetchContent_MakeAvailable(boringssl)

add_library(mylib STATIC
    foo.cpp bar.cpp .....)

target_link_libraries(mylib PRIVATE ssl crypto)

优势:

  • 无需手动处理依赖顺序和路径,CMake自动管理
  • 支持IDE索引,可直接跳转至BoringSSL源码
  • 构建流程与主项目同步,避免多阶段构建的冲突

2. 预编译BoringSSL库

如果需要稳定的依赖版本,可提前为Android各架构预编译BoringSSL,然后直接导入预编译库:

# 导入预编译的crypto库
add_library(crypto STATIC IMPORTED)
set_target_properties(crypto PROPERTIES
    IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/prebuilt/boringssl/${ANDROID_ABI}/libcrypto.a"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/prebuilt/boringssl/include"
)

# 导入预编译的ssl库
add_library(ssl STATIC IMPORTED)
set_target_properties(ssl PROPERTIES
    IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/prebuilt/boringssl/${ANDROID_ABI}/libssl.a"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/prebuilt/boringssl/include"
)

add_library(mylib STATIC foo.cpp bar.cpp)
target_link_libraries(mylib PRIVATE ssl crypto)

优势:

  • 构建速度快,无需每次编译BoringSSL
  • 版本可控,避免源码构建的不确定性

3. 使用Android NDK内置的BoringSSL

从NDK 17开始,Android NDK已内置BoringSSL作为默认SSL库,可直接链接系统提供的库:

add_library(mylib STATIC foo.cpp bar.cpp)
target_link_libraries(mylib PRIVATE log android ssl crypto)

优势:

  • 无需额外管理依赖,NDK自动处理
  • 符合Android平台标准配置,兼容性好
  • 注意:NDK内置的BoringSSL版本与官方可能存在差异,部分特性可能被裁剪

内容的提问来源于stack exchange,提问作者Kostya Vasilyev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 09:09:51