Use conanfile.py for consumers

You can use a conanfile.py for installing/consuming packages, even if you are not creating a package with it. You can also use the existing conanfile.py in a given package while developing it to install dependencies. There’s no need to have a separate conanfile.txt.

Let’s take a look at the complete conanfile.txt from the previous timer example with POCO library, in which we have added a couple of extra generators

[requires]
poco/1.9.4

[generators]
gcc
cmake
txt

[options]
poco:shared=True
openssl:shared=True

[imports]
bin, *.dll -> ./bin # Copies all dll files from the package "bin" folder to my project "bin" folder
lib, *.dylib* -> ./bin # Copies all dylib files from the package "lib" folder to my project "bin" folder

The equivalent conanfile.py file is:

from conans import ConanFile, CMake

class PocoTimerConan(ConanFile):
   settings = "os", "compiler", "build_type", "arch"
   requires = "poco/1.9.4" # comma-separated list of requirements
   generators = "cmake", "gcc", "txt"
   default_options = {"poco:shared": True, "openssl:shared": True}

   def imports(self):
      self.copy("*.dll", dst="bin", src="bin") # From bin to bin
      self.copy("*.dylib*", dst="bin", src="lib") # From lib to bin

Note that this conanfile.py doesn’t have a name, version, or build() or package() method, as it is not creating a package. They are not required.

With this conanfile.py you can just work as usual. Nothing changes from the user’s perspective. You can install the requirements with (from mytimer/build folder):

$ conan install ..

conan build

One advantage of using conanfile.py is that the project build can be further simplified, using the conanfile.py build() method.

If you are building your project with CMake, edit your conanfile.py and add the following build() method:

from conans import ConanFile, CMake

class PocoTimerConan(ConanFile):
   settings = "os", "compiler", "build_type", "arch"
   requires = "poco/1.9.4"
   generators = "cmake", "gcc", "txt"
   default_options = {"poco:shared": True, "openssl:shared": True}

   def imports(self):
      self.copy("*.dll", dst="bin", src="bin") # From bin to bin
      self.copy("*.dylib*", dst="bin", src="lib") # From lib to bin

   def build(self):
      cmake = CMake(self)
      cmake.configure()
      cmake.build()

Then execute, from your project root:

$ conan install . --install-folder build
$ conan build . --build-folder build

The conan install command downloads and prepares the requirements of your project (for the specified settings) and the conan build command uses all that information to invoke your build() method to build your project, which in turn calls cmake.

This conan build will use the settings used in the conan install which have been cached in the local conaninfo.txt and file in your build folder. This simplifies the process and reduces the errors of mismatches between the installed packages and the current project configuration. Also, the conanbuildinfo.txt file contains all the needed information obtained from the requirements: deps_cpp_info, deps_env_info, deps_user_info objects.

If you want to build your project for x86 or another setting just change the parameters passed to conan install:

$ conan install . --install-folder build_x86 -s arch=x86
$ conan build . --build-folder build_x86

Implementing and using the conanfile.py build() method ensures that we always use the same settings both in the installation of requirements and the build of the project, and simplifies calling the build system.

Other local commands

Conan implements other commands that can be executed locally over a consumer conanfile.py which is in user space, not in the local cache:

  • conan source <path>: Execute locally the conanfile.py source() method.

  • conan package <path>: Execute locally the conanfile.py package() method.

These commands are mostly used for testing and debugging while developing a new package, before exporting such package recipe into the local cache.

See also

Check the section Reference/Commands to find out more.