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
): 使用 settings、options 和/或self.name
和self.version
来生成不同的构建文件夹和不同的 CMake 预设名称。
self.cpp¶
layout()
方法允许声明 cpp_info
对象,不仅用于最终的包(如在 package_info(self)
方法中使用 self.cpp_info
的传统方法),还可以用于 self.source_folder
和 self.build_folder
。
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
可以定义构建时生成的头文件的位置,例如某些工具生成的头文件存根(stubs)。
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"]
环境变量和配置¶
有些包可能会在其 package_info()
方法中通过 self.buildenv_info
、self.runenv_info
定义一些环境变量。其他包也可以使用 self.conf_info
向其消费者传递配置。
只要这些环境变量或配置的值不需要使用 self.package_folder
,这都不是问题。如果需要使用,那么它们的值对于“source”和“build”布局来说将是不正确的。在 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"))
例如,当包处于 editable 模式时,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
实例。