[CMake] Making it easier for downstreams to use my library

Alexander Neundorf a.neundorf-work at gmx.net
Fri Apr 9 14:20:29 EDT 2010


On Friday 09 April 2010, Michael Wild wrote:
> On 9. Apr, 2010, at 9:53 , Stephen Kelly wrote:
> > Hi,
> >
> > I've just tagged and tarballed a release candidate of Grantlee version
> > 0.1.0. Grantlee is a Free Software string template system written in Qt
> > and using CMake for its build system.[1]
> >
> > Most of my CMake knowledge is about writing simple CMakeLists.txt files
> > to consume other libraries. Writing the necessary CMake files to so that
> > downstreams can use my library is harder and I'm not sure I've done it
> > right.
> >
> > I'd appreciate some review of the CMake stuff if anyone has the time and
> > inclination.
> >
> > In particular, I'm not sure I'm doing the GrantleeUse.cmake file stuff
> > correctly. I'm include()ing the Use file in my CMakeLists.txt file so
> > that I can use its macros. Is that the usual way to do these things?[3]
> >
> > Also, the GrantleeConfig.cmake file looks wrong to me, but I don't know
> > the right way to implement it. There's a lot of if(UNIX) etc for things
> > which CMake must already know. I believe the solution I need there is
> > importing and exporting the library, but I haven't figured out how to do
> > it. [3]
> >
> > I'd like to know if any of this stuff should be a release blocker for me
> > or will cause problems down the line, and get some information of what
> > I'm doing wrong or what I could be doing better. Otherwise I'll probably
> > make the 0.1.0 release as-is and fix the ugly-but-works stuff later.
> >
> > All the best,
> >
> > Steve.
> >
> >
> > [1] http://www.grantlee.org
> > [2]
> > http://gitorious.org/grantlee/grantlee/blobs/master/cmake/modules/Grantle
> >eUse.cmake [3]
> > http://gitorious.org/grantlee/grantlee/blobs/master/cmake/modules/Grantle
> >eConfig.cmake.in
>
> Hi
>
> I had a look through your GrantleeConfig.cmake.in file. Most of the stuff
> looks fine, except where you set the library names:
>
> if (UNIX)
>   if (APPLE)
>     set(Grantlee_CORE_LIBRARY
> "${Grantlee_LIBRARY_DIR}/libgrantlee_core.dylib") set(Grantlee_GUI_LIBRARY
> "${Grantlee_LIBRARY_DIR}/libgrantlee_gui.dylib") else (APPLE)
>     set(Grantlee_CORE_LIBRARY
> "${Grantlee_LIBRARY_DIR}/libgrantlee_core.so") set(Grantlee_GUI_LIBRARY
> "${Grantlee_LIBRARY_DIR}/libgrantlee_gui.so") endif (APPLE)
> else (UNIX)
>   if (MINGW)
>     set(Grantlee_CORE_LIBRARY
> "${Grantlee_LIBRARY_DIR}/libgrantlee_core.dll") set(Grantlee_GUI_LIBRARY
> "${Grantlee_LIBRARY_DIR}/libgrantlee_gui.dll") else(MINGW)
>     set(Grantlee_CORE_LIBRARY "${Grantlee_LIBRARY_DIR}/grantlee_core.lib")
>     set(Grantlee_GUI_LIBRARY "${Grantlee_LIBRARY_DIR}/grantlee_gui.lib")
>   endif(MINGW)
> endif (UNIX)
>
> As you suspected, there's a much easier, more flexible and reliable way of
> doing things. E.g. in corelib/CMakeLists.txt do:
>
> install(TARGETS grantlee_core EXPORTS GrantleeExports
>          RUNTIME DESTINATION ${BIN_INSTALL_DIR}
>          LIBRARY DESTINATION ${LIB_INSTALL_DIR}
>          ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
>          COMPONENT Devel
> )
>
> This will add the grantlee_core library to the export set GrantleeExports.
> You can the write this export-set to a file using the following in your
> top-level CMakeLists.txt:
>
> install(EXPORT GrantLeeExports DESTINATION "${LIB_INSTALL_DIR}/grantlee")
>
> In your GrantleeConfig.cmake.in then replace the stuff from above with:
>
> include("@LIB_INSTALL_DIR@/grantlee/GrantleeExports.cmake")
>
> which will create IMPORTED targets with the same names as in the Grantlee
> project. So you can then set the variables
>
> set(Grantlee_CORE_LIBRARIES grantlee_core ${QT_QTCORE_LIBRARIES})
> set(Grantlee_GUI_LIBRARIES grantlee_gui ${QT_QTGUI_LIBRARIES})

I think this is not necessary at all when using the exported library targets, 
all the dependencies should be there already.
If you want to limit those dependency, you can use the 
LINK_INTERFACE_LIBRARIES feature of target_link_libraries(), e.g. if you use 
the following to link the grantlee_core library:
target_link_libraries(grantlee_core ${QT_QTCORE_LIBRARIES} ${JPEG_LIBRARIES} 
${ZLIB_LIBRARIEs})

then by default everything which links against grantlee_core would also link 
against JPEG and ZLIB.
You can limit this to e.g. only the Qt libs this way:

target_link_libraries(grantlee_core LINK_INTERFACE_LIBRARIES 
${QT_QTCORE_LIBRARIES})

> Also, you should make sure that Qt is available in your
> GrantleeConfig.cmake file, e.g. by calling find_package(Qt4 COMPONENTS
> QtCore QtGui REQUIRED). Don't call this in your GrantleeUse.cmake file,
> that's too late already. Also you might want to rename PARSE_ARGUMENT to
> GRANTLEE_PARSE_ARGUMENTS to avoid possible collisions with downstream
> packages.
>
>
> Things get a tad more complicated if you want this to also work from the
> build-tree. In that case you need to call the EXPORT(TARGETS ...) function
> and write the stuff to ${CMAKE_BINARY_DIR}/GrantleeExports.cmake. Things
> are trickier with the GrantleeConfig.cmake now, since you need to different
> versions: One for the install-tree and one for the build tree. I usually
> configure the former into
> ${CMAKE_BINARY_DIR}/InstallFiles/GrantleeConfig.cmake and the latter into
> ${CMAKE_BINARY_DIR}/GrantleeConfig.cmake. Also, recent versions of CMake
> have the very handy EXPORT(PACKAGE Grantlee) function which enables other
> projects to easily find the build tree.
>
> One last thing to consider: When you install GrantleeConfig.cmake, make
> sure it can be found easily by FIND_PACKAGE (as documented in the man-page)
> on all platforms you target.

which means to use the cmake 2.6.2-compatible location, which is 
lib/<package>/cmake/, and not the >= 2.6.3 compatible location, which is 
lib/cmake/<package>/, since KDE 4.4 (and I think also 4.5) still depend on 
CMake 2.6.2.

Alex


More information about the CMake mailing list