[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