FAQ

另请参阅

Conan 背后有一个强大的社区,用户在 Cpplang Slack 中互相帮助。 请在 #conan 频道中加入我们!

故障排除

错误:缺少预构建的软件包

当安装软件包(使用 conan installconan create)时,您可能会收到如下错误

ERROR: Missing binary: zlib/1.2.11:b1d267f77ddd5d10d06d2ecf5a6bc433fbb7eeed

zlib/1.2.11: WARN: Can't find a 'zlib/1.2.11' 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.2.11'. 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.2.11' argument

More Info at 'https://docs.conan.org.cn/en/2/knowledge/faq.html#error-missing-prebuilt-package'

这意味着软件包配方 zlib/1.2.11 存在,但由于某些原因,没有适用于您当前设置或选项的预编译软件包。 可能是软件包创建者根本没有构建和共享预构建的软件包,而只上传了软件包配方,或者他们只为某些平台或编译器提供软件包。 例如,软件包创建者从 apple-clang 11 的配方构建了软件包,但您正在使用 apple-clang 14。您可能还想检查您的 package ID mode,因为它可能会影响可用的软件包。

默认情况下,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.ymlsettings_user.yml 可以使用 conan config install 命令轻松共享),一切都会正常工作。 settings.yml 文件只是一种机制,以便用户就典型设置的通用拼写达成一致。 此外,如果您认为某些设置对许多其他 conan 用户有用,请将其作为 issue 或 pull request 提交,以便将其包含在未来的版本中。

一些内置的 helper 或集成(例如 CMakeCMakeToolchain)可能无法理解新添加的设置,不要使用它们,如果您为现有设置添加了一些新的意外值,甚至可能会失败。 诸如 CMake 之类的 helper 只是将 conan 设置转换为相应的构建系统语法和命令行参数的简单实用程序,因此可以使用您自己的 helper 进行扩展或替换,这将处理您自己的私有设置。

错误: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 选项值结束。 此 in-recipe 选项值定义仅在以下情况下有效

  • 没有其他软件包依赖于图中的 zlib

  • 图中有其他软件包依赖于 zlib,但 mypkg/0.1 是第一个 require(依赖关系图中的第一个分支)。 这意味着 requires = "mypkg/0.1", "zlib/1.3" 将起作用并将 zlib 作为共享,但 requires = "zlib/1.3", "mypkg/0.1" 将首先扩展 zlib 及其默认值,即 shared=False,并且当计算 mypkg/0.1 时,更改 zlibshared=True 将为时已晚。

如果某些配方根本无法使用依赖项的某些选项,建议在配方中定义一个 validate() 方法,以保证如果由于某种原因上游依赖项没有正确的选项值,它将引发一个错误。

Conan 可能会在 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 难题,称为 SAT 求解器。 在 Conan 中评估此 NP 难题中的每个假设非常昂贵,因为它通常需要在所有定义的远程仓库中查找版本/修订版本,然后下载此类版本/修订版本的压缩文件,解压缩它们,加载并进行 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 难题,因此算法在那里停止并引发冲突。

这可以通过交换 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] 可以被之前的 liba/1.0 成功满足,因此它可以成功解析图。

通用最佳实践如下:

  • 对于同一个依赖项,尽量在所有地方使用相同的方法:对该特定依赖项使用版本范围,或者在所有地方使用固定版本。

  • 保持版本对齐。如果使用版本范围,尽量在所有地方使用相同的版本范围。

  • 首先声明使用固定版本的依赖项,而不是版本范围

  • 使用 conan graph info ... --format=html > graph.html 图形交互输出,以理解和导航冲突。