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 three objects available in the layout() method:

  • self.cpp.package: For a regular package being used from the Conan cache. Describes the contents of the final package. Exactly the same as in the package_info() self.cpp_info, but in the layout() method.

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

    • self.cpp.source.includedirs: To specify where the headers are at development time, like the typical src folder, before being packaged in the include package folder.

    • self.cpp.source.libdirs and self.cpp.source.libs could describe the case where libraries are committed to source control (hopefully exceptional case), so they are not part of the build results, but part of the source.

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

    • self.cpp.build.libdirs will express the location of the built libraries before being packaged. They can often be found in a folder like x64/Release, or release64 or similar.

    • self.cpp.build.includedirs can define the location of headers that are generated at build time, like headers stubs generated by some tools.

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

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.