[cmake-developers] How to handle package Config.cmake files with dependencies ?

Brad King brad.king at kitware.com
Mon Feb 27 16:05:04 EST 2012


On 2/27/2012 3:37 PM, Michael Wild wrote:
> On 02/27/2012 09:15 PM, Alexander Neundorf wrote:
>> When the FooConfig.cmake has been found, Foo_FOUND is set to TRUE:
>>
>>   // Set a variable marking whether the package was found.
>>    std::string foundVar = this->Name;
>>    foundVar += "_FOUND";
>>
>> This means it is true in all cases that the Config.cmake file has been found
>> (and the version was compatible).

The find_package command is acting as a primitive like find_library from
the point of view of setting Foo_DIR, and that can be tested directly to
see if the config file was found.  That leaves room to change the way
we set Foo_FOUND.  We could add a policy that in NEW behavior unsets
Foo_FOUND completely before loading FooConfig.  After FooConfig has been
loaded it detects whether Foo_FOUND is now defined.  If set, use that
value.  If not set, set it to true as it is now.  That will give the
FooConfig file a chance to set the result.

>> * how to handle COMPONENTS ?
>
> I like that proposal. I'm also quite unhappy with how components are
> handled in config-mode.

With the approach I suggest above it will be up to FooConfig to determine
this.

Another approach is to add an API to give FooConfigVersion access to the
list of desired components.  If the package version file encodes a known
list of available components it would be able to report UNSUITABLE if a
requested component is missing.  Then find_package would move on to
another candidate.  This might confuse users that expect a particular
location to be found because it wouldn't report that it is missing a
component and instead silently ignore it.  It is probably better to let
FooConfig report a message that says its Foo doesn't have the component.

>> * how to handle dependencies ?
>>
>> Let's say the exported targets of Foo link against other imported/exported
>> targets. So that the imported targets work properly, the targets for the
>> libraries it depends on must have been found and imported before.
>> Where should this
>> find_package(Bar)
>> be done ?
>> In FooConfig.cmake ?
>> This would be possible only if Bar can be found in Config mode, because
>> otherwise Foo cannot rely on FindBar.cmake being available.

It can if Foo's installation comes with the FindBar.cmake it needs and
at least temporarily adds its location to CMAKE_MODULE_PATH.

>> For a Config file I'm not sure about it. Shouldn't this be only a source of
>> information, purely declarative, and not initiate searching other packages ?
>
> I think current best practice is to call find_package(Bar) inside the
> FooConfig.cmake. If the FindBar.cmake is contained in CMake,
> everything's fine (possibly, you need a cmake_minimum_required()),
> otherwise Foo should install FindBar.cmake alongside FooConfig.cmake.

I agree.  We can't push knowledge of Foo's dependencies onto the project
that finds it.  FooConfig should do the search.  Of course ideally a
package manager that installed Foo would have put something in it so
that it knows where to find the Bar it was built against by the package
manager without searching.

Allowing FooConfig to set Foo_FOUND as I suggest above would allow it
to set it to false if a dependency is not found.

-Brad



More information about the cmake-developers mailing list