仅在构建包时使用系统依赖

在某些情况下,您可能希望仅在构建包时使用系统依赖,而不是在安装时使用。当您希望在 CI/CD 流水线中构建包,但在不同环境中安装 Conan 包时不运行系统包管理器时,这会很有用。对于这些情况,有几种方法可以实现此目标。

将系统包的 Conan 包封装作为构建依赖项使用

在这种方法中,您可以为 封装的系统包 使用 Conan 包。然后,可以通过方法 build_requirements() 常规地使用该包。

from conan import ConanFile

class MyPackage(ConanFile):
    name = "mypackage"
    settings = "os", "compiler", "build_type", "arch"

    def build_requirements(self):
        self.tool_requires("ncurses/system")

    ...

这确保了包 mypackage 的下游消费者不会直接调用系统包管理器(例如 apt-get)。只有直接使用 ncurses 系统封装包的消费者在构建包时才会执行系统包管理器。

ncurses 集中并封装在一个独立的 recipe 中,使其在多种情况下可重用,并且是避免代码重复的良好实践。

直接在 build() 方法中消耗系统包

如果只想在构建包时运行系统包管理器,但没有 Conan 包来封装系统库信息,则可以在 build() 方法中运行系统包管理器

from conan import ConanFile
from conan.tools.system import package_manager

class MyPackage(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    ...

    def build(self):
        if self.settings.os == "Linux":
            apt = package_manager.Apt(self)
            apt.install(["libncurses-dev"], update=True, check=True)

这样,系统包管理器将仅在构建包时被调用,而不是在安装时调用。这样做的好处是无需创建单独的 Conan 包来封装系统库信息,这是一种更简单的情况,仅当单个 recipe 需要安装系统包时适用。

然而,如果多个 recipe 使用相同的系统包,这种方法可能导致代码重复。建议谨慎使用此方法,仅限于独立的情况。