[CMake] Interpackage dependencies - find_package() from package

2016-01-17 Thread Thomas Ruschival
Hi,
I have problems understanding how the cmake-buildsystem is supposed to
resolve inter-package dependencies (imported targets form installed
packages).

Let say I have a project with an executable target (e.g. someApp) that
depends on a library (libfoo). While libfoo is built in a separate
project and depends on libbar which is built in another project.
Libbar and libfoo export cmake packages (fooConfig.cmake,
fooVersion.cmake fooTargets.cmake etc.) according to [1] and [3]

I.e.:
someApp->libfoo->libbar

In libfoo:
- find_package(bar CONFIG REQUIRED)
- target_link_libraries(bar::bar)

The packages are installed and found - no problem here.
In FooTargets.cmake the dependency on bar::bar is added to
INTERFACE_LINK_LIBRARIES.

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?

Do I miss something or does CMake (3.4) just not do what I want it to do
out of the box?

Thanks in advance!
Thomas

I am using the wiki + reference:
[1] https://cmake.org/Wiki/CMake/Tutorials/Packaging
[2] https://cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
and this example:
[3] https://github.com/forexample/package-example


-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake


Re: [CMake] Interpackage dependencies - find_package() from package

2016-01-17 Thread Domen Vrankar
> 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
-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake


Re: [CMake] Interpackage dependencies - find_package() from package

2016-01-17 Thread Thomas Ruschival
Thank you Domen
for your detailed answer!

> If your application, foo, bar and bas are not built as the same super
> project [...]
In fact this is where I started, for now all are build in the same
super-project and foo and bar have tight coupling. In fact foo and bar
end up in the same Cpack package and are installed together.
(BTW. foo and bar are static libraries and bar exports compile_flags to
let its clients know how it  was compiled.)

I started playing around trying if I can use the packages installed and
found the problem that while bar can be used in the client program foo
couldn't and I wondered wether this is possible.
Your arguments make total sense... althought it would be cool if it
worked...

Thanks again!
Thomas

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake