如何让使用Conan开发的C++库的用户可选择是否使用Conan
Conan开发C++库避免强制用户使用Conan的解决方案
存在标准方案可以替换导出Targets中的Conan专属目标引用,无需强制库的使用者安装Conan,具体实现如下:
核心实现思路
利用CMake原生的生成器表达式或者别名目标,拆分「库本身构建」和「库安装后被用户引用」两个场景的依赖逻辑:你本地开发时用Conan管理的protobuf目标,导出给用户的配置里只引用标准CMake可以识别的protobuf官方目标。
方法1:使用生成器表达式区分场景(最推荐)
CMake的BUILD_INTERFACE和INSTALL_INTERFACE生成器表达式可以自动适配不同场景,修改你链接protobuf的逻辑即可:
target_link_libraries(mylib PUBLIC # 仅在你本地构建mylib的时候生效,使用Conan的protobuf目标 $<BUILD_INTERFACE:CONAN_PKG::protobuf> # 仅在导出到MylibTargets.cmake的时候生效,使用标准protobuf目标 $<INSTALL_INTERFACE:protobuf::libprotobuf> )
接下来你需要配套提供MylibConfig.cmake配置文件,让用户引用你的库时自动查找protobuf依赖:
- 先创建
MylibConfig.cmake.in模板文件:
include(CMakeFindDependencyMacro) # 自动查找用户环境中的protobuf依赖 find_dependency(Protobuf REQUIRED) # 导入你的库目标 include("${CMAKE_CURRENT_LIST_DIR}/MylibTargets.cmake")
- 在CMakeLists中添加生成和安装Config的逻辑:
include(CMakePackageConfigHelpers) configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/MylibConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/MylibConfig.cmake INSTALL_DESTINATION lib/cmake/mylib ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/MylibConfig.cmake DESTINATION lib/cmake/mylib )
此时生成的MylibTargets.cmake里的依赖就会变成protobuf::libprotobuf,用户只需要在自己环境中安装了protobuf,通过find_package(Mylib REQUIRED)就能正常引用你的库,不需要使用Conan。
方法2:创建统一别名目标
如果不想在链接时写生成器表达式,可以提前定义统一的protobuf别名,自动适配不同场景:
# 如果当前环境没有标准protobuf目标,就把Conan的目标别名成标准名称 if(NOT TARGET protobuf::libprotobuf) add_library(protobuf::libprotobuf ALIAS CONAN_PKG::protobuf) endif() # 直接链接统一的别名目标 target_link_libraries(mylib PUBLIC protobuf::libprotobuf)
这种方式导出的目标里也只会出现protobuf::libprotobuf,不会带有任何Conan相关的引用。
注意事项
- 请保证你使用的Conan安装的protobuf版本、编译选项与用户环境常用的版本ABI兼容,避免出现链接错误。
- 如果你的库依赖protobuf的特殊编译选项(如
PROTOBUF_USE_DLLS、线程安全开关等),请在库的使用文档中明确说明要求。
内容的提问来源于stack exchange,提问作者Jonas Andersson
相关产品推荐
相关产品推荐

