FAQ¶
另请参阅
Conan 背后有一个庞大的社区,用户们在 Cpplang Slack 中互相帮助。请加入我们的 #conan 频道!
错误:缺少预构建包¶
在安装包(使用 conan install 或 conan create)时,可能会遇到如下错误
ERROR: Missing binary: zlib/1.3.1:b1d267f77ddd5d10d06d2ecf5a6bc433fbb7eeed
zlib/1.3.1: WARN: Can't find a 'zlib/1.3.1' package binary 'b1d267f77ddd5d10d06d2ecf5a6bc433fbb7eeed' for the configuration:
[settings]
arch=x86_64
build_type=Release
compiler=apple-clang
compiler.cppstd=gnu11
compiler.libcxx=libc++
compiler.version=14
os=Macos
[options]
fPIC=True
shared=False
ERROR: Missing prebuilt package for 'zlib/1.3.1'. You can try:
- List all available packages using 'conan list "{ref}:*" -r=remote'
- Explain missing binaries: replace 'conan install ...' with 'conan graph explain ...'
- Try to build locally from sources using the '--build=zlib/1.3.1' argument
More Info at 'https://docs.conan.org.cn/en/2/knowledge/faq.html#error-missing-prebuilt-package'
这意味着包配方 zlib/1.3.1 存在,但由于某种原因,没有为您的当前设置或选项编译好的包。也许包创建者根本没有构建和共享预构建的包,而只是上传了包配方,或者他们只为某些平台或编译器提供包。例如,包创建者从配方构建了 apple-clang 11 的包,但您使用的是 apple-clang 14。您可能还想检查您的 包 ID 模式,因为它可能会影响可用的包。
默认情况下,Conan 不会从源代码构建包。有几种可能性可以克服此错误
您可以尝试从源代码为您的设置构建包,指示一些构建策略作为参数,例如 --build zlib* 或 --build missing。如果包配方和源代码适用于您的设置,您将在本地构建并准备好使用的二进制文件。
如果从源代码构建失败,并且您使用的是 conancenter 远程仓库,您可以在 Conan Center Index 仓库 中提交 issue。
错误:无效的设置¶
有时,当您指定默认设置中不存在的设置时,可能会收到如下消息
$ conan install . -s compiler.version=4.19 ...
ERROR: Invalid setting '4.19' is not a valid 'settings.compiler.version' value.
Possible values are ['4.4', '4.5', '4.6', '4.7', '4.8', '4.9', '5.1', '5.2', '5.3', '5.4', '6.1', '6.2']
这并不意味着 Conan 不支持该编译器版本,只是它当前默认设置中不存在。您可以在您的用户主文件夹中找到一个设置文件 ~/.conan2/settings.yml,您可以修改、编辑、添加任何设置或任何值,如有必要,可以进行任何嵌套。请参阅 settings.yml 了解如何自定义您的设置以根据您的意愿建模您的二进制文件。
只要您的团队或用户拥有相同的设置(settings.yml 和 settings_user.yml 可以使用 conan config install 命令轻松共享),一切都会正常工作。settings.yml 文件只是一个机制,让用户就典型设置的常见拼写达成一致。此外,如果您认为某些设置对许多其他 conan 用户有用,请将其提交为 issue 或 pull request,以便将其包含在未来的版本中。
某些内置的辅助工具或集成,例如 CMake 或 CMakeToolchain 可能无法理解新添加的设置,或者如果您为现有设置添加了一些新的意外值,甚至可能无法使用。像 CMake 这样的辅助工具只是将 conan 设置转换为各自构建系统语法和命令行参数的简单实用程序,因此可以扩展或替换为您自己的实用程序,以处理您自己的私有设置。
错误:AuthenticationException:¶
如果 conan 的 HTTP 请求中没有或有错误的身份验证凭据,则可能会发生此错误。要获取更多信息,请尝试启用 HTTP 连接的调试级别
import http.client
http.client.HTTPConnection.debuglevel = 1
错误的一个来源可能是 .netrc 文件,该文件被 requests 库 认可。
在 Linux 和 Windows 上获取不同的修订版本错误¶
Git 默认情况下会在 Windows 系统中使用 CRLF 行尾符检出文件,从而产生与在 Linux 上使用 LF 行尾符的文件不同的文件。由于文件不同,Conan 配方修订版本将与在其他平台(如 Linux)上计算的修订版本不同,从而导致缺少其他修订版本中的相应二进制文件。
Conan 不会以任何方式规范化或更改源文件,这不是它的职责,并且存在破坏事物风险。更改文件的应用程序是源控制,因此这是处理此问题的更正确的位置。有必要指示 Git 使用相同的行尾符进行检出。这可以通过多种方式完成,例如,在项目仓库中添加一个 .gitattributes 文件,内容如下
* text eol=lf
另一种方法是更改 .gitconfig 以全局更改它。现代编辑器(甚至记事本)在 Windows 上可以完美地使用带有 LF 的文件,因此不再需要更改行尾符。
在 conanfile.py 配方中定义依赖项的选项不起作用¶
Conan 深度优先地扩展依赖关系图,这对于实现许多非常特殊的 C/C++ 传播逻辑(头文件、静态和共享库、应用程序、工具要求、测试要求、冲突、覆盖等)至关重要。
这意味着当 conanfile.py 声明如下内容时
class MyPkg(ConanFile):
name = "mypkg"
version = "0.1"
default_options = {"zlib/*:shared": True}
# Or
def requirements(self):
self.requires("zlib/1.3", options={"shared": True})
它不能总是被遵守,并且 zlib 依赖项最终可能会具有不同的 shared=False 选项值。配方中定义的依赖项的选项值仅在以下情况下有效
图中没有其他包依赖于
zlib图中存在依赖于
zlib的其他包,但mypkg/0.1是第一个 require(依赖关系图中的第一个分支)被 require。这意味着requires = "mypkg/0.1", "zlib/1.3"将起作用,并且zlib将是 shared,但requires = "zlib/1.3", "mypkg/0.1"将首先扩展zlib及其默认值,即shared=False,当计算mypkg/0.1时,已经太晚了,无法将zlib更改为shared=True。
如果某个配方由于依赖项的某些选项而根本无法工作,建议在配方中定义一个 validate() 方法,以保证如果由于某种原因上游依赖项没有正确的选项值,它将引发错误。
Conan 可能会显示一些(不保证详尽)这些问题,请仔细阅读输出。
Options conflicts
liba/0.1:myoption=1 (current value)
libc/0.1->myoption=2
It is recommended to define options values in profiles, not in recipes
通常,建议在配置文件中定义选项值,而不是在配方中。配方定义的选项优先级低于配置文件中定义的选项。
即使在使用版本范围时也出现版本冲突¶
在安装依赖项时,可能会出现版本冲突错误消息,例如
...
Version conflict: Conflict between math/1.0.1 and math/1.0 in the graph
此 版本冲突教程 总结了相同包依赖项的不同版本如何在依赖关系图中发生冲突以及如何解决这些冲突。
但是,在某些情况下,冲突并不明显,例如当存在一些混合版本范围和固定依赖项时,例如
def requirements(self):
self.requires("libb/1.0") # requires liba/[>=1.0 <2]
self.requires("libc/1.0") # requires liba/1.0
并且发生 libb/1.0 具有到 liba/[>=1.0 <2] 的传递要求,并且 libc/1.0 需要 liba/1.0,并且存在 liba/1.1 或更高版本的包。在这种情况下,Conan 可能会抛出“版本冲突”错误。
根本原因是解决版本范围定义的所有可能约束的联合兼容性是一个众所周知的 NP-hard 问题,称为 SAT-solver。在 Conan 中评估此 NP-hard 问题的每个假设非常昂贵,因为它通常需要在所有定义的远程仓库中查找版本/修订版本,然后下载这些版本/修订版本的压缩文件,解压缩它们,加载和 Python 解析它们,最后进行所有图计算处理,其中包括通过已经扩展的图传播 C/C++ 要求特征,这些特征可能会产生冲突。这将使问题在实践中变得难以处理,需要等待数小时才能完成。
因此,Conan 不会这样做,而是使用“贪婪”算法,该算法不需要回溯,但仍然会尝试在可能的情况下协调版本范围和固定版本。重要的是要知道 Conan 实施“深度优先”图扩展,按声明的顺序评估 requires。了解这一点可以帮助解决此冲突。在上面的例子中,错误发生是因为首先扩展了 libb/1.0,它找到了对 liba/[>=1.0 <2] 的要求,并且由于之前没有找到对 liba 的其他约束,因此它自由地解析到最新的 liba/1.1。当稍后扩展 libc/1.0 时,它找到了对 liba/1.0 的要求,但为时已晚,因为它将与之前的 liba/1.1 冲突。回溯到之前的假设是使问题变为 NP-hard 的“回溯”部分,因此算法停止并引发冲突。
只需交换 requires 的顺序即可解决此问题
def requirements(self):
self.requires("libc/1.0") # requires liba/1.0
self.requires("libb/1.0") # requires liba/[>=1.0 <2]
如果首先扩展 libc/1.0,它将解析到 liba/1.0。当稍后扩展 libb/1.0 时,其传递要求 liba/[>=1.0 <2] 可以通过之前的 libb/1.0 成功满足,因此它可以成功解析图。
一般最佳实践是
对于相同的依赖项,请尝试在所有地方使用相同的方法:在所有地方使用版本范围,或在特定依赖项中使用固定版本。
保持版本一致。如果使用版本范围,请尝试在所有地方使用相同的版本范围。
首先声明使用固定版本而不是版本范围的依赖项
使用
conan graph info ... --format=html > graph.html图形交互式输出来理解和导航冲突。
Conan 正在将输出重定向到 stderr¶
如 命令参考 中所述,Conan 默认情况下将其日志信息重定向到标准错误输出 (stderr),而命令的实际结果则发送到标准输出 (stdout)。
这样做是为了允许用户轻松地将 Conan 命令的输出重定向到文件或其他进程,而无需将日志信息与实际结果混合在一起。
例如,运行如下命令
$ conan graph info --requires=zlib/1.3.1 --format=json > graph.json
...
======== Computing dependency graph ========
Graph root
cli
Requirements
zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76 - Cache
======== Computing necessary packages ========
Connecting to remote 'conancenter' anonymously
Requirements
zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76:dbb40f41e6e9a5c4a9a1fd8d9e6ccf6d92676c92#8976086f07d37e3f6288e2fccf9650ae - Cache
将创建一个名为 graph.json 的文件,其中包含命令的 JSON 输出,但它不包含任何日志信息,这些信息将打印到控制台。
请注意,这种方法在许多命令行工具(如 git 和 curl)中很常见,它不是 Conan 特有的。
缺少为刚刚使用 conan create 创建的工具包的二进制文件¶
有时,对于一个包,旨在用作其他包的 tool_requires,其配方包含一个 test_package 文件夹,该文件夹需要该工具,如下所示
from conan import ConanFile
class secure_scannerTestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
def build_requirements(self):
self.tool_requires(self.tested_reference_str)
然后,执行包创建的用户使用
$ conan create
...
mytool/0.1: Package created successfully
======== Launching test_package ========
...
======== Computing necessary packages ========
...
ERROR: Missing binary: mytool/0.1
将在 test_package 步骤中找到“缺少二进制文件”错误。这是如何可能的,如果包二进制文件在几行代码之前已经创建了?
conan create 命令默认情况下为“host”上下文创建包,使用“host”配置文件。但是,如果我们要创建的包旨在用作工具,即作为 tool_requires,那么它需要为“build”上下文构建。
如果出于任何原因,“host”和“build”上下文不相同,那么在初始包创建中构建的二进制文件将是“host”上下文的二进制文件,但随后 test_package 将需要它作为 tool_requires(),需要在“build”上下文中需要它,并且由于尚未构建,因此该二进制文件将丢失。
这在交叉编译的例子中很明显,例如,在Windows笔记本电脑上为RaspberryPI使用交叉编译器构建二进制文件。 “构建”环境将是“Windows”,而“宿主”环境将是“RaspberryPI”。 默认情况下,针对“mytool/0.1”的常规 conan create . 将会创建一个针对“RaspberryPI”的二进制文件! 因此,当稍后 test_package 想要将其用作 tool_requires() 时,它会查找“Windows”二进制文件,因为它需要在当前的Windows机器上运行它,即“构建”环境。
--build-require 参数指定了这一点。 当提供此参数时,当前的配方二进制文件将被构建为在“构建”环境中运行
注意
在为用作 tool_requires 的包执行 conan create 时,始终指定 conan create ... --build-require 参数。