包处于可编辑模式时的自定义布局可以通过不同方式定义:

配方定义布局

当配方不在本地缓存中时,可以在其package_info() 方法中定义自定义布局,如下所示:

  1. from conans import ConanFile
  2. class Pkg(ConanFile):
  3. settings = "build_type"
  4. def package_info(self):
  5. if not self.in_local_cache:
  6. d = "include_%s" % self.settings.build_type
  7. self.cpp_info.includedirs = [d.lower()]

当使用build_type=Debug conan设置时,会将include目录映射到examples/features/editable/cmake/say/include_debug,如果build_type=Release,则将include目录映射到examples/features/editable/cmake/say/include_release。 同样,其他目录(libdir,bindirs等)也可以使用任何逻辑进行自定义,这些逻辑对于不同的OS,构建系统等是不同的。

  1. from conans import ConanFile
  2. class Pkg(ConanFile):
  3. settings = "os", "compiler", "arch", "build_type"
  4. def package_info(self):
  5. if not self.in_local_cache:
  6. if self.settings.compiler == "Visual Studio":
  7. # NOTE: Use the real layout used in your VS projects, this is just an example
  8. self.cpp_info.libdirs = ["%s_%s" % (self.settings.build_type, self.settings.arch)]

例如,这会将库目录定义为examples/features/editable/cmake/say/Release_x86_64。 这只是一个示例,VS使用的实际布局将有所不同。

布局文件

无需更改配方文件以匹配本地布局,而是可以在单独的文件中定义布局。 如果您有大量具有相同结构的库,那么这特别有用,因此您可以编写一次并将其用于多个软件包。
布局文件是ini文件,但是在解析它们之前,Conan使用Jinja2模板引擎传递设置,选项和当前参考对象,因此可以向文件添加逻辑:

  1. [build_folder]
  2. build/{{settings.build_type}}
  3. [source_folder]
  4. src
  5. [includedirs]
  6. src
  7. [libdirs]
  8. build/{{settings.build_type}}/lib

您可以查看 Jinja2 文档,以了解有关其强大语法的更多信息。
该文件可以使用包参考来定制特定包的逻辑:

  1. [say/0.1@user/channel:build_folder]
  2. {% if settings.compiler == "Visual Studio" %}
  3. build
  4. {% else %}
  5. build/{{settings.build_type}}
  6. {% endif %}
  7. [build_folder]
  8. build/{{settings.arch}}/{{settings.build_type}}
  9. [source_folder]
  10. src
  11. [includedirs]
  12. src
  13. [libdirs]
  14. build/{{settings.build_type}}/lib
  15. [bindirs]
  16. build/{{settings.build_type}}/bin

这种布局将为say和其他处于可编辑模式的软件包定义src include目录。 另外,build_folder仅对say/0.1@user/channel软件包具有条件。 根据编译器,它将使用特定的路径。
在每种情况下,将受可编辑模式影响的目录包括includeirslibdirsbindirsresdirssrcdirsbuilddirs,所有这些都在cpp_info字典中声明。 该词典中的其余值将不会被修改。 因此,仍将使用在package_info()中定义的库中的cflagsdefines,库名。
默认情况下,所有文件夹路径都相对于可编辑包的conanfile.py所在的目录(这是用于创建链接的路径)的相对路径,尽管它们也允许绝对路径。

指定布局文件

布局文件在conan editable add命令中指定,作为额外的参数:

  1. $ cd examples/features/editable/cmake/say
  2. $ conan editable add . say/0.1@user/channel --layout=layout_vs

首先将相对于当前目录查找该layout_vs文件(路径也可以是绝对路径)。 如果找到,将使用它。 可以将这些布局添加到源存储库中,因此在克隆后总是很容易找到它们。
如果找不到相对于当前目录的指定布局,则将在.conan/layouts文件夹的Conan缓存中查找该布局。 具有一个可以与团队共享并使用conan config install安装的布局的单一定义,这非常方便。
如果未指定任何参数,conan editable add命令将尝试使用本地缓存中的.conan/layouts/default布局。
您可以通过将不同的参数传递给conan editable add的来切换布局文件。

评估顺序及优先级

了解有关布局定义的评估顺序和优先级非常重要:

  • 将始终执行的第一件事是配方package_info()。这将定义标志,定义以及布局文件夹的一些值:includedirs,libdirs等。
  • 如果定义了布局文件,无论是显式定义还是使用隐式.conan/layouts/default定义,conan都会根据其程序包引用查找匹配项。
  • 如果找到匹配项,则是由于[includedirs]之类的全局定义,还是由于[pkg/version@user/channel:includedirs]之类的匹配项,因此布局文件夹(includedirs,libdirs,resdirs,builddirs,bindirs)将是无效并由文件中定义的替换。
  • 如果找到特定的匹配项,例如[pkg/version@user/channel:includedirs],则应该也定义了其特定的[pkg/version@user/channel:libdirs]等。找到匹配项后将不会应用。
  • 如果找不到匹配项,则将遵循package_info()中定义的布局文件夹的原始值。
  • 要使用的布局文件是在conan editable add 时定义的。如果在**conan editable add**之后添加.conan/layouts/default文件,则将完全不使用该文件。