我们很高兴地宣布 Conan 1.55 发布,并带来了一些重要的新功能和错误修复。首先,CMakeDeps 提供了在消费者端设置属性的功能。此外,我们添加了新的 tools.build:compiler_executables 配置,用于在 CMakeToolchainMesonToolchainAutotoolsToolchain 中定义编译器的可执行文件位置。我们改进了与 NMAKE 的集成,使用了 NMakeDepsNMakeToolchain 生成器。最后,我们启用了环境变量和配置,以便在可编辑包中使用。

CMakeDeps 现在可以自定义其属性

您可能知道,Conan 在几个版本之前引入了属性模型,以添加一种通用方法来将某些信息传递给生成器。Conan 将此模型用于 新的生成器,替换了旧的 cpp_info 属性,如 cpp_info.namescpp_info.filenames(您可以查看从旧模型迁移的指南 此处)。在 1.55 之前,无法覆盖依赖项设置的值。例如,如果一个配方将 cmake_find_mode 设置为 both,Conan 将为该配方的每个使用者生成配置文件和模块文件,但这可能不是该配方的使用者想要的。

从 1.55 开始,Conan 允许从消费者端覆盖 CMakeDeps 的以下属性:cmake_file_namecmake_target_namecmake_find_modecmake_module_file_namecmake_module_target_name。让我们来看一个将 Zlib 作为依赖项的配方的示例。

例如,如果您检查 Conan Center 中的 Zlib 配方,它会在 package_info() 方法中为 CMakeDeps 定义多个属性

...

def package_info(self):
    self.cpp_info.set_property("cmake_find_mode", "both")
    self.cpp_info.set_property("cmake_file_name", "ZLIB")
    self.cpp_info.set_property("cmake_target_name", "ZLIB::ZLIB")
...

假设您有一个使用 Zlib 的应用程序,并且您想更改这些属性,因为您只想生成配置文件,并且您在 CMakeLists.txt 中为 Zlib 使用了不同的目标名称。然后,您可以在 generate() 方法中使用 CMakeDeps.set_property 来覆盖 Zlib 配方中设置的值

from conan.tools.cmake import CMakeDeps

...

class ConsumerRecipe(ConanFile):

    ...

    def generate(self):
        deps = CMakeDeps(self)
        # We want to use zlib target name instead of ZLIB::ZLIB
        deps.set_property("zlib", "cmake_target_name", "zlib")
        # We invalidate whatever value the zlib recipe sets and fallback to
        # the default for Conan
        deps.set_property("zlib", "cmake_find_mode", None)

    ...

关于示例的一些说明

  • 我们显式地将 cmake_target_name 设置为 zlib
  • 我们使用值 None 来设置 cmake_find_mode 属性。如果将属性设置为 None,Conan 将使配方中设置的属性失效,并使用该属性的默认值,在本例中为 config。在本例中,deps.set_property("zlib", "cmake_find_mode", None) 等效于 deps.set_property("zlib", "cmake_find_mode", "config")

您可以在 Conan 文档 中阅读有关 CMakeDeps set_property 方法的更多信息。

新的 tools.build:compiler_executables 配置文件

我们添加了 tools.build:compiler_executables 配置来设置编译器可执行文件的位置。此配置定义了一个字典,其中语言作为键,可执行文件位置作为值。例如,您可以在 Conan 配置文件中使用它

[settings]
os=Macos
arch=x86_64

[conf]
tools.build:compiler_executables={"cpp": "path_to_my_c++_compiler", "c": "path_to_my_c_compiler"}

此配置适用于 CMakeToolchainAutotoolsToolchainMesonToolchain

  • CMakeToolchain:为 CMake 定义相应的 CMAKE_<LANG>_COMPILER 变量。检查文档中接受的键列表 此处
  • AutotoolsToolchain:为 CMake 定义相应的 CMAKE_<LANG>_COMPILER 变量。检查文档中接受的键列表 此处
  • MesonToolchain:定义相应的环境变量(如 CCCXX)。检查文档中接受的键列表 此处

NMakeDeps 和 NMakeToolchain 生成器

我们通过 NMakeDepsNMakeToolchain 生成器改进了与 NMAKE 的集成。这些生成器将生成环境脚本,定义 NMAKE 在构建时使用的环境变量。

  • NMakeDeps 定义 CLLIB_LINK_ 环境变量,注入必要的标志以定位和链接在 requires 中声明的依赖项
  • NMakeToolchain 定义 CL 环境变量,注入从 Conan 设置(如 compiler.cppstd 或 Visual Studio 运行时)推导出的必要标志

启用环境变量和配置以在可编辑包中使用

我们修复了在可编辑模式下但需要配方在开发过程中在 package_info() 方法中设置的信息时可能发生的情况。例如,在可编辑模式下的如下包中可能会发生这种情况


import os
from conan import ConanFile


class ConanPackage(ConanFile):

    ...

    def package_info(self):
        # This is BROKEN if we put this package in editable mode
        self.runenv_info.define_path("MYDATA_PATH", 
                                     os.path.join(self.package_folder, "my/data/path"))

如果处于可编辑模式,这将中断,因为还没有包。对于这些情况,我们可以在 layout() 方法中定义它,就像可以在那里定义 cpp_info 一样。layouts 对象包含 sourcebuildpackage 范围,并且每个范围都包含一个 buildenv_inforunenv_infoconf_info 实例

from conan import ConanFile

class SayConan(ConanFile):
    ...
    def layout(self):
        # The final path will be relative to the self.source_folder
        self.layouts.source.buildenv_info.define_path("MYDATA_PATH", "my/data/path")
        # The final path will be relative to the self.build_folder
        self.layouts.build.buildenv_info.define_path("MYDATA_PATH", "my/data/path")
        # The final path will be relative to the self.build_folder
        self.layouts.build.conf_info.define_path("MYCONF", "my/conf/folder")


除了上面列出的项目之外,还有一些小的错误修复,您可能希望了解。如果是这样,请参阅 更改日志 以获取完整列表。

我们希望您喜欢此版本,并期待您的 反馈