Conan 1.28 已经发布。它包含了大量的新功能,确实让人感觉到了进步!锁文件基本上进行了彻底的修改,所以我们先从这里开始。

锁文件改进

无论您过去是否阅读过关于锁文件的文章,这些变化都值得您重新阅读所有锁文件文档(对于那些正在使用或计划使用锁文件的人来说)。

锁文件文档

首先,命令本身已经完全改变。以前是

    conan graph lock

现在是

    conan lock

接下来,在使用 conan create 命令与锁文件一起使用时,现在需要一个新的参数。如果您传递 --lockfile 参数,则还必须传递 --lockfile-out 参数。用户可以为两者传递相同的文件名,有效地覆盖原始锁文件,但在许多情况下,用户希望它们不同。以前的行为在许多情况下令人困惑。

接下来,添加了一个名为“基础锁文件”的新概念。基础锁文件仅捕获依赖关系图的拓扑结构。具体来说,它锁定包含 name/version@user/channelref 字段。如果启用了修订版本,它还会锁定包含“配方修订版本”的 rrev 字段。它不会捕获包 ID 或包修订版本字段。这在解决持续集成工作流中遇到的常见竞争条件方面特别有用,这些工作流执行多个构建。通常,每个构建都在一个单独且干净的工作区中执行,并在不同的时间开始构建。即使“并行”执行,它们也可能略有偏差。问题在于,其他作业可以随时上传依赖项的新版本或修订版本。因此,在不同的工作区中多次运行 conan lock,即使仅相隔几秒钟,也可能导致不同的配置锁定同一依赖项的不同修订版本。现在,CI 作业可以通过使用 --base 标志调用 conan lock 来开始。这将生成一个仅锁定依赖项名称和版本的“通用”锁文件。此锁文件的副本可以传递给后续每个构建阶段中的 conan create,这会将特定于配置的字段和信息添加到副本中。

此“基础锁文件”概念导致了下一个主要改进:更严格地执行“锁定”值,使锁文件中的每个字段都“真正不可变”。这并不是说锁文件不能更新(锁文件可以并且会被更新)。规则如下:锁文件中的空字段可以填充,但一旦字段具有值,则该值不能更改。基础锁文件是等待未来命令设置值的未填充字段的一个很好的例子。此改进非常重要,因为最近发现,在以前的版本中,有几种方法可以生成完全无效且无法构建的锁文件。从现在开始,这种情况应该不再可能发生。

新属性:provides、required_conan_version、recipe_folder、deprecated

根据用户的特性请求,Conanfile.py 学习了一些新属性。如果您最近没有查看列表,也许值得重新看一下。

conanfile.py 属性文档

provides 是一个非常重要的新的属性,对于处理已知会产生冲突的包很有帮助。举一个简单的例子,我们可以看看三个独立的库/包:libjpeglibjpeg-turbomozjpeg。它们都是同一库的备选实现,生成相同的符号。如果您尝试同时编译和链接所有三个库,则将违反 C++ 的“单定义规则”(ODR),并收到致命的编译器错误。通过将此属性添加到 Conan,我们可以在编译开始之前根据属性检测到违规行为,从而在许多情况下节省大量时间。

required_conan_version 使用户能够声明配方所需的 Conan 的最低版本。您可能知道,Conan 在此版本之前已经支持 required_conan_version 的声明,但以前这只能在 conan.conf 中全局定义。该功能将继续存在并得到支持,因为它在企业环境中非常有用,可以确保所有开发人员和构建机器根据需要更新。这里的主要变化是它现在可以在配方级别指定。如果您熟悉 CMake 构建系统,您可能会认识到这类似于函数 cmake_minimum_required()。它们都出于同样的原因而有意义。Conan 和 CMake 都在快速发展,在配方文件中使用新功能会导致混乱的错误和中断,当旧版本尝试处理它们时。展望未来,可以使用此属性正确记录和明确不兼容性。

recipe_folder 只是使配方更容易以编程方式引用当前正在从中构建 conanfile.py 的目录。这在许多情况下对自定义生成器、python 需求和其他棘手的情况很有帮助。多年来,此功能已被多次请求,因此我们很高兴在本版本中完成它。

deprecated 表示配方以某种方式过时,并导致打印警告消息。如果存在替换配方,则可以在 deprecated 字段中命名它,并且该字符串将打印在给用户的警告消息中。

改进的 Windows 上 Clang 支持

在本版本中,我们终于能够合并一个已挂起近 1 年的 PR。diff 仅显示一个文件中的 6 行已更改,但这掩盖了对其进行的研究、考虑和讨论的规模。有了它,默认的 settings.yml 现在包含一些必要的更改,以支持更多 Windows 上 Clang 的用例。

此 PR 悬而未决如此之久的原因是,Clang 对以正式的方式(即 Conan 所做的那样)建模 ABI 兼容性提出了多个独特且具有挑战性的问题。首先,Clang 用户可以从两个可执行文件中选择:clang.execlang-cl.exe。它们可以生成相同/兼容的二进制文件,但 clang.exe 也可以生成不兼容的二进制文件。接下来,在 Linux 上,Clang 始终有一个名为 -stdlib 的标志供用户定义要链接的标准库。在 Windows 上,Clang 链接到 Microsoft 的 STL,这使得此标志变得无关紧要。相反,在 Windows 上,Clang(就像 CL.exe 一样)允许用户选择要链接的 MSVC 运行时(MT/MD 等)。此概念在 Linux 上的 Clang 中不存在。因此,当前的 PR 为 clang 编译器添加了 runtime 子集,并通过添加 None 作为有效选择,使 libcxx 的现有子集成为可选。

需要注意的是,这些新设置虽然是向前迈出的重要一步,但这仅仅是第一步。为 Windows 上的 Clang 提供真正强大且一流的体验需要在多个版本中采用迭代方法,并在此过程中收集反馈(这就是我们在这里处理大多数事情的方式)。我们已经在努力进行一些后续步骤,但用户对此第一组更改的反馈将非常有帮助。

支持 pkg-config 生成器中的组件

几个版本之前,我们发布了“包组件”概念的第一个草案,其中一个包可以将其提供的功能分离成组件,这些组件可以被下游包选择性地使用。此后不久,我们在 CMake 系列生成器中添加了对这些组件的支持。在本版本中,我们向 pkg-config 生成器添加了支持。

定义生成器文件名(仅限 CMake)

所有生成器都使用以下命名约定生成生成的文件:conanbuildinfo.xyz,其中 xyz 是与相应构建系统或平台关联的典型文件扩展名。这是不可配置的。在过去的一年中,出于几个不同的原因,重新审视了此约定。此特定版本的更改是为了使配方作者能够使用 cpp_info 设置生成的构建系统文件。可以使用新的 filenames 字典变量在每个生成器的基础上设置名称,其中键名对应于您要为其指定文件名的生成器。

示例

    self.cpp_info.filenames["cmake"] = "my_conan_dependency_info.cmake"

文档

更多 conanfile.py init() 方法用例

我们意识到在 1.24 中发布的用于 python_requiresinit() 方法对于其他动态属性逻辑(例如从某些其他数据文件设置许可证/描述等)更为有用。我们在此处记录了一个示例

        # data.json
        # {"license": "MIT", "description": "My library", "author": "Me"}
        def init(self):
            data = load(os.path.join(self.recipe_folder, "data.json"))
            d = json.loads(data)
            self.license = d["license"]
            self.description = d["description"]
            self.author = d["author"]

其他功能和修复

还有一些值得一提的项目。我们通过 Conan V2 CLI 迈出了几步,改进了 apt 包管理器的检测,并扩展了一些生成器兼容性。这包括使 venv 生成器能够在非 Windows 平台上生成 powershell,并使 msbuild 生成器能够在 Linux 上运行。

像往常一样,我们无法在本博文中介绍发布中的所有内容,因此请访问更改日志以获取完整列表。



像往常一样,我们希望您喜欢此版本,并期待您提供反馈