[CMake] Using find_package() portably?

R0b0t1 r030t1 at gmail.com
Tue Nov 21 14:46:15 EST 2017


Hello friends!

The points brought up are good. However, I have some experience with
CMake's edge cases (due to using Gentoo) so I feel like I should give
my opinion on some of the solutions. The solutions are good, I just
think it is important to indicate that building truly cross platform
code with CMake still seems to be an open problem.

Specifically, if anyone has anything to add on how to use CMake to
find Windows dependencies, I am looking for help in that area.


On Tue, Nov 21, 2017 at 5:36 AM, Konstantin Tokarev <annulen at yandex.ru> wrote:
>
>
> 21.11.2017, 13:45, "Johannes Zarl-Zierl" <johannes.zarl-zierl at jku.at>:
>> Hi,
>>
>> I thought you might want some context for the suggestions:
>>
>> On Dienstag, 21. November 2017 11:45:43 CET Konstantin Tokarev wrote:
>>>  1) add instruction how to install dependencies
>>
>> This is what many/most projects do, and it works reasonably well.
>> Advantages:
>>  - You don't clutter your project with dependencies
>>  - People on each platform already know how to install dependencies
>>  - You don't complicate things for package maintainers
>> Disadvantages:
>>  - No automatic dependency resolution
>>

This is really the best solution on Unix-based operating systems and
will work in the vast majority of cases. The one sticking point is
that most FOSS libraries are not distributed by installer for Windows
anymore, and it is extremely likely you will need to bundle your
dependencies with your project when targeting Windows.

Also, sometimes fringe distributions will not have their library
install locations in the paths checked by CMake. Usually they will
have pkg-config configured properly, and you can find the libraries
and headers that way.

>>>  2) use hand-made script or more complex solution to automate dependency
>>>  installation, or
>>
>> Hand-made scripts are often a maintenance nightmare and hard to get right for
>> all platforms. The One True Way(TM) would be a so-called "super-build", i.e. a
>> CMake project that uses external_project() to build your project along with
>> its dependencies.
>
> FWIW I've seen many projects that provide scripts or one-liners how to install all
> dependencies on popular systems, and if things are readily available or otherwise pre-built
> and downloadable from central place, it's not hard to maintain, at least when number of
> dependencies is small
>

>>
>>>  3) avoid using find_package() st all
>>
>> That's the first time I've heard that suggestion. I'm not sure if this will
>> ease your pain ;-)
>
> I've meant by using things like ExternalProject, or from your point 4, or when
> using other metabuilders. When all dependencies are in known locations,
> you don't really need to use find_package anymore.
>
> Though It may be handy though if you allow building with both external and
> internal dependencies, e.g. if you develop open source project distributors
> will be reluctant to include it if it can use bundled dependencies only.
>

Using ExternalProject and a dependency fetching script suffer from the
same problem. It is very easy to implement these things insecurely,
and it makes your software hard to package for Linux distributions.
When I see a trendy new project that prominently features a "curl |
sh" line on its webpage I shudder and, try as I might, I usually write
it off in my mind. Besides those lines sometimes not having "https://"
in them, installing software outside of your package manager will
eventually lead to a slew of problems (developers that focus on one or
two projects may never experience those problems, but that is almost
entirely luck).

I think there are two major examples I can give:

1) Haskell's Cabal would fetch code (some immediately executed but
also the packages) over HTTP with no authentication, and that code
would often run as root. This has only recently been fixed, but I
still feel like I need to double check myself.

2) Sage Math bundles, I think, 80 pieces of software with it, and has
its own package management system. It builds GCC to build itself! For
some of the problems that this causes, see
https://bugs.gentoo.org/201321.

I do recognize that sometimes distributions simply won't have the
libraries you need. In that case, I recommend leaving it to the user
to find a way to get those libraries. Personally I install them to
~/.local and add them to the search paths, but this is hard to do with
CMake. Sometimes users will find newer libraries in a backports
repository.

>>
>> 4) Shipping the dependency with your project (not using external_project)
>> This can sometimes be useful, but you should carefully consider the
>> implications beforehand to see if it's worth it for your project. As a rule of
>> thumb: don't do this if the dependency is readily available and/or big.
>>

I dislike doing this on principle but it's pretty common for Windows.
Sticking a deps/ directory in your repository with precompiled
libraries and the header files is an easy way to reduce the burden for
potential contributors. I have also seen instructions for building
packages and specifying their location manually.

Should you do this, GPG-signing your commits would be an especially good idea.

Cheers,
     R0b0t1


More information about the CMake mailing list