layout()

在 layout() 方法中,您可以调整 self.foldersself.cpp

self.folders

  • self.folders.source (默认为 ""):指定源文件所在的子文件夹。在 source(self)build(self) 方法内部,self.source_folder 属性将设置为此子文件夹。source(self) 方法中的当前工作目录将包含此子文件夹。export_sourcesexports 源文件也将被复制到根源目录。它在运行 conan create 时(相对于缓存源文件夹)在缓存中使用,并在运行 conan build 时(相对于本地当前文件夹)在本地文件夹中使用。

  • self.folders.build (默认为 ""):指定构建文件所在的子文件夹。self.build_folder 属性和 build(self) 方法内部的当前工作目录将设置为此子文件夹。它在运行 conan create 时(相对于缓存源文件夹)在缓存中使用,并在运行 conan build 时(相对于本地当前文件夹)在本地文件夹中使用。

  • self.folders.generators (默认为 ""):指定一个子文件夹,用于写入生成器和工具链的文件。在缓存中,当运行 conan create 时,此子文件夹将相对于根构建文件夹;当运行 conan install 命令时,它将相对于当前工作目录。

  • self.folders.root (默认为 None):指定一个父目录,其中包含源文件、生成器等,特别是在 conanfile.py 位于单独的子目录中时。请查看 此示例,了解如何使用 self.folders.root

  • self.folders.subproject (默认为 None):指定 conanfile.py 相对于项目根目录的子文件夹。这对于 具有多个子项目的布局 尤其有用。

  • self.folders.build_folder_vars (默认为 None):使用设置、选项和/或 self.nameself.version 来生成不同的构建文件夹和不同的 CMake 预设名称。

self.cpp

layout() 方法不仅允许为最终包声明 cpp_info 对象(如在 package_info(self) 方法中使用 self.cpp_info 的经典方法),还允许为 self.source_folderself.build_folder 声明。

self.cpp.buildself.cpp.source 中的 cpp_info 对象的字段与 此处 描述的相同。也支持组件。

用于声明包消费者所需的所有信息的属性:包含目录、库名称、库路径等……既用于 可编辑包,也用于缓存中的常规包。

layout() 方法中有三个可用对象

  • self.cpp.package:用于从 Conan 缓存中使用的常规包。描述最终包的内容。与 package_info() 方法中的 self.cpp_info 完全相同,但位于 layout() 方法中。

  • self.cpp.source:用于“可编辑”包,描述 self.source_folder 下的构件。这些可以包括:

    • self.cpp.source.includedirs:指定开发时头文件的位置,例如典型的 src 文件夹,在打包到 include 包文件夹之前。

    • self.cpp.source.libdirsself.cpp.source.libs 可以描述库已提交到源代码管理的情况(希望是例外情况),因此它们不是构建结果的一部分,而是源代码的一部分。

  • self.cpp.build:用于“可编辑”包,描述 self.build_folder 下的构件。

    • self.cpp.build.libdirs 将表示构建的库在打包之前的位置。它们通常可以在诸如 x64/Releaserelease64 之类的文件夹中找到。

    • self.cpp.build.includedirs 可以定义在构建时生成的头文件的位置,例如某些工具生成的头文件存根。

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

    # In the local folder (when the package is in development, or "editable") the artifacts can be found:
    self.cpp.source.includedirs = ["my_includes"]
    self.cpp.build.libdirs = ["lib/x86_64"]
    self.cpp.build.libs = ["foo"]

    # In the Conan cache, we packaged everything at the default standard directories, the library to link
    # is "foo"
    self.cpp.package.libs = ["foo"]

另请参阅

  • 在此 教程 和 Conan 包布局中阅读更多关于 layout() 的用法。

  • 此处.

环境变量与配置

有些包可能会通过 self.buildenv_infoself.runenv_info 在其 package_info() 方法中定义一些环境变量。其他包也可以使用 self.conf_info 将配置传递给其消费者。

只要这些环境变量或配置的值不需要使用 self.package_folder,这就不是问题。如果需要,那么它们的值对于“源”和“构建”布局将不正确。在 editable 模式下使用时,类似这样的情况将会失效

import os
from conan import ConanFile

class SayConan(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"))

当包处于可编辑模式时,例如,self.package_folderNone,因为显然还没有包。解决方案是在 layout() 方法中定义它,就像 cpp_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/source/data/path")
        # The final path will be relative to the self.build_folder
        self.layouts.build.buildenv_info.define_path("MYDATA_PATH2", "my/build/data/path")
        # The final path will be relative to the self.build_folder
        self.layouts.build.conf_info.define_path("MYCONF", "my_conf_folder")

layouts 对象包含 sourcebuildpackage 范围,每个范围都包含一个 buildenv_inforunenv_infoconf_info 实例。