I've tried CMake with Conan and I really liked it
As it’s probably obvious by now, I’m not a fan of CMake. I don’t like the weird syntax, the verbosity of the language, the flawed concept of multistage build system generation and external dependency management which seems like an after thought.
I can’t deny though, that CMake is very popular and has a lot of traction so, it’s the necessary evil until we all, as an industry, decide on some other solution.
Recently, I decided to give conan a go in one of my CMake projects and I must say that I was positively surprised.
What’s Conan?
Conan is a package manager which solves a lot of CMake’s problems. Without conan (or any other package manager for that matter) preparing a self-contained development environment with CMake feels like a hack. With it, dependency management feels a bit more streamlined and less painful.
How does it work?
In short, you specify your dependencies in conanfile.txt
(or conanfile.py
-
for more complex configurations). Prior to building your project, conan will
install all the dependencies and prepare the environment for CMake so, it can
find all the packages without any problems at all.
Example
Let’s suppose you’re writing a program requiring e.g. fmt
.
|
|
No problems at all! You go to conan center and there’s the recipe:
|
|
Save it as conanfile.txt
. In CMakeLists.txt
you just have to find the
package. Here’s an example CMakeLists.txt
in its entirety:
|
|
You don’t even have to read Conan’s documentation to use the recipe, because conan center literally gives you all the commands that you have to invoke to use it. So, let’s do that:
conan install -of bld --build=missing .
Once it builds and caches fmt
, conan even tells you how to use your
dependencies and start the CMake build:
|
|
CMake can be invoked either using presets or the ’traditional’ way. With presets, it’s super easy:
cmake --preset conan-release
cmake --build --preset conan-release
Without presets, it’s a bit more verbose
cmake \
-Bbld/build/Release/generators \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake \
-GNinja \
-S .
ninja -C bld/build/Release/generators
Just like that all dependencies have been satisfied and integrated into the project.
Integration with meson
conan can cater not only to CMake projects but meson as well (although meson
has its own ‘wraps’ system which is very convenient on its own). It’s purely a
matter of choosing a different generator. In case of meson, the dependencies
are resolved with pkg-config
. Prior example built with meson
would need the below, adjusted conanfile.txt
:
|
|
In meson.build
you just need to declare the dependencies to find them:
|
|
Build directory setup is done in exactly the same way as before:
conan install -of bld --build=missing .
Meson bootstrap will need the native-file to setup the paths properly:
meson setup --native-file bld/conan_meson_native.ini bld
After that, the build can be done as usual:
meson compile -C bld
libboxes
I’ve actually started working on a library containing all data structures I find myself writing very frequently in variety of projects and thought that it would be good to finally collate all of these (even only as a reference implementation) in a working, ready to use library.
The library is called libboxes and since I want to appeal to a wider audience and provide flexibility for myself as well, CMake integration is a must hence I decided to provide both meson and CMake as build systems. The library contains conan recipes so, it’s super easy to use it in CMake projects. It’s still pretty much a work in progress and at the moment, the selection of available data structures is limited but I plan to extend it to offer a greater variety.
This was my main motivation to finally explore conan and try it out on my own and with full honesty I’m glad I did.