我们很高兴地宣布 Conan 1.46 已经发布,并带来了一些重要的新功能和错误修复。我们通过添加新的 XcodeToolchain 生成器和 XcodeBuild 构建辅助工具改进了 Xcode 支持,这些工具补充了 Conan 1.42 中引入的 XcodeDeps 生成器。此外,Conan 配置系统 已经得到了显著改进,允许更强大的配置文件和配方中 Conan “conf” 的操作,并添加了 jinja2 模板语法支持。此外,我们还添加了新的 Git 辅助工具,以便在 export() 方法中直接使用以捕获 Git URL 和提交,并在 source() 方法中克隆和检出 Git 仓库。

新的 XcodeBuild 和 XcodeToolchain 工具

现在,您可以使用 XcodeToolchainXcodeBuild 新辅助工具以及 XcodeDeps 在 Conan 配方中构建您的 Xcode 项目。让我们看看如何创建一个使用 Xcode 构建系统的包。假设您在 Xcode 中生成了一个简单的“hello world”库项目,您希望使用 Conan 打包它,并且它具有以下结构

├── HelloLibrary.xcodeproj
└── src
    ├── hello.cpp
    └── hello.hpp

您可以使用类似于以下使用 XcodeBuild 构建库和 XcodeToolchain 将信息从 Conan 设置传递到 Xcode 构建系统的 conanfile.py 轻松地为该库创建 Conan 包


import os
from conan import ConanFile
from conan.tools.apple import XcodeBuild
from conan.tools.files import copy

class HelloLib(ConanFile):
    name = "hello"
    version = "1.0"
    settings = "os", "compiler", "build_type", "arch"
    generators = "XcodeToolchain"
    exports_sources = "HelloLibrary.xcodeproj/*", "src/*"

    def build(self):
        xcode = XcodeBuild(self)
        xcode.build("HelloLibrary.xcodeproj")

    def package(self):
        copy(self, "*/libhello.a", src=self.build_folder, 
             dst=os.path.join(self.package_folder, "lib"), 
             keep_path=False)
        copy(self, "src/hello.hpp", src=self.build_folder, 
             dst=os.path.join(self.package_folder, "lib"), 
             keep_path=False)

    def package_info(self):
        self.cpp_info.libs = ["hello"]

在创建包之前,您必须将 Conan 生成的 .xcconfig 文件添加到 Xcode 项目中。让我们为 ReleaseDebug 配置生成它们

$ conan install . -s build_type=Release
$ conan install . -s build_type=Debug

将生成的 .xcconfig 文件添加到 Xcode 项目中,并在 Info/Configurations 部分中,为这两个配置选择 conan_config

Set configuration files for Debug and Release

现在,您可以为 DebugRelease 配置创建库

$ conan create . -s build_type=Debug
$ conan create . -s build_type=Release

当 Conan 执行 build() 方法时,XcodeBuild 辅助工具会调用 Xcode 构建系统来构建库。请查看文档以获取 XcodeToolchainXcodeBuildXcodeDeps 的完整参考。

改进的“conf”系统

Conan 配置系统中有一些改进

  • 支持 global.conf 配置文件中的 jinja2 模板。例如,这对于将并行构建作业数设置为系统配置中定义的值很有用

      ...
      # Using all the cores automatically
      tools.build:jobs={{os.cpu_count()}}
      ...
    

Python ossystem 模块在模板上下文中可用。

  • 支持配置中的不同数据类型。现在,您可以在设置配置值时使用 Python 数据类型。Conan 将使用 Python 内置的 eval() 函数解释这些值。您可以使用字符串、布尔值、整数、列表和字典。例如
# String
tools.microsoft.msbuild:verbosity=Diagnostic
# Boolean
tools.system.package_manager:sudo=True
# Integer
tools.microsoft.msbuild:max_cpu_count=2
# List of values
user.myconf.build:listvalue=["value1", "value2"]
# Dictionary
tools.microsoft.msbuildtoolchain:compile_options={"ExceptionHandling": "Async"}
  • 配置文件中配置值的新运算符。您可以使用它们来追加 (=+)、追加 (+=) 或重置 (=!) 配置文件 [conf] 部分中的配置值。
[settings]
...

[conf]
# Define the value => ["value1"]
user.myconf.build:listvalue=["value1"]

# Append the value ["value2"] => ["value1", "value2"]
user.myconf.build:listvalue+=["value2"]

# Prepend the value ["value0"] => ["value0", "value1", "value2"]
user.myconf.build:listvalue=+["value0"]

# Unset the value
user.myconf.build:listvalue=!
  • conf_info 对象中可用的新方法 用于在 配方 中操作配置值。您可以使用不同的方法获取、定义或操作配置值
import os
from conans import ConanFile

class Pkg(ConanFile):
    name = "pkg"

    def package_info(self):
        # Setting values
        self.conf_info.define("tools.microsoft.msbuild:verbosity", "Diagnostic")
        # Getting values
        self.conf_info.get("tools.microsoft.msbuild:verbosity")  # == "Diagnostic"
        # Modifying configuration list-like values
        self.conf_info.append("user.myconf.build:listvalue", "value1")

有关可用方法的完整参考,请 查看 Conan 文档

新的 conan.tools.scm.Git 工具

Conan 中有一个 新的工具可用,用于在 conan.tools.scm 模块 中管理 Git 仓库。使用此工具,配方可以添加与 scm 功能 提供的功能相同的功能,但更灵活和明确(请注意,scm 功能将在 Conan 2.0 中删除)。

让我们看看如何使用新辅助工具的示例。我们可以采用之前用于定义 Xcode 包的配方,该配方具有以下结构

├── conanfile.py
├── HelloLibrary.xcodeproj
└── src
    ├── hello.cpp
    └── hello.hpp

我们将更改配方以从 Git 仓库获取源代码。新配方可能如下所示


import os
from conan import ConanFile
from conan.tools.apple import XcodeBuild
from conan.tools.files import copy
from conan.tools.scm import Git
from conan.tools.files import update_conandata


class HelloLib(ConanFile):

    ...

    def layout(self):
        self.folders.source = "."

    def export(self):
        git = Git(self, self.recipe_folder)
        scm_url, scm_commit = git.get_url_and_commit()
        # we store the current URL and commit in conandata.yml
        update_conandata(self, {"sources": {"commit": scm_commit, "url": scm_url}})

    def source(self):
        # we recover the saved URL and commit from conandata.yml
        git = Git(self)
        sources = self.conan_data["sources"]
        # get the sources from the URL and commit
        git.clone(url=sources["url"], target=".")
        git.checkout(commit=sources["commit"])

    def build(self):
        xcode = XcodeBuild(self)
        xcode.build("HelloLibrary.xcodeproj")

    ...

最重要的部分定义在 conanfile 的 export()source() 方法中

  • exports() 方法中,我们使用 get_url_and_commit() 获取 Git 仓库的当前 提交URL。然后,update_conandata() 辅助工具用于将此信息与配方一起保存到缓存中的 conandata.yml 文件中。

  • source() 方法中,我们检索存储在 conandata.yml 文件中的信息以克隆仓库 URL 并检出 提交

如您所见,这种在 Conan 配方中与 Git 仓库交互的方式非常灵活和明确。如果您想查看 Git 工具的所有可用方法,请 查看 Conan 文档



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

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