You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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"]

关键逻辑说明

  1. 构建阶段:调用CMake正常编译整个项目,自动处理子库和INTERFACE库的构建流程。
  2. 打包阶段:手动复制所有子库的头文件和库文件到Conan包目录——因为INTERFACE库本身没有实体文件,但其依赖的子库产物需要完整打包。
  3. 组件声明阶段:
    • 为每个子库创建独立的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 05:23:11