[CMake] CMake and include only libraries

Michael Wild themiwi at gmail.com
Tue Apr 5 05:22:30 EDT 2011


On 04/05/2011 11:02 AM, Theodore Papadopoulo wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> On 04/05/2011 03:53 AM, Michael Hertling wrote:
>>
>> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
>> PROJECT(HEADERLIBRARY C)
>> SET(CMAKE_VERBOSE_MAKEFILE ON)
>> FILE(WRITE ${CMAKE_BINARY_DIR}/f.h "void f(void)\n")
>> ADD_LIBRARY(f STATIC f.h)
>> SET_TARGET_PROPERTIES(f PROPERTIES
>>     LINKER_LANGUAGE C PUBLIC_HEADER ${CMAKE_BINARY_DIR}/f.h)
>> ADD_CUSTOM_COMMAND(TARGET f POST_BUILD
>>     COMMAND ${CMAKE_COMMAND} -E remove $<TARGET_FILE:f>)
>> INSTALL(TARGETS f EXPORT f
>>     PUBLIC_HEADER DESTINATION include
>>     ARCHIVE DESTINATION include OPTIONAL)
>> INSTALL(EXPORT f DESTINATION share)
>>
>> Note the ARCHIVE DESTINATION *include* to prevent the INSTALL() command
>> from creating a directory for the non-existing library. The downside of
>> that approach is a little extra cost to build the empty library each
>> time make is run.
>>
>> Nevertheless, the export file created by INSTALL(EXPORT ...) will still
>> contain a reference to the non-existing libf.a, so I wonder what's the
>> point of using the INSTALL() command's EXPORT feature with a header-
>> only library, i.e. what's so bad with INSTALL(FILES ...) or - after
>> setting up the library's headers - with INSTALL(DIRECTORY ...)?
> 
> I tried that, and indeed there remains a reference to the libf.a.
> The idea is to have a single uniform mecanism to do export, all the more
> that things get more complex when you want to use the built library
> either at the build location or at the install location....
> Since the EXPORT seems to be done for that, I expected it to work with
> INSTALL(FILES ...) or INSTALL(DIRECTORY ...) (exactly for headers) but
> it does not....
> 
> Honestly, headers seem sometimes a second class citizen in cmake: there
> are some properties related to headers but few header knowledgeable
> commands...
> 
> On 04/05/2011 03:53 AM, Michael Wild wrote:
>> I don't see what the problem with install(FILES ...) is? If you have a
>> header-only library, you just don't need any of the complex EXPORT
>> stuff. That is only related to the dependencies between libraries,
>> executables and transitive linking. In the case of a header-only library
>> you dump the files, create a XXXConfig.cmake and XXXConfigVersion.cmake
>> file, and be done with.
> 
> Well, I tend to disagree. Headers also have dependencies (to other
> headers or even to other libraries), so the concepts of transitive
> linking are useful as well for header-only libraries.
> 
> Again, headers are a full part of software development, so (at least to
> me) it makes sense to treat them as well as libraries, executables,...
> That they happen to be readble and (usually) machine independent, does
> not mean that they do not convey dependencies, have version problems,
> ... I really think that having a target of type INCLUDES might bring
> consistency to cmake, and ease of use to users.
> 
> If peope share this view, I might even try to add such a thing.
> For now, I guess I have to rely on INSTALL(FILES|DIRECTORY ...)


The whole EXPORT stuff is target at ABI compatibility, not API
compatibility. As I said, it is fairly easy to write a fully functional
XXXConfig.cmake.in file for a header-only library. Put something like
the following in it:

############################
# Tell the user project where to find our headers
set(XXX_INCLUDE_DIR "@XXX_INCLUDE_DIR@")

# Find required dependency
find_package(YYY REQUIRED)

# Set things up for the user-project
set(XXX_INCLUDE_DIRS "${XXX_INCLUDE_DIR}" ${YYY_INCLUDE_DIRS})
set(XXX_LIBRARIES ${YYY_LIBRARIES})
#############################

I really don't see how CMake could automate this any more, or what
additional information it could generate for you. If your headers have
dependencies, just put the appropriate find_{package,path,library} calls
in there. Besides, you'll have to create a XXXConfig.cmake file anyways
where you would need to include the exported targets, so this is just as
simple.

I'm still a bit wondering what you actually want CMake to do for you.

Michael



More information about the CMake mailing list