[CMake] [cmake-developers] Using CMake as a package manager vs using a dedicated package management tool (like Conan)

Craig Scott craig.scott at crascit.com
Tue Feb 19 05:56:05 EST 2019


On Tue, Feb 19, 2019 at 12:46 PM Timothy Wrona <tjwrona1992 at gmail.com>
wrote:

> I have been working on a new C++ project and I am trying to decide whether
> I should use CMake as my package management system or if I should use a
> dedicated package management tool such as Conan.
>
> For more information on Conan see: https://conan.io/
>
> I am trying to understand the main difference between using Conan to
> manage dependencies vs using CMakes "FetchContent" module. Are there any
> compelling reasons to prefer something like Conan?
>

Excellent question, one that I think deserves a more detailed answer than I
can provide here, but I'll try to hit the main points as I see them.

Personally, I think there is no "right answer" or "one size fits all" when
it comes to package management for a CMake project. What works well for one
situation, person or project may not be as convenient or suitable for
another. There are competing needs and views, some of which are personal
preferences, others are hard requirements from things like OS distribution
policies for packaging. Even just the maturity of a project can have a big
influence on how developers may prefer to handle its dependencies and
handle it as a dependency of other projects.

The key thing for me is that the developer should ideally have choices when
it comes to this area. If a project hard-codes that its dependencies must
come from a particular provider (whether that be Conan, Hunter, vcpkg or
some other system), this might not be compatible with what the developer's
situation allows. You would need to weigh up whether it makes sense to lock
the developer into a particular package manager if they want to use your
project or not. An inappropriate choice here can mean lower adoption of the
project as some may reject it for consideration based on this point alone.

If instead a project relies only on find_package() to find its
dependencies, then it is up to the developer to ensure they are all
available. This could be done using whatever package manager the developer
finds convenient, or they could build the dependency projects from source
individually or they might set up a superbuild parent project that builds
the dependencies in the required order and makes dependees available to
dependers. This gives good flexibility at the cost of more responsibility
on the developer than perhaps some would want (again, it will be highly
situation-dependent).

A drawback with find_package() is that it assumes you actually have a
packageable project. For a variety of reasons, this may not be the case.
Consider a large, complex project in its early stages and where multiple
teams are working on different subprojects which all get combined into some
larger whole. Each of the subprojects may need to be able to build on their
own with their own smaller subset of dependencies, but they also need to be
able to be incorporated into a larger build (think of different teams
working on core toolkits, rendering engines, different algorithm
strategies, multiple GUI applications, backend components, etc). No-one may
know yet how it should get packaged up and everyone might be focused on
just getting a minimal viable prototype up and running as a technical
demonstrator. For a case like that, neither find_package() nor a package
manager really fits the workflow. In this situation though, FetchContent is
a perfect fit, since it doesn't require any packaging to already be in
place, it needs no external tools other than CMake and it gives each
project precise control over its dependencies down to the individual commit
to bring in for each one.

With the above in mind, perhaps the following few questions may be helpful
in clarifying what your constraints are and maybe steering you more toward
one way or the other:

   - Will the project be incorporated into a Linux distribution at some
   point (not just be installed on Linux, but be part of the actual Linux
   distribution as provided by its own native package manager)? If so, I would
   expect this would pretty much eliminate using any package manager and
   instead require that you use find_package() to find all dependencies.
   - Are any of the dependencies of the project using a build system other
   than CMake? If so, they tend to take a bit more work to incorporate into a
   build via ExternalProject or FetchContent. If you can assume the developer
   provides those somehow, bringing them in by find_package() shifts
   responsibility for building them from the project to the developer (or
   whatever package manager they choose to use). This might be anywhere from
   entirely appropriate to entirely problematic depending on who your intended
   audience is.
   - How many dependencies does the project have and what is the maturity
   of each one? Will the project need to update any of those dependencies
   often (are they also being actively developed, do you need to follow recent
   work in them)? What will be the impact on developers working on the project
   when these dependencies need to be updated (how easy is it for them to
   update, what assumptions are you making about their development environment
   and tools)?
   - What breadth of platforms, compilers and CMake generators do you want
   to support? The bigger this set, the more it may drive you towards building
   dependencies from source rather than relying on having pre-built packages
   available to you.
   - Do you want developers to be able to use tools like sanitizers,
   perform code refactoring across projects or have source code visibility
   into dependencies within their IDE tools? FetchContent supports all of
   these requirements quite naturally, but doing so for the other methods it
   may be more difficult.
   - How will you manage repeatability of building past releases? Will you
   be able to build a year old release again if you update a build slave? In
   particular, what assumptions are you making about a CI system's build
   slaves and what dependencies they have installed (can you have multiple
   versions of any given dependency available at once, whether that be at a
   known path or via whatever package manager(s) you choose to use)?


On a side note, this is an area I'm increasingly thinking about these days
(I'm the author of the FetchContent module). I'm interested in hearing
peoples' views on dependency management and building an understanding of
what works for people and what doesn't. If you want to send feedback my
way, do feel free to get in touch.

-- 
Craig Scott
Melbourne, Australia
https://crascit.com

Get the hand-book for every CMake user: Professional CMake: A Practical
Guide <https://crascit.com/professional-cmake/>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://cmake.org/pipermail/cmake/attachments/20190219/b78a43ee/attachment.html>


More information about the CMake mailing list