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

交叉编译树莓派项目:解决rabbitmq-c依赖OpenSSL的CMake配置问题

问题

为树莓派交叉编译时,需要使用依赖OpenSSL的rabbitmq-c库,希望通过CMake自动编译所有依赖。最初用FetchContent同时引入OpenSSL和rabbitmq-c,配置项目时rabbitmq-c找不到OpenSSL,推测是因为OpenSSL要到make阶段才编译安装,配置阶段缺少必要文件。改用ExternalProject后仍报相同错误,如何正确处理这类链式依赖?

初始配置代码

cmake_minimum_required(VERSION 3.25)

project(
  proj
  LANGUAGES CXX
)

set(CMAKE_FIND_ROOT_PATH .)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

include(FetchContent)

FetchContent_Declare(openssl
  GIT_REPOSITORY https://github.com/openssl/openssl.git
  GIT_TAG openssl-3.1.1
)
FetchContent_MakeAvailable(openssl)

FetchContent_Declare(rabbitmq-c
  GIT_REPOSITORY https://github.com/alanxz/rabbitmq-c.git
  GIT_TAG v0.13.0
)

FetchContent_MakeAvailable(rabbitmq-c)

初始报错信息

...
-- Looking for posix_spawnp in rt - not found
CMake Error at /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the
  system variable OPENSSL_ROOT_DIR (missing: OPENSSL_CRYPTO_LIBRARY
  OPENSSL_INCLUDE_DIR) (Required is at least version "1.1.1")
Call Stack (most recent call first):
  /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE)
  /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindOpenSSL.cmake:670 (find_package_handle_standard_args)
  build/_deps/rabbitmq-c-src/CMakeLists.txt:116 (find_package)


-- Configuring incomplete, errors occurred!

改用ExternalProject后的配置代码

cmake_minimum_required(VERSION 3.25)

project(
  proj
  LANGUAGES CXX
)

set(CMAKE_FIND_ROOT_PATH .)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

include(FetchContent)
include(ExternalProject)

###########
# OpenSSL
set(OPENSSL_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl-src) # default path by CMake
set(OPENSSL_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl)
set(OPENSSL_INCLUDE_DIR ${OPENSSL_INSTALL_DIR}/include)
set(OPENSSL_CONFIGURE_COMMAND ${OPENSSL_SOURCE_DIR}/config)
ExternalProject_Add(
  OpenSSL
  SOURCE_DIR ${OPENSSL_SOURCE_DIR}
  GIT_REPOSITORY https://github.com/openssl/openssl.git
  GIT_TAG openssl-3.1.1
  USES_TERMINAL_DOWNLOAD TRUE
  CONFIGURE_COMMAND
    ${OPENSSL_CONFIGURE_COMMAND}
    --prefix=${OPENSSL_INSTALL_DIR}
    --openssldir=${OPENSSL_INSTALL_DIR}
  BUILD_COMMAND make
  TEST_COMMAND ""
  INSTALL_COMMAND make install
  INSTALL_DIR ${OPENSSL_INSTALL_DIR}
)

# We cannot use find_library because ExternalProject_Add() is performed at build time.
# And to please the property INTERFACE_INCLUDE_DIRECTORIES,
# we make the include directory in advance.
file(MAKE_DIRECTORY ${OPENSSL_INCLUDE_DIR})

add_library(OpenSSL::SSL STATIC IMPORTED GLOBAL)
set_property(TARGET OpenSSL::SSL PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libssl.${OPENSSL_LIBRARY_SUFFIX})
set_property(TARGET OpenSSL::SSL PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
add_dependencies(OpenSSL::SSL OpenSSL)

add_library(OpenSSL::Crypto STATIC IMPORTED GLOBAL)
set_property(TARGET OpenSSL::Crypto PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libcrypto.${OPENSSL_LIBRARY_SUFFIX})
set_property(TARGET OpenSSL::Crypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
add_dependencies(OpenSSL::Crypto OpenSSL)

set(OPENSSL_ROOT_DIR ${OPENSSL_INSTALL_DIR})

###########
# RabbitMQ
FetchContent_Declare(rabbitmq-c
  GIT_REPOSITORY https://github.com/alanxz/rabbitmq-c.git
  GIT_TAG v0.13.0
)

FetchContent_MakeAvailable(rabbitmq-c)

后续报错信息

CMake Error at /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the
  system variable OPENSSL_ROOT_DIR (missing: OPENSSL_CRYPTO_LIBRARY)
  (Required is at least version "1.1.1")
Call Stack (most recent call first):
  /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE)
  /usr/local/Cellar/cmake/3.26.4/share/cmake/Modules/FindOpenSSL.cmake:670 (find_package_handle_standard_args)
  build/_deps/rabbitmq-c-src/CMakeLists.txt:116 (find_package)
解决方案

问题核心在于:FetchContent在配置阶段拉取构建依赖,而ExternalProject仅在构建阶段编译安装OpenSSL,rabbitmq-c的配置阶段早于OpenSSL的构建,自然找不到实际存在的库文件。要解决这个问题,需要让rabbitmq-c的配置阶段能感知到预定义的OpenSSL路径,同时确保rabbitmq-c的构建依赖于OpenSSL的安装完成。

方案1:用ExternalProject统一管理所有依赖(推荐)

放弃FetchContent,改用ExternalProject管理rabbitmq-c,在配置rabbitmq-c时显式指定OpenSSL的安装路径,并设置依赖关系。

完整配置代码:

cmake_minimum_required(VERSION 3.25)

project(proj LANGUAGES CXX)

set(CMAKE_FIND_ROOT_PATH .)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

include(ExternalProject)

# 定义所有依赖的统一安装目录
set(DEPS_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps)
file(MAKE_DIRECTORY ${DEPS_INSTALL_DIR})

###########
# OpenSSL
set(OPENSSL_INSTALL_DIR ${DEPS_INSTALL_DIR}/openssl)
ExternalProject_Add(
  OpenSSL
  GIT_REPOSITORY https://github.com/openssl/openssl.git
  GIT_TAG openssl-3.1.1
  USES_TERMINAL_DOWNLOAD TRUE
  CONFIGURE_COMMAND
    ${CMAKE_CURRENT_BINARY_DIR}/OpenSSL-prefix/src/OpenSSL/config
    --prefix=${OPENSSL_INSTALL_DIR}
    --openssldir=${OPENSSL_INSTALL_DIR}
    # 树莓派交叉编译需指定目标架构,示例:linux-armv4
    # ${OPENSSL_TARGET}
  BUILD_COMMAND make -j${CMAKE_BUILD_PARALLEL_LEVEL}
  TEST_COMMAND ""
  INSTALL_COMMAND make install
  INSTALL_DIR ${OPENSSL_INSTALL_DIR}
)

# 创建OpenSSL导入目标,供主项目直接使用
file(MAKE_DIRECTORY ${OPENSSL_INSTALL_DIR}/include)

add_library(OpenSSL::SSL STATIC IMPORTED GLOBAL)
set_property(TARGET OpenSSL::SSL PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libssl.a)
set_property(TARGET OpenSSL::SSL PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INSTALL_DIR}/include)
add_dependencies(OpenSSL::SSL OpenSSL)

add_library(OpenSSL::Crypto STATIC IMPORTED GLOBAL)
set_property(TARGET OpenSSL::Crypto PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libcrypto.a)
set_property(TARGET OpenSSL::Crypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INSTALL_DIR}/include)
add_dependencies(OpenSSL::Crypto OpenSSL)

###########
# rabbitmq-c
set(RABBITMQ_INSTALL_DIR ${DEPS_INSTALL_DIR}/rabbitmq-c)
ExternalProject_Add(
  rabbitmq-c
  GIT_REPOSITORY https://github.com/alanxz/rabbitmq-c.git
  GIT_TAG v0.13.0
  USES_TERMINAL_DOWNLOAD TRUE
  CONFIGURE_COMMAND
    cmake
    -S ${CMAKE_CURRENT_BINARY_DIR}/rabbitmq-c-prefix/src/rabbitmq-c
    -B ${CMAKE_CURRENT_BINARY_DIR}/rabbitmq-c-prefix/src/rabbitmq-c-build
    -DCMAKE_INSTALL_PREFIX=${RABBITMQ_INSTALL_DIR}
    # 显式传递OpenSSL路径,避免系统搜索
    -DOPENSSL_ROOT_DIR=${OPENSSL_INSTALL_DIR}
    -DOPENSSL_INCLUDE_DIR=${OPENSSL_INSTALL_DIR}/include
    -DOPENSSL_CRYPTO_LIBRARY=${OPENSSL_INSTALL_DIR}/lib/libcrypto.a
    -DOPENSSL_SSL_LIBRARY=${OPENSSL_INSTALL_DIR}/lib/libssl.a
    # 交叉编译需指定工具链文件,示例:
    # -DCMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/toolchain-rpi.cmake
  BUILD_COMMAND make -j${CMAKE_BUILD_PARALLEL_LEVEL}
  TEST_COMMAND ""
  INSTALL_COMMAND make install
  INSTALL_DIR ${RABBITMQ_INSTALL_DIR}
  # 设置依赖,确保OpenSSL安装完成后再构建rabbitmq-c
  DEPENDS OpenSSL
)

# 创建rabbitmq-c导入目标,供主项目直接使用
file(MAKE_DIRECTORY ${RABBITMQ_INSTALL_DIR}/include)

add_library(rabbitmq::rabbitmq STATIC IMPORTED GLOBAL)
set_property(TARGET rabbitmq::rabbitmq PROPERTY IMPORTED_LOCATION ${RABBITMQ_INSTALL_DIR}/lib/librabbitmq.a)
set_property(TARGET rabbitmq::rabbitmq PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${RABBITMQ_INSTALL_DIR}/include)
add_dependencies(rabbitmq::rabbitmq rabbitmq-c)

关键说明

  • 交叉编译适配:需要为OpenSSL指定树莓派对应的目标架构(如linux-armv4),同时给rabbitmq-c指定CMake工具链文件,确保编译出符合目标架构的二进制文件。
  • 显式路径传递:在rabbitmq-c的配置命令中直接指定OpenSSL的头文件和库路径,跳过系统自动搜索逻辑。
  • 依赖顺序控制:通过DEPENDS OpenSSL强制rabbitmq-c的构建流程等待OpenSSL安装完成。

方案2:FetchContent结合路径传递(仅适配支持CMake目标传递的依赖)

如果rabbitmq-c的CMake配置支持直接链接OpenSSL的CMake目标,可以在FetchContent声明前添加以下配置:

# 在FetchContent_MakeAvailable(rabbitmq-c)前添加
set(CMAKE_PREFIX_PATH ${OPENSSL_INSTALL_DIR};${CMAKE_PREFIX_PATH})
set(rabbitmq-c_DEPENDS OpenSSL)
FetchContent_MakeAvailable(rabbitmq-c)

此方案依赖rabbitmq-c的CMake脚本实现,可靠性不如方案1。


内容的提问来源于stack exchange,提问作者K. Shores

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:07:36