如何使用CMake为C++项目正确链接nghttp2 asio库
CMake配置nghttp2库依赖解决方案
问题根因
你遇到的链接错误核心原因有两个:
nghttp2::asio_http2::server等Asio封装的接口实现不在核心的libnghttp2库中,而是在独立的libnghttp2_asio库中,你原来的配置仅链接了nghttp2核心库,缺少asio封装库的链接。- nghttp2源码默认不会编译Asio组件,如果你使用本地子模块编译的方式,需要手动开启编译开关。
两种优雅配置方案
方案1:使用系统预安装的nghttp2(推荐)
这种方案不需要编译nghttp2子模块,运行效率更高,配置更简洁:
- 先确保你的系统已经正确安装nghttp2的asio组件:
- 源码编译nghttp2时需添加
--enable-asio-lib编译参数 - Ubuntu/Debian可直接安装
apt install libnghttp2-dev
- 源码编译nghttp2时需添加
- 修改CMakeLists.txt配置,替换原来的nghttp2子模块相关配置:
# 新增PkgConfig依赖用于查找nghttp2_asio find_package(PkgConfig REQUIRED) pkg_check_modules(NGHTTP2_ASIO REQUIRED libnghttp2_asio) # 添加编译定义,对应你手动编译时的-DBOOST_LOG_DYN_LINK参数 target_compile_definitions(${PROJECT_NAME} PRIVATE BOOST_LOG_DYN_LINK) # 引入nghttp2_asio头文件和库路径 target_include_directories(${PROJECT_NAME} PRIVATE ${NGHTTP2_ASIO_INCLUDE_DIRS}) target_link_directories(${PROJECT_NAME} PRIVATE ${NGHTTP2_ASIO_LIBRARY_DIRS}) # 链接nghttp2_asio和缺失的OpenSSL::SSL库 target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads PRIVATE Boost::system PRIVATE Boost::thread PRIVATE Boost::log PRIVATE OpenSSL::Crypto PRIVATE OpenSSL::SSL PRIVATE ${NGHTTP2_ASIO_LIBRARIES} )
- 删掉原来的
set(NGHTTP2_SRC_DIR lib/nghttp2)、add_subdirectory、链接nghttp2的相关代码即可。
方案2:使用本地lib目录下的nghttp2子模块编译
如果你需要随项目一起编译nghttp2,可使用该方案:
- 在add_subdirectory之前开启nghttp2的asio编译开关,修改nghttp2相关配置为:
# 开启nghttp2 asio组件编译 set(ENABLE_ASIO_LIB ON CACHE BOOL "Build nghttp2 asio library" FORCE) # 可选:如果不需要静态库可关闭,减少编译时间 set(ENABLE_STATIC_LIB OFF CACHE BOOL "" FORCE) set(NGHTTP2_SRC_DIR lib/nghttp2) add_subdirectory(${NGHTTP2_SRC_DIR}) target_compile_definitions(${PROJECT_NAME} PRIVATE BOOST_LOG_DYN_LINK) # 直接链接nghttp2子模块导出的nghttp2_asio目标 target_link_libraries(${PROJECT_NAME} PUBLIC nghttp2_asio OpenSSL::SSL)
- 删掉原来链接
nghttp2核心库的配置即可。
其他需要修正的配置
- 你原来的CMake配置仅链接了
OpenSSL::Crypto,缺少手动编译时的-lssl对应的OpenSSL::SSL依赖,需要补上否则会出现SSL相关接口的链接错误。 - 你原来配置中的
target_include_directories指向的include目录在你的项目结构中不存在,没用的话可以直接删掉,避免后续编译出现路径警告。
内容的提问来源于stack exchange,提问作者user16516564
相关产品推荐
相关产品推荐

