[cmake-developers] Adding argument "OPTIONAL" to find_package() and add_subdirectory

Alexander Neundorf neundorf at kde.org
Thu Jun 9 08:50:54 EDT 2011


On Thursday 09 June 2011, Brad King wrote:
> On 6/9/2011 2:58 AM, Alexander Neundorf wrote:
> > This wish comes mainly from packagers, not from the developers
> > themselves. I am sure packagers would be happy if they had one
> > consistent way to disable every package any cmake checks for with a
> > standardized option.
> 
> This is a nice goal, but I do not think it is easy to do.
> 
> What if find_package(Foo) is called in more than one location with
> different COMPONENT values?  What if one is required and the other is
> not?  

Now that you say it, we (cmake) have issues with this anyway.

Some people told me in Randa that they have problems with this.
Calling FindQt4 in some directory with components A and B, and in some other 
directory with component C, and the second one doesn't do anything because the 
first one has already set something to "I am done" already so the second one 
doesn't do anything.

Maybe we have the same issue when somebody calls
find_package(Foo 2.0.0 NO_MODULE)
in some directory, and it finds eg. version 2.0,
and
find_package(Foo 3.0.0 NO_MODULE) 
in some other directory ?
Foo_DIR (which is in the cache) has been already set then.
This could be also mixed with different components, which may are only 
installed for one of the two versions...

Maybe, if Foo is disabled, this could be interpreted as "the user wants to be 
independent from Foo, regardless of components etc.", i.e. a quite global off-
switch.
I have to think a bit more about this.

> What if the FindFoo.cmake script calls find_package(Bar) and does
> not require it but the project also does find_package(Bar) and does? I'm
> sure there are more cases I haven't listed here.

I think this can be handled.
find_package() should error out in this case, because Bar was required but it 
was disabled.
Maybe this option to disable a find_package() could even be provided for all 
find_package() calls, and for each REQUIRED one it will cause an error. This 
would create a bunch of unusable options, but would be very consistent ;-)

> The overall problem is that not all calls of find_package() are intended
> to declare a dependency of the main project on a third party package.
> In order to make such intention explicit you need to have a different
> syntax, like a macro that handles it in a way that makes sense for a
> given project.  When projects start nesting inside one another I'm not
> even sure it is a well-defined problem.
> 
> >   if (! mf->IsOn(DISABLE_FIND_PACKAGE_<name>)
> >   {
> >   
> >     cacheVars = getAllCacheVars();
> >     doNormalFinding();
> >     newCacheVars = getAllCacheVars();
> >     addedCacheVars = newCacheVars - cacheVars;
> >     FIND_PACKAGE_<name>_CACHE_VARS = addedCacheVars;
> >     put FIND_PACKAGE_<name>_CACHE_VARS in the cache
> >   
> >   }
> >   else // it is disabled
> >   {
> >   
> >     get FIND_PACKAGE_<name>_CACHE_VARS from cache
> >     remove all variables listed there from cache
> >     set <name>_FOUND to FALSE
> >   
> >   }
> 
> That kind of auto-cache-cleanup logic will be problematic in non-toy
> cases.  If two different find_package() calls lead transitively to
> the same cache values then one could erase the other's results.

Are you sure ?
Let's say I have a project which uses PNG and ZLIB.
Assume I disable PNG (which finds ZLIB).
If PNG is searched first, both PNG and ZLIB variables are remved from the 
cache. After this, when ZLIB is searched, it will search again, and the 
results will end up in the cache.

The other way round, if I disable ZLIB, PNG will not be found, which is ok, 
since this would have dragged in ZLIB.

Or maybe not actually remove them from the cache, but set the "normal" 
variables to NOTFOUND ?

Alex



More information about the cmake-developers mailing list