Requirement traits

Traits are properties of a requires clause. They determine how various parts of a dependency are treated and propagated by Conan. Values for traits are usually computed by Conan based on dependency’s package_type, but can also be specified manually.

A good introduction to traits is provided in the Advanced Dependencies Model in Conan 2.0 presentation.

In the example below headers and libs are traits.

self.requires("math/1.0", headers=True, libs=True)


Indicates that there are headers that are going to be #included from this package at compile time. The dependency will be in the host context.


The dependency contains some library or artifact that will be used at link time of the consumer. This trait will typically be True for direct shared and static libraries, but could be false for indirect static libraries that are consumed via a shared library. The dependency will be in the host context.


This dependency is a build tool, an application or executable, like cmake, that is used exclusively at build time. It is not linked/embedded into binaries, and will be in the build context.


This dependency contains some executables, either apps or shared libraries that need to be available to execute (typically in the path, or other system env-vars). This trait can be True for build=False, in that case, the package will contain some executables that can run in the host system when installing it, typically like an end-user application. This trait can be True for build=True, the package will contain executables that will run in the build context, typically while being used to build other packages.


This require will be propagated downstream, even if it doesn’t propagate headers, libs or run traits. Requirements that propagate downstream can cause version conflicts. This is typically True, because in most cases, having 2 different versions of the same library in the same dependency graph is at least complicated, if not directly violating ODR or causing linking errors. It can be set to False in advanced scenarios, when we want to use different versions of the same package during the build.


If True the headers of the dependency will be visible downstream.


If True the libraries to link with of the dependency will be visible downstream.


This requirement is a test library or framework, like Catch2 or gtest. It is mostly a library that needs to be included and linked, but that will not be propagated downstream.


If the recipe wants to specify how the dependency version affects the current package package_id, can be directly specified here.

While it could be also done in the package_id() method, it seems simpler to be able to specify it in the requires while avoiding some ambiguities.

# We set the package_id_mode so it is part of the package_id
self.tool_requires("tool/1.1.1", package_id_mode="minor_mode")

Which would be equivalent to:

def package_id(self):["tool"].minor_mode()


This requires will force its version in the dependency graph upstream, overriding other existing versions even of transitive dependencies, and also solving potential existing conflicts.


The same as the force trait, but not adding a direct dependency. If there is no transitive dependency to override, this require will be discarded. This trait only exists at the time of defining a requires, but it will not exist as an actual requires once the graph is fully evaluated


If the dependency is a direct one, that is, it has explicitly been declared by the current recipe, or if it is a transitive one.


The validate_build() method is used to verify if a configuration is valid for building a package. It is different from the validate() method that checks if the binary package is “impossible” or invalid for a given configuration.

The validate() method should do the checks of the settings and options using the and

The validate_build() method has to use always the self.settings and self.options:

from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
class myConan(ConanFile):
    name = "foo"
    version = "1.0"
    settings = "os", "arch", "compiler"
    def package_id(self):
        # For this package, it doesn't matter the compiler used for the binary package
    def validate_build(self):
        # But we know this cannot be build with "gcc"
        if self.settings.compiler == "gcc":
            raise ConanInvalidConfiguration("This doesn't build in GCC")
    def validate(self):
        # We shouldn't check here the because it has been removed in the package_id()
        # so it doesn't make sense to check if the binary is compatible with gcc because the compiler doesn't matter