requirements()

The requirements() method is used to specify the dependencies of a package.

def requirements(self):
    self.requires("zlib/1.2.11")

For simple cases the attribute syntax can be used, like requires = "zlib/1.2.11".

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

headers

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.

libs

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.

build

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.

run

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.

visible

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.

transitive_headers

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

transitive_libs

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

test

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.

package_id_mode

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):
  self.info.requires["tool"].minor_mode()

force

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 downstream consumer’s force traits always have higher priority.

override

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

Note

Best practices

The force and override traits to solve conflicts are not recommended as a general versioning solution, just as a temporary workaround to solve a version conflict. Its usage should be avoided whenever possible, and updating versions or version ranges in the graph to avoid the conflicts without overrides and forces is the recommended approach.

direct

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.

options

It is possible to define options values for dependencies as a trait:

self.requires("mydep/0.1", options={"dep_option": "value"})

Warning

Defining options values in recipes does not have strong guarantees, please check this FAQ about options values for dependencies. The recommended way to define options values is in profile files.

package_type trait inferring

Some traits are automatically inferred based on the value of the package_type if not explicitly set by the recipe.

  • application: headers=False, libs=False, run=True

  • shared-library: run=True

  • static-library: run=False

  • header-library: headers=True, libs=False, run=False

  • build-scripts: headers=False, libs=False, run=True, visible=False

Additionally, some additional traits are inferred on top of the above mentioned based on the package_type of the dependant:

  • header-library: transitive_headers=True, transitive_libs=True

Default traits for each kind of requires

Each kind of requires sets some additional traits by default on top of the ones stated in the last section. Those are:

  • requires: build=False

  • build_requires: headers=False, libs=False, build=True, visible=False

  • tool_requires: headers=False, libs=False, build=True, run=True, visible=False

  • test_requires: headers=True, libs=True, build=False, visible=False, test=True