如何用Conan 2.0为含子库的CMake接口库打包?
解决方案:为包含INTERFACE库的CMake项目编写Conan打包脚本
不需要为每个子库单独编写conanfile.py,主项目的单个conanfile.py就能通过Conan的components特性统一管理所有子库和INTERFACE库。
完整Conan打包脚本示例
from conan import ConanFile from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps from conan.tools.files import copy class PartInterfaceConan(ConanFile): name = "part_interface" version = "1.0.0" settings = "os", "compiler", "build_type", "arch" generators = "CMakeDeps" def layout(self): self.folders.source = "." self.folders.build = "build" self.folders.install = "install" # 全局头文件路径,子库头文件可单独调整 self.cpp.source.includedirs = ["include"] def generate(self): tc = CMakeToolchain(self) tc.generate() deps = CMakeDeps(self) deps.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build() def package(self): # 打包所有子库的头文件 copy(self, "*.h", src=self.source_folder + "/part1/include", dst=self.package_folder + "/include") copy(self, "*.h", src=self.source_folder + "/part2/include", dst=self.package_folder + "/include") copy(self, "*.h", src=self.source_folder + "/part3/include", dst=self.package_folder + "/include") # 打包全局头文件(如果存在) copy(self, "*.h", src=self.source_folder + "/include", dst=self.package_folder + "/include") # 打包所有子库的库文件 copy(self, "*.lib", src=self.build_folder, dst=self.package_folder + "/lib", keep_path=False) copy(self, "*.a", src=self.build_folder, dst=self.package_folder + "/lib", keep_path=False) copy(self, "*.dll", src=self.build_folder, dst=self.package_folder + "/bin", keep_path=False) copy(self, "*.so", src=self.build_folder, dst=self.package_folder + "/lib", keep_path=False) copy(self, "*.dylib", src=self.build_folder, dst=self.package_folder + "/lib", keep_path=False) def package_info(self): # 定义每个子库的component self.cpp_info.components["part1"].libs = ["part1"] self.cpp_info.components["part1"].includedirs = ["include"] self.cpp_info.components["part2"].libs = ["part2"] self.cpp_info.components["part2"].includedirs = ["include"] self.cpp_info.components["part3"].libs = ["part3"] self.cpp_info.components["part3"].includedirs = ["include"] # 定义INTERFACE库的component,自动依赖所有子库 self.cpp_info.components["part_interface"].requires = ["part1", "part2", "part3"]
关键逻辑说明
- 构建阶段:调用CMake正常编译整个项目,自动处理子库和INTERFACE库的构建流程。
- 打包阶段:手动复制所有子库的头文件和库文件到Conan包目录——因为INTERFACE库本身没有实体文件,但其依赖的子库产物需要完整打包。
- 组件声明阶段:
- 为每个子库创建独立的
component,指定链接库名和头文件路径。 - 为
part_interface创建component,通过requires关联所有子库组件,这样下游项目依赖part_interface时,会自动链接所有子库。
- 为每个子库创建独立的
优化建议
如果子项目的CMakeLists.txt中已经包含install指令(示例如下),可以在package阶段直接调用cmake.install()自动复制文件,无需手动写copy命令:
# part1/CMakeLists.txt示例 add_library(part1 STATIC src/part1.cpp) target_include_directories(part1 PUBLIC include) install(TARGETS part1 DESTINATION lib) install(DIRECTORY include/ DESTINATION include)
对应的Conan打包阶段代码替换为:
def package(self): cmake = CMake(self) cmake.install()
内容的提问来源于stack exchange,提问作者PMDP3
相关产品推荐
相关产品推荐

