[CMake] Interpackage dependencies - find_package() from package

Domen Vrankar domen.vrankar at gmail.com
Sun Jan 17 05:47:04 EST 2016


> If in someApp I find foo find_package(foo CONFIG REQUIRED)
> I get an error: "The following imported targets are referenced, but are
> missing: bar::bar"
>
> The current workaround is to manually add in someApp
> find_package(bar CONFIG REQUIRED) before
> find_package(foo CONFIG REQUIRED)
>
>
> But in my understanding this find_package(bar) should somehow be
> resolved from the package foo - am I wrong?
> The client should not have to resolve the entire dependency tree
> manually bay adding find_package() in the correct order.
> How can this be done?

As far as I know find_package(foo) will not search for its
dependencies (e.g. bar) except if you put another find_package inside
Findfoo.cmake script that finds it for you.

On the other hand I doubt that this is a CMake issue/shortcoming.
I imagine that your dependency tree looks something like this:

your_program <- foo <- bar
                    <- bar

so both your program and foo library depend on bar library and there
are three cases that I see:

1) your application has direct dependency on bar library (is using bar api)
2a) your application depends on foo that exposes bar api because it
uses bar api as public foo api
2b) you application depends on foo that exposes bar api but foo
doesn't use it as public foo api

In all cases you will have to search for bar library yourself and link
it to your application but:

In case 1 it is logical that you have to search for bar lib yourself
since it is just a coincidence that foo is using bar internally.

In case 2a dependency to bar is by design and it's questionable why
bar is used in public foo api (maybe performance reasons?) so it might
be a flaw in library design (or is your own library in which case it
would probably be better to create an object library and do all the
linking and searching for libraries in you applications cmake list -
in this case you could also set a variable with PARENT_SCOPE that gets
propagated to root cmake list to automate you dependency detection).

In case 2b dependency to bar is accidental and is just poor/old
library design - library is not linked with everything being a private
symbol and only public api being marked as public either by using an
attribute (https://gcc.gnu.org/wiki/Visibility   - supported in one
way or the other in gcc, Visual C++, xlC from version 13.1 and
probably clang and others) or some other form like export lists or
static keywords
(http://www.ibm.com/developerworks/aix/library/au-aix-symbol-visibility/).
If this is an external library and you are using it for production
application I would suggest that  if possible you write a wrapper
library that only exposes its public api and link your application
only to your wrapper - or if library is open sourced ask if they are
interested in such patches and contribute them there.

In any case if this is not supporter directly by CMake (could be that
it is and I only don't know about it) I doubt that it should be since
libraries leaking their internal implementation probably have API and
ABI compatibility issues between versions and can cause interesting
compile and runtime errors when linked twice as in your case but with
different shared library versions (e.g. you get an already compiled
library and just want to link to it but don't know with which version
of internally dependent library it was built).

Issues with this can be easily seen in cases such as:
your_program <- foo <- bar (v 1.0)
                     <- bas <- bar (v 2.1)
                    <- bar (v 1.3)
If your application, foo, bar and bas are not built as the same super
project or expect different (not API compatible) versions of bar and
they all leak their internal use to the world (and let's also say that
bar 1 and 2 were not tested for combined use in the same application)
then have fun building such an application without causing interesting
runtime errors (e.g. constructor from being called version 1.0 and
destructor from version 2.1).

Hope this helps.

Regards,
Domen


More information about the CMake mailing list