交叉编译树莓派项目:解决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
相关产品推荐
相关产品推荐

