Conan2: from conanfile.txt to conanfile.py

“Also, we will explain how to transition from the conanfile.txt file we used in the first example to a more powerful conanfile.py.”
—Conan Documentation --Release 2.0.17, Chapter 4.1

Using a conanfile.txt to build your projects using Conan it’s enough for simple cases, but if you need more flexibility you should use a conanfile.py file where you can use Python code to make things such as adding requirements dynamically, changing options depending on other options or setting options for your requirements.

conanfile.txt

[requires]
zlib/1.2.11

[tool_requires]
cmake/3.22.6

[generators]
CMakeDeps
CMakeToolchain

conanfile.py

from conan import ConanFile


class CompressorRecipe(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeToolchain", "CMakeDeps"

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

    def build_requirements(self):
        self.tool_requires("cmake/3.22.6")

This file is what is typically called a “Conan recipe”.
It can be used for consuming packages, like in this case, and also to create packages.

For our current case, it will define our requirements (both libraries and build tools) and logic to modify options and set how we want to consume those packages.

In the case of using this file to create packages, it can define (among other things)
how to download the package’s source code,
how to build the binaries from those sources,
how to package the binaries,
and information for future consumers on how to consume the package.

To create the Conan recipe we declared a new class that inherits from the ConanFile class.
This class has different class attributes and methods:

settings this class attribute defines the project-wide variables, like the compiler, its version, or the OS itself that may change when we build our project.
This is related to how Conan manages binary compatibility as these values will affect the value of the package ID for Conan packages.
We will explain how Conan uses this value to manage binary compatibility later.

generators this class attribute specifies which Conan generators will be run when we call the conan install command.
In this case, we added CMakeToolchain and CMakeDeps as in the conanfile.txt.

requirements() in this method we use the self.requires() method to declare the zlib/1.2.11 dependency.
build_requirements() in this method we use the self.tool_requires() method to declare the cmake/3.22.6 dependency.

command lines

for windows:

> conan install . --output-folder=build --build=missing 

> cmake .. -G "Visual Studio 17 2022" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake

> cmake --build . --config Release


for linux:

$ conan install . --output-folder build --build=missing
$ cd build
$ source conanbuild.sh
Capturing current environment in deactivate_conanbuildenv-release-x86_64.sh
Configuring environment variables
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
$ cmake --build .
...
Building with CMake version: 3.22.6
...
[100%] Built target compressor
$ ./compressor
Uncompressed size is: 233
Compressed size is: 147
ZLIB VERSION: 1.2.11
$ source deactivate_conanbuild.sh


Use the layout() method

In the previous examples, every time we executed a conan install command, we had to use the –output-folder argument to define where we wanted to create the files that Conan generates.

There’s a neater way to decide where we want Conan to generate the files for the build system that will allow us to decide, for example, if we want different output folders depending on the type of CMake generator we are using.

You can define this directly in the conanfile.py inside the layout() method and make it work for every platform without adding more changes.

conanfile.py

import os


from conan import ConanFile


class CompressorRecipe(ConanFile):
    # Binary configuration
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeToolchain", "CMakeDeps"

    def requirements(self):
        self.requires("zlib/1.2.11")
        # Add base64 dependency only for Windows
        if self.settings.os == "Windows":
            self.requires("base64/0.4.0")

    def build_requirements(self):
        if self.settings.os != "Windows":  # we need cmake 3.22.6 in other platforms
            self.tool_requires("cmake/3.22.6")

    def layout(self):
        # We make the assumption that if the compiler is msvc the
        # CMake generator is multi-config
        multi = True if self.settings.get_safe("compiler") == "msvc" else False
        if multi:
            self.folders.generators = os.path.join("build", "generators")
            self.folders.build = "build"
        else:
            self.folders.generators = os.path.join("build", str(self.settings.build_type), "generators")
            self.folders.build = os.path.join("build", str(self.settings.build_type))


As you can see, we defined the self.folders.generators attribute in the layout() method.
This is the folder where all the auxiliary files generated by Conan (CMake toolchain and cmake dependencies files) will be placed.

Note that the definitions of the folders is different if it is a multi-config generator (like Visual Studio), or a single-config generator (like Unix Makefiles).
In the first case, the folder is the same irrespective of the build type, and the build system will manage the different build types inside that folder.
But single-config generators like Unix Makefiles, must use a different folder for each different configuration (as a different build_type Release/Debug).
In this case we added a simple logic to consider multi-config if the compiler name is msvc.

The following command line will work in this case:

> conan install . --build=missing

There’s no need to always write this logic in the conanfile.py.
There are some pre-defined layouts you can import and directly use in your recipe.
For example, for the CMake case, there’s a cmake_layout() already defined in Conan:

conanfile.py

from conan import ConanFile
from conan.tools.cmake import cmake_layout


class CompressorRecipe(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeToolchain", "CMakeDeps"

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

    def build_requirements(self):
        self.tool_requires("cmake/3.22.6")
        
    def layout(self):
        cmake_layout(self)

Use the validate() method to raise an error for non-supported configurations

...
from conan.errors import ConanInvalidConfiguration
class CompressorRecipe(ConanFile):
	...
	def validate(self):
		if self.settings.os == "Macos" and self.settings.arch == "armv8":
			raise ConanInvalidConfiguration("ARM v8 not supported in Macos")

Conditional requirements using a conanfile.py

from conan import ConanFile

	class CompressorRecipe(ConanFile):
		# Binary configuration
		settings = "os", "compiler", "build_type", "arch"
		generators = "CMakeToolchain", "CMakeDeps"
		
		def requirements(self):
			self.requires("zlib/1.2.11")
			# Add base64 dependency for Windows
			if self.settings.os == "Windows":
				self.requires("base64/0.4.0")

		def build_requirements(self):
			# Use the system's CMake for Windows
			if self.settings.os != "Windows":
				self.tool_requires("cmake/3.22.6")


References

Conan Documentation --Release 2.0.17

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值