<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
In my case all projects provide their own FooBarConfig.cmake, but
not a FindFooBar.cmake. For this reason I wanted to use those,
because I thought it saves me the effort of writing a lot of
FindFooBar.cmake files, and it also seemed like the right way to do
it, because it provides things like FooBar_LIBRARIES, which is what
I need. The reason I said that I create my own FooBarConfig.cmake,
is because I want to use CMake properly in my own project, so I also
want to provide a FoorBarConfig.cmake file for my users. So even if
the projects I use don't do everything properly, I still want to do
it properly myself. The problem in this case is that I'm not sure
what the proper way is. If the FoorBarConfig.cmake file is not
enough to handle the dependencies I encounter, should I provide a
FindFooBar.cmake file or something, instead of just the
FooBarConfig.cmake? And meanwhile also write a FindFooBar.cmake file
for all my dependencies?<br>
<br>
Another reason why this seems odd to me, is because if N different
projects use FooBar, then also possibly N different versions of
FindFooBar.cmake are created by all the different projects (I have
actually already seen this a lot). That is the case, because the
FindFooBar.cmake file is not provided by the FooBar project, unlike
the FooBarConfig.cmake.<br>
<br>
Cheers,<br>
Sven<br>
<br>
<div class="moz-cite-prefix">On 06/08/2016 03:11 PM, Chuck Atkins
wrote:<br>
</div>
<blockquote
cite="mid:CAOXZzG5dWm-MgnsC3QSFFZz5jNkMvoeL=KkAtT=99KfrVcGsjg@mail.gmail.com"
type="cite">
<div dir="ltr">
<div>
<div>
<div>
<div>
<div>
<div>The FooBarConfig.cmake is something that should
be generated by FooBar's build. The reason you
don't get absolute paths for the "libraries" from a
package config file is that they're not actually
libraries but imported targets. The imported target
let's you treat "foo" as though it were a library
built by your project. It then has the appropriate
target properties set on it ti define the full path
to it's library, etc. That being said, if you're
manually creating the FooBarConfig.cmake that's not
really the right approach. If the FooBar buil;d
doesn't actually generate it's own
FooBarConfig.cmake file then you'll want to create
you're own FindFooBar.cmake. A bare bones find
module that creates an imported target would look
something like this:<br>
<span style="font-family:monospace,monospace"><br>
if(NOT FooBar_FOUND AND NOT TARGET FooBar::FooBar)<br>
find_path(FooBar_INCLUDE_DIR FooBar.h)<br>
find_library(FooBar_LIBRARY FooBar)<br>
<br>
include(FindPackageHandleStandardArgs)<br>
find_package_handle_standard_args(FooBar<br>
FOUND_VAR FooBar_FOUND<br>
REQUIRED_VARS FooBar_INCLUDE_DIR
FooBar_LIBRARY<br>
)<br>
endif()<br>
<br>
if(FooBar_FOUND AND NOT TARGET FooBar::FooBar)<br>
add_library(FooBar::FooBar UNKNOWN IMPORTED)<br>
set_target_properties(FooBar::FooBar PROPERTIES<br>
IMPORTED_LOCATION ${FooBar_LIBRARY}<br>
INTERFACE_INCLUDE_DIRECTORIES
${FooBar_INCLUDE_DIR}<br>
)<br>
endif()</span><br>
<br>
</div>
Then in your project you can use:<br>
<br>
</div>
<span style="font-family:monospace,monospace">find_package(FooBar)<br>
</span></div>
<span style="font-family:monospace,monospace">add_library(MyLib
supercoolfiles.cxx)<br>
</span></div>
<span style="font-family:monospace,monospace">target_libkLibraries(MyLib
FooBar::FooBar)<br>
</span><br>
</div>
Where this starts to get really helpful in your situation is
if you have an imported target for A, B, and C, then you can
create the appropriate dependencies. Say, for example, you
have a FindA.cmake that follows the pattern above and
generates an A::A target. Then in your FindB.cmake you can
have:<br>
<br>
<span style="font-family:monospace,monospace">if(NOT B_FOUND
AND NOT TARGET B::B)<br>
find_path(B_INCLUDE_DIR B.h) <br>
find_library(B_LIBRARY B)<br>
<br>
include(FindPackageHandleStandardArgs)<br>
find_package_handle_standard_args(B<br>
FOUND_VAR B_FOUND<br>
REQUIRED_VARS B_INCLUDE_DIR B_LIBRARY<br>
)<br>
<br>
<b> find_package(A QUIET)<br>
if(A_FOUND)<br>
set(B_Extra_Deps A::A)<br>
endif()</b><br>
endif()<br>
<br>
if(B_FOUND AND NOT TARGET B::B)<br>
add_library(B::B UNKNOWN IMPORTED) <br>
set_target_properties(B::B PROPERTIES<br>
IMPORTED_LOCATION ${B_LIBRARY}<br>
INTERFACE_INCLUDE_DIRECTORIES ${B_INCLUDE_DIR}<br>
)<br>
<b> if(B_Extra_Deps)<br>
set_target_properties(B::B PROPERTIES<br>
INTERFACE_LINK_LIBRARIES ${B_Extra_Deps}<br>
)<br>
endif()</b><br>
endif()</span><br>
<br>
</div>
and similarly for FindC.cmake. Since A::A, B::B, and C::C are
actual proper CMake targets and not just library files then they
carry with them associated target dependency information. In
CMake vernacular we refer this as "target usage requirements"
since the target caries with it all the necessary information
for something to actually use it, whether that's just extra link
libraries or also extra include directories and compile
definitions needed. The <span
style="font-family:monospace,monospace">Package::Target</span>
naming convention is the idea that each package has it's own
namespace where you may define multiple targets.<br>
</div>
</blockquote>
<br>
</body>
</html>