[CMake] Inter-target dependencies on autogenerated headers

Roger Leigh rleigh at codelibre.net
Wed Dec 18 18:54:15 EST 2013


Hi folks,

In the bioformats project, we make use of a custom tool to generate 
classes from an xml schema during the build.  This is working correctly, 
but breaks if building in parallel (with unix makefiles and make -j8).

For reference, this is the library built using a combination of static 
and generated sources¹. A second library is built against the first 
libraries headers and linked against it (and also contains its own 
generated code)².  Both use common cmake functions to do this³.  The 
problem is that when building in parallel, the second library is being 
compiled before the headers are generated in the first, and this causes 
obvious breakage--the compile fails outright.

To simplify the problem, what we have is two separate CMakeLists in two 
subdirectories:

Module a:
   set(a_generated_headers …)
   set(a_generated_sources …)
   set(a_static_headers …)
   set(b_static_sources …)
   add_custom_command(OUTPUT ${a_generated_headers} 
${a_generated_sources} COMMAND ${custom_tool} DEPENDS ${tool_dependencies)
   set(a_headers ${a_generated_headers} ${a_static_headers})
   set(a_sources ${a_generated_sources} ${a_static_sources})
   add_library(a SHARED ${a_sources} ${a_headers})

Module b:
   set(b_headers …)
   set(b_sources …)
   add_library(b SHARED ${b_sources} ${b_headers})
   target_link_libraries(b a)

The code generation, compiling and linking of module a works fine, and 
the code is regenerated if the dependencies are touched.  This works 
building serially or in parallel.

The compiling and linking of module b works fine only if building 
serially.  If building in parallel, the ${b_sources} which include any 
headers from module a's ${a_generated_headers} will fail if they are 
built before header generation in module a occurs.  This is inherently racy.

I'm at a bit of a loss for how to describe the needed dependency with 
cmake.  We have the correct library dependency with 
target_link_libraries, but this only appears to affect linking; I need 
to have a dependency which affects compiling.  I don't want any source 
files in module b compiling until the header generation in module a is 
complete (or to take it to the extreme, until module a is linked).  Is 
it possible to describe such a dependency with cmake?  Just making each 
of ${b_sources} depend upon "a" would be a workable solution.

Since these are in separate subdirectories, module b doesn't know about 
the custom command in module a, so it can't trigger source generation, 
and we don't have any explicit dependencies on any files in module a 
even if we could do that--module b doesn't have any special knowledge of 
the source layout to be able to do that.


I'd be very grateful for any suggestions.  Googling showed several 
questions and answers for source generation, but my problem here isn't 
really with the source generation (which works fine), but with 
preventing compiling until the generated files exist for targets which 
need the generated files indirectly.


Many thanks,
Roger


1. 
https://github.com/rleigh-dundee/bioformats/blob/cpp-bioformats-metadata/cpp/lib/ome/xml/CMakeLists.txt
2. 
https://github.com/rleigh-dundee/bioformats/blob/cpp-bioformats-metadata/cpp/lib/ome/bioformats/CMakeLists.txt
3. 
https://github.com/rleigh-dundee/bioformats/blob/cpp-bioformats-metadata/cpp/cmake/XsdFu.cmake


-- 
   .''`.  Roger Leigh
  : :' :  Debian GNU/Linux    http://people.debian.org/~rleigh/
  `. `'   schroot and sbuild  http://alioth.debian.org/projects/buildd-tools
    `-    GPG Public Key      F33D 281D 470A B443 6756 147C 07B3 C8BC 
4083 E800


More information about the CMake mailing list