layout()¶
在 layout() 方法中,您可以调整 self.folders
和 self.cpp
。
self.folders¶
self.folders.source (默认值
""
): 指定源代码所在的子文件夹。`source(self)` 和 `build(self)` 方法中的self.source_folder
属性将设置为此子文件夹。`source(self)` 方法中的当前工作目录将包含此子文件夹。`export_sources` 和 `exports` 源也将被复制到根源目录。在运行 conan create 时(相对于缓存的源文件夹)以及在本地文件夹中运行 conan build 时(相对于本地当前文件夹),它都会在缓存中使用。self.folders.build (默认值
""
): 指定构建文件所在的子文件夹。`build(self)` 方法中的self.build_folder
属性和当前工作目录将设置为此子文件夹。在运行 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.name
和self.version
来生成不同的构建文件夹和不同的 CMake 预设名称。
self.cpp¶
layout() 方法不仅允许声明最终包的 cpp_info
对象(类似于在 `package_info(self)` 方法中使用 `self.cpp_info` 的传统方法),还允许声明 `self.source_folder` 和 `self.build_folder` 的 cpp_info
对象。
在 `self.cpp.build` 和 `self.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.libdirs
和self.cpp.source.libs
可以描述库已提交到版本控制的情况(希望是例外情况),因此它们不是构建结果的一部分,而是源的一部分。
self.cpp.build: 用于“可编辑”包,以描述 `self.build_folder` 下的工件。
self.cpp.build.libdirs
将表示构建的库在打包之前的路径。它们通常可以在类似 `x64/Release` 或 `release64` 或类似的文件夹中找到。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"]
环境变量和配置¶
有些包可能通过 `self.buildenv_info`、`self.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_folder` 为 `None`,因为显然还没有包。解决方法是在 `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` 对象包含 `source`、`build` 和 `package` 作用域,每个作用域都包含一个 `buildenv_info`、`runenv_info` 和 `conf_info` 实例。