Conan migration guide to 2.0
Conan team is working hard on the next major release. We’ve been gathering feedback from the community about our features and we think it’s time to break some default behaviors, clean the codebase and add space for new developments. Development is ongoing and the Conan 2.0 Tribe is having discussions about it.
Conan 2.0-alpha is already released. You can install the latest Conan Alpha version from PyPI doing:
$ pip install conan --pre
The documentation for 2.0 is still far from being complete, but we are working on it and you can access it with the right version label.
This section summarizes some of the necessary changes during Conan 1.X to be ready to upgrade to Conan 2.0:
Update the syntax of your Conanfile
Use the
from conan import ConanFile
import instead of the legacyfrom conans ...
(note the plural)Do not use dictionary expressions in your recipe
settings
definition (likesettings = {"os": ["Windows", "Linux"]}
. This way of limiting supported configurations by one recipe will be removed. Use thevalidate()
method instead to raiseConanInvalidConfiguration
if strictly necessary to fail fast for unsupported configurations.Use
self.test_requires()
to define test requirements instead of the legacyself.build_requires(..., force_host_context)
.Use
self.tool_requires()
to define the legacy build_requires.Move all your packages to lowercase. Uppercase package names (or versions/user/channel) will not be possible in 2.0.
Explicit test package requirement
In Conan 2.0, the test_package/conanfile.py
needs to declare the requirement being tested explicitly.
To be prepared you have to set the attribute test_type="explicit"
(this will be ignored in 2.0) to make Conan
activate the explicit mode, then declaring the require using the self.tested_reference_str
that contains the
reference being tested.
from conan import ConanFile
class MyTestPkg(ConanFile):
test_type = "explicit"
def requirements(self):
# A regular requirement
self.requires(self.tested_reference_str)
def build_requirements(self):
# If we want to test the package as a tool_require (formerly `test_type = "build_requires"`)
# Keep both "requires()" and "tool_requires()" if you want to test the same package both as a regular
# require and a tool_require (formerly `test_type = "build_requires", "requires"`)
self.tool_requires(self.tested_reference_str)
New namespace conan.tools.xxxxx
Use generators and helpers only from conan.tools.xxxx
space. All the other ones are
going to be removed. Please check the tools section to learn more about the new tools
available for Conan 2.0.
Host and build profiles and new cross-building model
Use always build and host profiles.
Conan 1.x uses one profile by default, to start using two profiles, please do the following:
Pass
-pr:b=default
in the command line to most commands.Or set the variable
core:default_build_profile=default
at the global.conf file to apply it always, automatically.
Do not use os_build
, arch_build
anywhere in your recipes or code.
Conan uses revisions by default in Conan 2.0
Conan 2.0 uses revisions by default and the local cache 2.0 will store multiple recipe and package revisions for your Conan packages (Conan 1.X supports only one revision). To start working with revisions enabled in Conan 1.X, please enable them in your Conan configuration:
$ conan config set general.revisions_enabled=True
self.copy() disappears from recipes
The self.copy
has been replaced by the explicit tool copy.
from conan.tools.files import copy
def package(self):
...
copy(self, "*.lib", self.build_folder, join(self.package_folder, "lib"), keep_path=False)
copy(self, "*.dll", self.build_folder, join(self.package_folder, "bin"), keep_path=False)
self.dependencies to access information about dependencies
Do not use self.deps_cpp_info
, self.deps_env_info
or self.deps_user_info
. Use
the self.dependencies access
to get information about dependencies.
Commands that disappear in 2.0: copy
Do not use the conan copy
command to change user/channel. Packages will be immutable,
and this command will dissapear in 2.0. Package promotions are generally done in the
server side, copying packages from one server repository to another repository.
Methods that disappear in 2.0: self.imports
The def imports(self)
method from the conanfile has been removed. If you need to import files from your
dependencies you can do it in the generate(self)
method:
from conan.tools.files import copy
def generate(self):
for dep in self.dependencies.values():
copy(self, "*.dylib", dep.cpp_info.libdirs[0], self.build_folder)
copy(self, "*.dll", dep.cpp_info.libdirs[0], self.build_folder)
Editables don’t use external templates any more. New layout model
If you are using editables
, the external template files are going to be removed. Use
the layout()
method definition instead. Please check the documentation for more
information about layouts.
Symlinks in recipes and packages
Conan won’t alter any symlink while exporting or packaging files. If any manipulation to the symlinks is required, the package conan.tools.files.symlinks contains some tools to help with that.
Default cpp_info.builddirs
The default root package folder (self.cpp_info.builddirs = ['']
) has been removed. Also assign it
will be discouraged because it affects how CMakeToolchain and
CMakeDeps locate executables, libraries, headers… from the right context (host vs build).
To be prepared for Conan 2.0:
If you have cmake modules or cmake config files at the root of the package, it is strongly recommended to move them to a subfolder
cmake
and assing it:self.cpp_info.builddirs = ["cmake"]
If you are not assigning any
self.cpp_info.builddirs
assign an empty list:self.cpp_info.builddirs = []
.Instead of appending new values to the default list, assign it:
self.cpp_info.builddirs = ["cmake"]
Removing missing settings
In Conan 2, removing a setting, for example, del self.settings.compiler.libcxx
in the configure()
method, will
raise an exception if the setting doesn’t exist. It has to be protected with try/except:
def configure(self):
try:
# In windows, with msvc, the compiler.libcxx doesn't exist, so it will raise.
del self.settings.compiler.libcxx
except Exception:
pass
New properties model for the cpp_info in Conan 2.0 generators
Using .names
, .filenames
and .build_modules
will not work any more for new
generators, like CMakeDeps and PkgConfigDeps.
They have a new way of setting this information using set_property
and
get_property
methods of the cpp_info
object (available since Conan 1.36).
def set_property(self, property_name, value)
def get_property(self, property_name):
New properties cmake_target_name
, cmake_file_name
, cmake_module_target_name
,
cmake_module_file_name
, pkg_config_name
and cmake_build_modules
are defined to allow
migrating names
, filenames
and build_modules
properties to this model. In Conan 2.0 this
will be the default way of setting these properties for all generators and also passing
custom properties to generators.
Important
The 2 mechanisms are completely independent:
Old way using
.names
,.filenames
will work exclusively for legacy generators likecmake_find_package
New properties, like
set_property("cmake_target_name")
will work exclusively for new generators likeCMakeDeps
. They have changed to be absolute, and that would break legacy generators.Recipes that want to provide support for both generators need to provide the 2 definitions in their
package_info()
New properties defined for CMake generators family, used by CMakeDeps generator:
cmake_file_name property will define in
CMakeDeps
the name of the generated config file (xxx-config.cmake
)cmake_target_name property will define the absolute target name in
CMakeDeps
cmake_module_file_name property defines the generated filename for modules (
Findxxxx.cmake
)cmake_module_target_name defines the absolute target name for find modules.
cmake_build_modules property replaces the
build_modules
property.cmake_find_mode will tell CMakeDeps to generate config files, modules files, both or none of them, depending on the value set (
config
,module
,both
ornone
)
Properties related to pkg_config, supported by both legacy pkg_config and new PkgConfigDeps:
pkg_config_name property equivalent to the
names
attribute.pkg_config_custom_content property supported by both generators that will add user defined content to the .pc files created by the generator
component_version property supported by both generators that sets a custom version to be used in the
Version
field belonging to the created*.pc
file for that component.
Properties related to pkg_config, only supported by new PkgConfigDeps:
pkg_config_aliases property sets some aliases of any package/component name for the
PkgConfigDeps
generator only, it doesn’t work inpkg_config
. This property only accepts list-like Python objects.
All of these properties, but cmake_file_name
and cmake_module_file_name
can be defined at
global cpp_info
level or at component level.
The set/get_property model is very useful if you are creating a custom generator.
Using set_property()
you can pass the parameters of your choice and read them using the
get_property()
method inside the generator.
def package_info(self):
...
# you have created a custom generator that reads the 'custom_property' property and you set here
# the value to 'prop_value'
self.cpp_info.components["mycomponent"].set_property("custom_property", "prop_value")
...
Please check a detailed migration guide in the dedicated section.
scm
is removed, replaced by export()
and source()
methods
The scm
by attribute feature will be removed. The new approach in Conan 2.0 will be:
The
export()
method is responsible of capturing the “coordinates” of the current URL and commit. The newconan.tools.scm.Git
can be used for this (do not use the legacyGit
helper but this one)The
export()
method, after capturing the coordinates, can store them in theconandata.yml
using theupdate_conandata()
helper functionThe
source()
method can use the information inself.conan_data
coming from exportedconandata.yml
file to do a clone and checkout of the matching code. The newconan.tools.scm.Git
can be used for this purpose.
This approach is already available in 1.X,. Check the conan.tools.scm.Git
documentation in the reference for examples.
The core logic would be in the export()
method:
def export(self):
git = Git(self, self.recipe_folder)
scm_url, scm_commit = git.get_url_and_commit()
# we store the current url and commit in conandata.yml
update_conandata(self, {"sources": {"commit": scm_commit, "url": scm_url}})
Please check the full example in the conan.tools.scm.Git section.