layout()

In the layout() method you can adjust self.folders and self.cpp.

self.folders

  • self.folders.source (Defaulted to ""): Specifies a subfolder where the sources are. The self.source_folder attribute inside the source(self) and build(self) methods will be set with this subfolder. The current working directory in the source(self) method will include this subfolder. The export_sources and exports sources will also be copied to the root source directory. It is used in the cache when running conan create (relative to the cache source folder) as well as in a local folder when running conan build (relative to the local current folder).
  • self.folders.build (Defaulted to ""): Specifies a subfolder where the files from the build are. The self.build_folder attribute and the current working directory inside the build(self) method will be set with this subfolder. It is used in the cache when running conan create (relative to the cache source folder) as well as in a local folder when running conan build (relative to the local current folder).
  • self.folders.generators (Defaulted to ""): Specifies a subfolder in which to write the files from the generators and the toolchains. In the cache, when running conan create, this subfolder will be relative to the root build folder and when running the conan install command it will be relative to the current working directory.
  • self.folders.root (Defaulted to None): Specifies a parent directory where the sources, generators, etc., are located specifically when the conanfile.py is located in a separated subdirectory. Check this example on how to use self.folders.root.
  • self.folders.subproject (Defaulted to None): Specifies a subfolder where the conanfile.py is relative to the project root. This is particularly useful for layouts with multiple subprojects
  • self.folders.build_folder_vars (Defaulted to None): Use settings and options to produce a different build folder and different CMake presets names.

self.cpp

The layout() method allows to declare cpp_info objects not only for the final package (like the classic approach with the self.cpp_info in the package_info(self) method) but for the self.source_folder and self.build_folder.

The fields of the cpp_info objects at self.cpp.build and self.cpp.source are the same described here. Components are also supported.

Properties to declare all the information needed by the consumers of a package: include directories, library names, library paths… Used both for editable packages and regular packages in the cache.

There are four instances available, only while running the following methods:

  • At layout(self) method:
    • self.cpp.package: For a regular package being used from the Conan cache.

    • self.cpp.source: For “editable” packages, to describe the artifacts under self.source_folder.

    • self.cpp.build: For “editable” packages, to describe the artifacts under self.build_folder.

      def layout(self):
          ...
          self.folders.source = "src"
          self.folders.build = "build"
      
          # In the local folder (before a conan create) 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"]
      

See also

Read more about the usage of the layout() in this tutorial and Conan package layout here.

Environment variables and configuration

There are some packages that might define some environment variables in their package_info() method via self.buildenv_info, self.runenv_info. Other packages can also use self.conf_info to pass configuration to their consumers.

This is not an issue as long as the value of those environment variables or configuration do not require using the self.package_folder. If they do, then their values will not be correct for the “source” and “build” layouts. Something like this will be broken when used in editable mode:

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"))

When the package is in editable mode, for example, self.package_folder is None, as obviously there is no package yet. The solution is to define it in the layout() method, in the same way the cpp_info can be defined there:

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")

The layouts object contains source, build and package scopes, and each one contains one instance of buildenv_info, runenv_info and conf_info.