[CMake] Argh! Thwarted at every turn!

Paul Smith paul at mad-scientist.net
Fri May 20 11:58:09 EDT 2016


I'm using CMake 3.5.2 generating for Linux / OSX / Visual Studio.

I'm creating a shared library.  This shared library is constructed
mostly from other libraries (which are also built in other directories
by this cmake setup).

I have been doing this for a long time and it worked fine:

  add_library(mylibrary SHARED foo.cpp foo.h bar.cpp bar.h ...)
  target_link_libraries(mylibrary PRIVATE mylib1 mylib2 VerData ...)

Fine.  Now the problem is that I need to generate a link map and I have
a script that parses the object files in mylibrary to create the link
map (the link map is only created/used on Linux of course).

Well, I can't find any way to get a listing of the .o files that are
generated by compiling the .cpp files in the add_library() call above.

So, instead I decided to turn those files into a library, themselves,
then I can use $<TARGET_FILE:mylibrary> with my add_custom_command()
that runs the link map generator script.

However, then I have something like this:

  add_library(libIntern STATIC foo.cpp foo.h bar.cpp bar.h ...)
  add_library(mylibrary SHARED linkmap)
  target_link_libraries(mylibrary PRIVATE libIntern mylib1 mylib2 VerData ...)

  add_custom_command(OUTPUT linkmap COMMAND genmap $<TARGET_FILE:libIntern> ...)
  set_property(TARGET mylibrary APPEND PROPERTY LINK_DEPENDS linkmap)

But this doesn't work because since libIntern is a static library only
the symbols that are referenced somewhere else are included, and no
symbols are actually referenced anymore since there are no source files
in the library.

So then I thought, well, I'll use an OBJECT library for the internal
one:

  add_library(libIntern OBJECT foo.cpp foo.h bar.cpp bar.h ...)
 
add_library(mylibrary SHARED $<TARGET_OBJECTS:libIntern>)
 
target_link_libraries(mylibrary PRIVATE mylib1 mylib2 VerData ...)

  add_custom_command(OUTPUT linkmap COMMAND genmap
$<TARGET_FILE:libIntern> ...)
  set_property(TARGET mylibrary APPEND
PROPERTY LINK_DEPENDS linkmap)

That worked for mylibrary... but of course I can't use $<TARGET_FILE:> anymore with an OBJECT library.  And I can't use $<TARGET_OBJECTS:> in my custom command either.  In fact I can't find any way to get a list of the object files that are part of libIntern.

So then I finally said "whatever" and created another static library out of the OBJECT library, just for use with my linkmap generating script:

  add_library(libIntern OBJECT foo.cpp foo.h bar.cpp bar.h ...)
  add_library(mylibrary SHARED linkmap $<TARGET_OBJECTS:libIntern>)
  target_link_libraries(mylibrary PRIVATE mylib1 mylib2 VerData ...)

  add_library(internStatic STATIC $<TARGET_OBJECTS:libIntern>)
  add_custom_command(OUTPUT linkmap COMMAND genmap $<TARGET_FILE:internStatic> ...)
  set_property(TARGET mylibrary APPEND PROPERTY LINK_DEPENDS linkmap)

This is not nice but it does work...

Except for one thing.  Some of the files in foo.cpp ... depend on a header file which is generated as part of the build, using a separate custom command, and I handle this by compiling a little static library that needs this header file:

  add_custom_command(OUTPUT verdata.h COMMAND ...)
  set_source_files_properties(verdata.h PROPERTIES HEADER_FILE_ONLY TRUE)
  add_library(VerData STATIC Version.cpp Version.h)
  set_property(SOURCE Version.cpp APPEND PROPERTY OBJECT_DEPENDS verdata.h)

Then the VerData library is added to target_link_libraries() everywhere.  Coming from a strictly makefile background it doesn't seem to me that this should be sufficient, but in fact it appears to work.

But in my new setup you can see that the OBJECT library no longer depends on the VerData library, which means that the auto-generated header file is not ensured to be created before the compilation of the objects in libIntern.  And in fact, I get compilation errors because the verdata.h file is not generated before these compilations (particularly in Xcode, for some reason).

And, I don't know how to solve this problem: I can't find any way to add a new prerequisite to the the libIntern OBJECT library to ensure that the VerData library is built first.  I can't add a target_link_libraries() to an OBJECT library.  I sure don't want to have to explicitly set the OBJECT_DEPENDS property on every single source file!


All I want to do is call a script passing the object files to generate a link map before I create my shared library, and I've gone all the way down this rabbit hole...

Help!


More information about the CMake mailing list