New 1.20 release with useful features and improvements. Here you have the main highlights of this one!

Reuse CMake macros from your dependencies

Following the line of previous releases, we continue to pursue a transparent integration with build systems and in this case, we have improved the cpp_info model to include build system files or build modules in the case of CMake.

This new feature allows reusing the CMake macros on the consumer side in a transparent way. This comes in handy when libraries provide some kind of helper as a function or macro to consumers to create or link targets or to use a built-in tool.

We did some tests using the pybind11 library. This library provides a CMake macro that helps a consumer to create and link its targets: pybin11_add_module().

The recommended way to use the library can be found in the (library’s documentation)[https://pybind11.readthedocs.io/en/stable/compiling.html#building-with-cmake] as the following:

cmake_minimum_required(VERSION 2.8.12)
project(example)

add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)

Using build modules, the files needed to reuse that macro can be now included in the cpp_info model like this:

conan-pybind11/conanfile.py

...
    def package_info(self):
        base_path = os.path.join("share", "cmake", "pybind11")
        self.cpp_info.builddirs = [base_path]
        self.cpp_info.build_modules = [
            os.path.join(base_path, "pybind11Tools.cmake"),
            os.path.join(base_path, "FindPythonLibsNew.cmake")
        ]
...

Those build modules will be included in the find and config files generated by the cmake_find_package and cmake_find_package_multi generators so they can be used transparently like this:

cmake_minimum_required(VERSION 2.8.12)
project(example)

find_package(pybind11 REQUIRED)
pybind11_add_module(example example.cpp)

The complete diff of the changes required in the pybind11 recipe as well as the consumer’s CMakeLists.txt can be found here.

Remember to check the documentation for full details about this feature.

Support for system libraries

Another useful improvement coming to the cpp_info model is the system libraries. Commonly, libraries require consumers to link to system libraries like pthread, m or Ws2_32.

This was normally done appending those system libs to the cpp_info.libs and therefore, mixing package libraries with the system ones.

Some generators were smart enough to detect package libraries and system libraries, but they did not apply any special treatment to the latest.

With the usage of cpp_info.system_libs generators have now the ability to improve the target generation, linking them as INTERFACE_LINK_LIBRARIES in all the CMake generators.

You can read more about system libraries in the documentation.

Compatible packages

In our investigation to support new compilers, we realized while integrating the Intel C++ compiler that the compatibility with packages built with a base compiler was not possible due to the package ID model restriction in Conan.

Until this release, the only compatibility possible was to create the same package (unique package ID) with the same settings input. This means, that if you wanted to model the compatibility of a package for GCC 4.7, 4.8 and 4.9, the only possible way was to define a unique ID for all of them with a fixed version value (see example here). However, that is not the case when mixing packages for the Intel C++ compiler and Visual Studio and GCC.

This new feature allows package creators to define compatible packages with a completely different package ID. A list of compatible packages can be defined in the package_id() method, for example, you can define GCC 4.9 and 4.7 as compatible packages for consumers that are using GCC 4.9 as input in their profiles. The difference here is that now, if you apply a profile for GCC 4.7 you will generate a package for 4.7, if you apply a profile of 4.8 you will get a package ID for 4.8, but if you don’t generate a package for 4.9 and you require this package as a consumer, you will get a binary for 4.8 or 4.7 if available:

...
    def package_id(self):
        if self.settings.compiler == "gcc" and self.settings.compiler.version == "4.9":
            for version in ("4.8", "4.7"):
                compatible_pkg = CompatiblePackage(self)
                compatible_pkg.settings.compiler.version = version
                self.compatible_packages.append(compatible_pkg)
...

When a package is not found but a compatible package exists, Conan will pick the available package and notify it with the following message:

$ conan install lib/0.1@us/ch
...
Main binary package '2ef6f6c768dd0f332dc252b72c30dee116632302' missing.
Using compatible package '1151fe341e6b310f7645a76b4d3d524342835acc'
...
    lib/0.1@us/ch:1151fe341e6b310f7645a76b4d3d524342835acc - Cache

Note that this implies that the packages are compatible at all effects, as Conan will treat them as fully interchangeable.

This is has been introduced as a experimental feature and the interface might change in future releases but you can take a look at the documentation and the examples to learn more about it.

Dynamically set the name or the version of your packages

Now you can dynamically define the name and the version of your recipes with set_name() and set_version(). For example, if you want to extract the version from the CMakeLists.txt:

class HelloConan(ConanFile):
        name = "Hello"

        def set_version(self):
            content = load("CMakeLists.txt")
            version = re.search(b"set\(MY_LIBRARY_VERSION (.*)\)", content).group(1)
            self.version = version.strip()

The set of self.name and self.version is only allowed inside those methods and the information will be stored in the recipe metadata, meaning that these methods will be only used when the recipe is exported to the cache.

SCM improvements

We had some optimizations pending for the SCM feature that are now solved in this release.

Now, when a package is created with not committed changes, the auto fields in the recipe are not replaced automatically. This marks the packages as dirty and prevents the upload of the recipe to a remote without uncommitted changes but allows developers to continue testing the package creation with those changes.

However, you can still force Conan to replace the auto fields in export, create and export-pkg commands with the --ignore-dirty flag or force the upload of dirty packages with conan upload --force.

See the complete documentation of this feature.

Clang 10 and GCC 7.4 support

Conan 1.20 adds support for Clang 10 and includes the specific 7.4 version for GCC in the default settings.yml file.

Remember that the minor version values in the gcc compiler are claimed to be compatible and that Conan will use by default just GCC 7 as the version value in the profile unless it is explicitly indicated in the profile.

Generating Artifactory build-info from lockfiles

With our focus on improving the continuous integration flows for Conan packages, we have released a new approach to generate build information for packages using the Build Info JSON format for Artifactory. Instead of using the Conan trace file to gather the information, this is now done using a lockfile.

This new experimental feature is available through the conan_build_info command and we trust it will help to look into and develop how to achieve an efficient, robust and complete CI flow for C/C++ projects using Conan.



Finally, check the full list of features and fixes in the changelog and do not hesitate to report any bug or share your feedback opening a new issue in our issue tracker.