[CMake] Plural includes, pre-2.6.1 alternative to HINTS, persistence, C99

Jed Brown jed at 59A2.org
Tue Nov 4 17:36:34 EST 2008


On Tue 2008-11-04 21:58, Alexander Neundorf wrote:
> On Tuesday 04 November 2008, Jed Brown wrote:
> > A minor documentation nit: readme.txt says
> >
> >   XXX_INCLUDE_PATH was considered bad because a path includes an actual
> > filename
> >
> > but variable type
> >
> >   PATH     = Directory chooser dialog
> >
> > while FILEPATH refers to a file.  So this doesn't seem to be a valid
> > argument against XXX_INCLUDE_PATH, but we should agree on *something*
> > and all other forms should be clearly labeled as deprecated in the
> > documentation.
> 
> I haven't seen XXX_INCLUDE_PATH in use.

It's marked deprecated in a few cases, but not MPI, GLU, and HTMLHelp
which offer no alternative.  I used FindMPI as a starting point for my
first two modules, hence it was the first thing I saw.


> XXX_INCLUDE_DIR is usually one directory, searched using FIND_PATH, and so 
> usually ends up in the cache. 
> Then one project can need multiple include dirs, so these 
> XXXcomponent1_INCLUDE_DIR and XXXcomponent2_INCLUDE_DIR are then usually 
> merged into a XXX_INCLUDE_DIRS variable:
> set(XXX_INCLUDE_DIRS ${XXXcomponent1_INCLUDE_DIR}
>                      ${XXXcomponent2_INCLUDE_DIR} )
> 
> Instead of XXX_INCLUDE_DIRS sometimes also XXX_INCLUDES is used. I wouldreco

When linking against a package, we don't normally care whether there is
one or more include directories, we have to use them all anyway.
Whether there is one or more can depend on the configuration of the
package, so it doesn't make sense (to me) to classify packages as having
one or more include directories.  XXX_INCLUDE_DIRS seems most common
while XXX_INCLUDES seems slightly more consistent with XXX_LIBRARIES.
Would it make sense to choose one and deprecate all the other variants
(including the singular XXX_INCLUDE_DIR)?  I realize this is a minor
nit, but consistency is especially helpful to new users, which I am.  It
would be nice to not have to read the FindXXX.cmake to learn the
semantics of that package's configure.

> > To clarify a question in my previous message, is there a recommended
> > method for finding packages that contain multiple libraries?  FindQt4,
> > for instance, creates a huge list of cache entries for each individual
> > library within the package.  This doesn't seem like a good solution when
> > the list of libraries is not known apriori or may change with a new
> > release.  
> 
> Where do you see the problem ?

I need to algorithmically generate the components so it's not possible
to script against.  That is, you can't give someone directions to set
XXXcomponentfoo_INCLUDE_DIR because componentfoo may not exist.  For
instance PETSc could be configured with 8 components or with 40.  A new
release (or updating my development repository) could introduce more
optional packages so I can't list all the possible components and test
for them.  Instead, I have to discover them by parsing the link line.
Some of those components have subcomponents.  My solution is to lump
them all in PETSC_LIBRARIES because the user will have to link against
all the components anyway.

As a concrete example, PETSc can optionally be built with the parallel
direct solver MUMPS in which case we also link against 6 MUMPS
libraries.  PETSc can optionally be built with the ODE package Sundials
in which case we link against 3 Sundials libraries.  PETSc always links
against BLAS and Lapack; there are a huge number of variations in
configuration for these.  To build PETSc, these had to work so we don't
want to go searching for them again (i.e. by using
find_package(LAPACK)).  The project CMakeLists.txt could use PETSc's
flags to hint FindLAPACK, but this requires the project to do logic that
really couldn't work any other way.

PETSc usually links with an MPI implementation.  Since MPI does not
specify an ABI, it is essential that all dependencies (PETSc, HDF5,
ParMetis, etc) agree on which MPI is found.  (MPI is a much deeper
problem with no easy answer.  In some cases with shared libraries, all
the proposed link libs could be interrogated with ldd with the user
alerted if they link against different libmpi.)  We don't want our
package to go looking for its own MPI.  At best we'll find the same one
PETSc was built with, otherwise we get a broken build, but we won't know
it's broken until we seg-fault at runtime.

> > Dumping all the entries in a single variable isn't okay either
> > unless the module provides a way to (on reconfigure) change all the
> > paths in that list.  It seems like I always want a FOO_DIR cache entry
> > to use as a hint to find FOO_LIBRARIES.  
> 
> Yes, I think so.
> 
> > Now
> > find_package_handle_standard_args() will make FOO_LIBRARIES an advanced
> > cache entry 
> 
> No, find_package_handle_standard_args() doesn't mark anything as advanced. 
> Where did you see this ?

Whoops, I do that.  find_library() puts them in cache, all FindXXX
modules I've looked at put these variables in cache, marked as advanced.
The readme says these variables should not be cache entries and refers
to FindJPEG as an example, but I find JPEG_INCLUDE_DIR and JPEG_LIBRARY
as cache entries.  What's up?

> > and if the user edits this, it shouldn't get blasted by
> > reconfigure *unless* they change FOO_DIR.
> 
> Values in the cache are only overwritten if the FORCE option is used for 
> SET().

Right, but *if* the user changes FOO_DIR, then we *do* want to use FORCE
since all 40 paths will need to change.  This means the module has to
save an internal value of FOO_DIR on the first pass and on reconfigure,
compare the internal value to FOO_DIR to determine whether FOO_DIR has
changed, in which case it should use FORCE to update FOO_LIBRARIES and
FOO_INCLUDE_DIRS.  I've duplicated this logic multiple times now.

> > It seems like a fair number of modules use the environment variable
> > FOO_DIR as a hint to find_library(), etc.  
> 
> I wouldn't recommend this.
> With cmake 2.6 you can set the CMAKE_PREFIX_PATH environment variable to point 
> to your custom install locations.

But it may not make sense to lump everything together.  As a simple
example, suppose I have /path/to/DBG and /path/to/OPT and want to get
packages A from DBG and B from OPT.  I can't just set CMAKE_PREFIX_PATH
(PATH = list of directories again!) to "/path/to/DBG;/path/to/OPT" since
this will give me the wrong version of B.  Many packages have a native
build that recognizes FOO_DIR so it's natural that a user of that
library would already have this environment variable set.  The interface
I think is most intuitive for lots of packages is that the public cache
entry FOO_DIR defaults to the environment variable, and if changed,
forces an update of the advanced FOO_* entries.  Of course using
CMAKE_PREFIX_PATH is handy in many cases, but intermediate granularity
(between setting CMAKE_PREFIX_PATH and editing 40 advanced cache entries
with awk) requires a stupid amount of boilerplate.

BTW, the documentation for CMAKE_PREFIX_PATH says `it is intended to be
set by the project' but in all the cases I'm thinking of, the project
doesn't know anything about where to look for packages so would never
set this variable, the user (building the package) will want to set it
if their packages aren't found on the first pass.  I think this is
basically the same thing, but how do we tell users about it.  If we
don't set the CMAKE_PREFIX_PATH correctly in advance (how is a new user
even supposed to know this exists?), then cmake will run and get the
wrong values in cache, so even if we reconfigure with CMAKE_PREFIX_PATH
set correctly, the wrong entries won't be updated.  The reliable
recourse is to wipe the build directory and run cmake
-DCMAKE_PREFIX_PATH:STRING="/correct/paths;/for/all;/packages/here"
which is a terrible interface.

> P.S. can you split your initial mail into multiple small ones, one for each 
> topic ? Makes handling it a bit easier.

I didn't want to spam the list with lots of messages.  I'll break it up
next time.

Jed
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://www.cmake.org/pipermail/cmake/attachments/20081104/9c8da1b0/attachment-0001.pgp>


More information about the CMake mailing list