如何为Conan包创建多目标,实现单独链接子库?
问题
我正尝试创建一个Conan包,以便能在任意项目中安装并选择需要引入的子库。目前已完成以下操作:
我的包文件夹(命名为mypkg)包含一个CMakeLists.txt,用于编译所有子文件夹;每个子文件夹含.cpp/.hpp文件及如下模板的CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.12) project(library1) if(NOT TARGET ${PROJECT_NAME}) add_library(${PROJECT_NAME} STATIC library1.cpp library1.hpp ) endif()
该代码会生成N个.a静态库。对应的conanfile.py代码如下:
class mypkg(ConanFile): ... settings = "os", "arch", "compiler", "build_type" options = {"shared": [True, False]} default_options = "shared=True" generators = "cmake","cmake_find_package" def build(self): cmake = CMake(self) cmake.definitions['CMAKE_EXPORT_COMPILE_COMMANDS'] = "ON" cmake.configure() cmake.build() def package(self): self.copy("*.h", dst="include", src="src", keep_path=True) self.copy("*.a", dst="lib", keep_path=False) def package_info(self): self.cpp_info.libs = tools.collect_libs(self)
执行conan create .创建包后,在项目中引入时只能整体链接,无法单独链接子库:
可正常使用:
find_package(mypkg REQUIRED) target_link_libraries(${PROJECT_NAME} mypkg::mypkg)
无法使用:
find_package(mypkg REQUIRED) target_link_libraries(${PROJECT_NAME} mypkg::library1)
请问该如何解决此问题?
解决方法
要实现单独链接子库,核心是在Conan的package_info中为每个子库声明独立的组件(Component),具体步骤如下:
1. 修改conanfile.py的package_info方法
替换原有的package_info逻辑,为每个子库创建对应组件,明确每个组件的链接信息:
def package_info(self): # 自动收集所有子库名称,无需手动枚举 libs = tools.collect_libs(self) for lib in libs: # 为每个子库注册组件 self.cpp_info.components[lib].libs = [lib] # 设置头文件搜索路径,根据你的实际目录结构调整 self.cpp_info.components[lib].includedirs = ["include"] # 如果子库间有依赖,比如library2依赖library1,添加如下声明: # if lib == "library2": # self.cpp_info.components[lib].requires = ["library1"] # 保留整体链接目标,兼容原有使用方式 self.cpp_info.libs = libs
2. 确认打包内容完整性
确保你的package方法已经正确复制了所有子库的静态库和头文件:
- 静态库:
self.copy("*.a", dst="lib", keep_path=False)已经将所有子库的.a文件复制到包的lib目录 - 头文件:
self.copy("*.h", dst="include", src="src", keep_path=True)确保子库的头文件路径结构正确,方便项目引用
3. 验证使用效果
重新执行conan create .生成更新后的包,在项目中即可单独链接子库:
find_package(mypkg REQUIRED) # 单独链接指定子库 target_link_libraries(${PROJECT_NAME} mypkg::library1) # 同时链接多个子库 target_link_libraries(${PROJECT_NAME} mypkg::library1 mypkg::library2) # 依然支持整体链接所有子库 target_link_libraries(${PROJECT_NAME} mypkg::mypkg)
关键说明
- 组件机制会自动将Conan中声明的组件映射为CMake目标(如
mypkg::library1),和你CMakeLists.txt中定义的子库目标对应 - 子库间的依赖必须通过
requires声明,Conan会自动处理链接顺序,避免手动调整库顺序的问题
内容的提问来源于stack exchange,提问作者EddyIT
相关产品推荐
相关产品推荐

