Correct way to use third-party libraries in cmake project

A while back I answered this question on stackoverflow, since it is getting up voted regularly, I am also cross-posting here:

It may also help answer questions in this thread:

Cc: @thomthom

1 Like

I don’t have time to do too much detail here right now, but my general order of preference:

  • always find an external version
    • PRO: easy to maintain
    • CON: harder for users to build your software, especially if the dep is not available via the typical packaging routes (Linux distro, Anaconda, HomeBrew, MacPorts)
  • superbuild which builds your deps and your projects (ExternalProject)
    • Don’t try to do ExternalProject_add for your deps in your main project. The two approaches are like oil and water.
    • PRO: users have a turn-key solution to building your software, packaging environments can ignore the superbuild and provide dependencies the way they can/want.
    • CON: PITA to maintain outside of well-tested environments, fragile, and can make development harder
  • embedding/vendoring
    • PRO: Easy for anyone to build your code
    • CON: Linux distros and other packaging setups will be unhappy without conditional support for the first solution here. Mangling symbols and library names is a real PITA to maintain. Tends to stagnate and ship old versions without vigilance.
  • monorepo
    • This moves up the list for me if you are building a product that is self-contained. Keep away for “frameworks”, libraries, or “platforms”.
    • PRO: You know exactly what you’re building.
    • CON: Users get only what you ship (arguably also a PRO, but unless you support the cross product of targets, someone is going to be unhappy).

For the first, look at any standard Unix package (more or less). The second is used by ParaView to make sure its packages are consistent. The third is done by VTK and ParaView. Note that just doing FetchContent for your dependencies without mangling symbols, library names, and include paths (if an SDK is supported) is asking for trouble if you ship libraries loadable outside your project (plugins, SDKs) or load plugins from outside your project at runtime (plugins) if anyone brings in one of your dependencies by another route. The last is Chrome, many macOS and Windows applications, and other store-like deployment targets (Steam, Google Play, F-Droid, Apple’s App Store, Windows Store, etc.).

Third party projects are hard in C++ because there’s no packaging system and even if there were, getting people to agree on its properties at this point is nigh impossible. All three of the solutions above are double edged swords. Pick your poison with care.

That SO post is so close to answering my questions. In my post The Zen of integrating 3rd party packages I have a package that is so bad. Unfortunately, the package is very badly maintained.

I got it to build using ExternalProject, but other components need a little help finding the headers and library.

Any updates for this based on the “Dependency Provider” capability added in v3.24?

Cc: @craig.scott

I don’t intend to reply here. You may want to keep an eye on this post though, where I do intend to reply when I get a chance (will be some weeks away yet).

The post at CMake: How to build external projects and include their targets - Stack Overflow is very helpful for using ExternalProject