[CMake] Recursive dependencies and static libraries

Jed Brown jed at 59A2.org
Thu Nov 6 06:25:41 EST 2008


On Wed 2008-11-05 21:05, Bill Hoffman wrote:
> Jed Brown wrote:
>> On Wed 2008-11-05 23:02, Csaba Halász wrote:
>>> Yes, I have just run into this very problem (see my earlier mail about libtiff)
>>> I just made some try-compile tests to check for known possible dependencies.
>>> I hoped somebody with more cmake experience could offer some insight,
>>> but didn't get any responses yet.
>>
>> That's a coincidence, I hadn't read your message.  My Tiff example was
>> just the simplest case I could think of that exhibits this bug.
>>
>> The method you use is unfortunately exponential in the number of
>> possible dependencies, an issue when N=40.  When there is no other
>> information available, perhaps a reasonable solution is a macro that
>> checks for undefined symbols matching a regex.  Is there a CMake way to
>> interrogate an archive for undefined symbols (presumably just calling nm
>> isn't recommended).
>>
>
> I am not sure CMake will ever get this correct by itself. Just because  
> there is an undefined symbol in a static lib does not mean it won't  
> work.  It might be a system library.   I don't think CMake should try to  
> find the missing libraries automatically as this would have to try all  
> libraries on a system.

In Csaba's case, the maximal dependency graph is known statically, but
he is manually rolling conditionals to test with every connected
subgraph.

> This just means a project should have a good FindWhatEver.cmake that
> handles the known depends.

The problem is, the dependency graph isn't known in advance.  Should I
have to update FindBar.cmake when Bar releases a new minor version that
has another optional dependency?

> If the project is built by CMake, then a
> find_package config file can be created that has this information.

Right, but I have to find lots of packages that are not built with
CMake.  They have a Makefile which is intended to be included by the
user to get required link lines.  These link lines usually include the
entire dependency graph of the package because that is the portable
thing.  It seems like CMake is 

> If you look at FindQt4, you can see CMake has the ability to handle
> very complicated depend information in a Find script.

The maximal graph is known statically and dumped into the FindQt4.cmake
module.  This is terrible because the module needs to be updated if Qt4
adds another optional dependency.  It's also a huge amount of code
duplication.

  ## Xrender
  IF(QT_QCONFIG MATCHES "xrender")
    FIND_LIBRARY(QT_XRENDER_LIBRARY NAMES Xrender PATHS ${QMAKE_LIBDIR_X11})
    MARK_AS_ADVANCED(QT_XRENDER_LIBRARY)
    IF(QT_XRENDER_LIBRARY)
      SET(QT_QTGUI_LIB_DEPENDENCIES ${QT_QTGUI_LIB_DEPENDENCIES} ${QT_XRENDER_LIBRARY})
    ENDIF(QT_XRENDER_LIBRARY)
  ENDIF(QT_QCONFIG MATCHES "xrender")

This is also broken if there are multiple ABI-incompatible installations
of libXrender because PATHS is searched *after* (contrary to the
documentation) system paths.  I believe it's correct if HINTS is used
instead, or if NO_DEFAULT_PATH is given.

Please see my FindPETSc.cmake module for a way to dynamically resolve
the dependencies.

  http://github.com/jedbrown/cmake-modules/tree/master/FindPETSc.cmake

The pattern is duplicated in FindiMesh.cmake (same repo).  It would be
ideal if I could find_library() the interface libs (those that my code
will call into directly) and then dump the whole recursive link line on
CMake to determine the rest.  When shared libs are being used, it would
be correct to skip all these extra libs, but when static libs are used,
they need to be included.

> However, it will not come for free, someone is going to have to code up 
> that depend information.

I think this needs to be made easier for module writers.  The FindQt4
solution is terrible.  Every FindXXX.cmake module for a package which is
not a stand-alone library needs this logic to work correctly with static
libs.  There are three common patterns that I see, (1) pkg-config or
something similar is used (2) the package supplies a Makefile that
provides a working link line (i.e. it includes recursive dependencies)
and (3) the maximal dependency graph is known and the module needs to
determine what subgraph is needed.

> There are several packages that deal with stuff like this, things like
> pkg-config.

The FindPkgConfig.cmake module looks broken too, it assumes that

  -L/A -la -L/B -lb

is equivalent to

  -L/A -L/B -la -lb

To get fully resolved paths, I think it needs to do something like what
is in my FindPETSc.cmake.  PkgConfig defines PREFIX_STATIC_* which is
good, but this means that whoever is writing the FindXXX module needs to
branch on whether the libs they search for are actually resolving to
static libs.  This *always* needs to be done, but it's not done in the
modules included with CMake (FindLibXslt and FindLibXml2).


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/20081106/50800c41/attachment.pgp>


More information about the CMake mailing list