自定义 Conan 生成器¶
如果您需要使用 Conan 本身不支持的构建系统或工具,您可以使用自定义生成器创建自己的自定义集成。这可以通过三种不同的方式完成。
将自定义生成器用作 python_requires¶
在 Conan 中拥有自定义生成器的一种方法是将其用作 python_requires。您可以在 mygenerator/1.0 python_requires 包中声明一个 MyGenerator 类,其中包含生成某些文件的所有逻辑。
from conan import ConanFile
from conan.tools.files import save
class MyGenerator:
def __init__(self, conanfile):
self._conanfile = conanfile
def generate(self):
deps_info = ""
for dep, _ in self._conanfile.dependencies.items():
deps_info += f"{dep.ref.name}, {dep.ref.version}\n"
save(self._conanfile, "deps.txt", deps_info)
class PyReq(ConanFile):
name = "mygenerator"
version = "1.0"
package_type = "python-require"
然后 conan create mygenerator
并像这样在您自己的包的 generate 方法中使用它:
from conan import ConanFile
class MyPkg(ConanFile):
name = "pkg"
version = "1.0"
python_requires = "mygenerator/1.0"
requires = "zlib/1.3.1", "bzip2/1.0.8"
def generate(self):
mygenerator = self.python_requires["mygenerator"].module.MyGenerator(self)
mygenerator.generate()
然后,在 `pkg` 配方上执行 `conan install pkg` 将创建一个 `deps.txt` 文本文件,其中包含:
zlib, 1.2.11
bzip2, 1.0.8
这样做的优点是您可以对自定义生成器进行版本控制,并且还可以将这些生成器作为 Conan 包进行共享。
使用全局自定义生成器¶
您还可以全局使用自定义生成器,如果将它们存储在 `[CONAN_HOME]/extensions/generators` 文件夹中。您可以直接将它们放在该文件夹中,或者使用 `conan config install` 命令进行安装。
from conan.tools.files import save
class MyGenerator:
def __init__(self, conanfile):
self._conanfile = conanfile
def generate(self):
deps_info = ""
for dep, _ in self._conanfile.dependencies.items():
deps_info = f"{dep.ref.name}, {dep.ref.version}"
save(self._conanfile, "deps.txt", deps_info)
然后,您可以在配方中或使用 `-g` 参数在命令行中使用它们的名称:
conan install --requires=zlib/1.2.13 -g MyGenerator
来自 tool_requires 的生成器¶
警告
此功能是实验性的,可能会发生重大更改。有关更多信息,请参阅 Conan 稳定性 部分。
直接的依赖项 tool_requires 也可以用来提供自定义生成器。下面的示例展示了如何创建一个自定义生成器,该生成器生成一个包含包依赖项的文件(就像上面的示例一样),但使用 `tool_require` 而不是 `python_require` 来注入生成器到配方中,方法是在 `package_info` 方法中将它们添加到 `self.generator_info` 属性。请注意,此属性默认为 `None`,因此您需要显式将其设置为一个生成器列表。
from conan import ConanFile
from conan.tools.files import save
class MyGenerator:
def __init__(self, conanfile):
self._conanfile = conanfile
def generate(self):
deps_info = ""
for dep, _ in self._conanfile.dependencies.items():
deps_info = f"{dep.ref.name}, {dep.ref.version}"
save(self._conanfile, "deps.txt", deps_info)
class MyToolReq(ConanFile):
name = "mygenerator-tool"
version = "1.0"
def package_info(self):
self.generator_info = [MyGenerator]
然后在您的配方中有一个 `mygenerator-tool` 包的 `tool_requires`,它将自动将生成器注入到配方中。
注意
请注意,内置生成器也可以使用 tool_requires 来注入,通过按名称添加它们:`self.generator_info = ["CMakeDeps"]`。 `tool_require` 这个包将像在 `generators` 属性中声明一样,将 `CMakeDeps` 生成器注入到配方中。