[CMake] Generated source files and dependencies(+) (Esben Mose Hansen)

ZNV mejedi at gmail.com
Tue Sep 16 15:48:16 EDT 2008


Hi, Esben.
Thank you very much for helpful pointers.

>> project(FOO)
>> add_custom_target(generate ALL DEPENDS ${FOO_BINARY_DIR}/generated.h)
>> add_custom_command(OUTPUT ${FOO_BINARY_DIR}/generated.h COMMAND ...)
>> include_directories(${FOO_BINARY_DIR})
>> add_library(foo foo.c) # foo.c includes generated.h
>> add_library(bar bar.c) # bar.c includes generated.h as well
>>
>> Finally, how do I control targets ordering during build? I have
>> 'generate' target that generates 'generated.h'.
>> I have 'foo' and 'bar' targets that use 'generated.h'. How can I force
>> 'generate' to be build before 'foo' and 'bar'?
>
> That is what dependency tracking is for. And that should be handled
> automatically by the add_custom_target.

My experience contradicts your statement.
For instance if I remove 'ALL' token from my ADD_CUSTOM_TARGET,
'generate' target is not built at all. If I move 'generate' target
declaration
below 'foo' and 'bar', CMake attempts to build targets in wrong order:
(1)foo, (2)bar, (3)generate.

Is dependencies tracking actually two level -
(1)file-level dependencies, and
(2)target-level dependencies?

I mean, within a target file-to-file dependencies are tracked. If any file
is updated, everything depending on that file within the target is rebuilt.
Compiler, linker or random utility hooked in by ADD_CUSTOM_COMMAND
runs.

Additionally there are target-to-target dependencies. Some targets get
the timestamp from associated output file (like ADD_LIBRARY or
ADD_EXECUTABLE does). Other ones (like ADD_CUSTOM_TARGET)
are always considered out of date. Inter-target dependencies are
created either explicitly with ADD_DEPENDENCIES or implicitly
as side effect of another command like TARGET_LINK_LIBRARIES.

It looks like file-to-file dependencies do not span target boundaries.
Consider the following dependency graph:

random_data -> generated.h -> foo.c

It appears to me that this graph actually breaks into two parts
without contributing to targets relative ordering:

generated [random_data -> generated.h]
foo           [generated.h -> foo.c]

Please correct my guesswork if I was wrong.

If formal model behind CMake was written down, and availible
online alongside with already perfect per-command help it will
be so nice!

WBR, Mejedi

> Date: Mon, 15 Sep 2008 09:15:44 +0200
> From: Esben Mose Hansen <kde at mosehansen.dk>
> Subject: Re: [CMake] Generated source files and dependencies(+)
> To: cmake at cmake.org
> Message-ID: <200809150915.45723.kde at mosehansen.dk>
> Content-Type: text/plain;  charset="iso-8859-1"
>
> On Sunday 14 September 2008 15:14:15 ZNV wrote:
>> Hi!
>>
>> I am generating header file for subsequent use by multiple
>> libraries/executables in CMake-controlled build.
>> My preliminary solution which happens to work is the following; I
>> wonder if it is correct.
>
> If you look at my google protocols buffer module (which I submitted a
little
> above), it uses the same strategy
>
>>
>> project(FOO)
>> add_custom_target(generate ALL DEPENDS ${FOO_BINARY_DIR}/generated.h)
>> add_custom_command(OUTPUT ${FOO_BINARY_DIR}/generated.h COMMAND ...)
>> include_directories(${FOO_BINARY_DIR})
>> add_library(foo foo.c) # foo.c includes generated.h
>> add_library(bar bar.c) # bar.c includes generated.h as well
>>
>> The first question is, does CMake detect that 'foo' library depends on
>> 'generated.h' automaticly?
>
> Since it includes the generate.h, that should not be a problem.
>
>>
>> The second question is, when are source/header files dependencies
>> scanned? Does it happen
>> during configure stage (ie when CMake runs)? Does it happen during
>> build stage (when CMake-
>> generated Makefile/whatever runs)?
>
> In big projects, you can actually see CMake writing "scanning dependencies
> for". I think it does it before building each target.
>
>> Anyway, I do not understand, how #include dependencies created by
>> generated files are handled.
>
> Same way. The dependencies are scanned before the target that depends on
> generated.h is compiled. It would seem to me that this means scanning the
> dependencies for libfoo twice, but I'm no expect in this.
>
>> Assume 'foobar.c' is generated. For sure it includes something. During
>> configure stage there is
>> no 'foobar.c'. Do I have to manually enlist 'foobar.c' dependencies
>> via OBJECT_DEPENDS property?
>> Or may be 'foobar.c' is scanned on build stage, and everything just works
>> fine?
>
> The latter. It works fine with the protocols buffer this way, and also the
> FindQt.cmake seems to work like this (that include is somewhat involved,
> though)
>
>>
>> Finally, how do I control targets ordering during build? I have
>> 'generate' target that generates 'generated.h'.
>> I have 'foo' and 'bar' targets that use 'generated.h'. How can I force
>> 'generate' to be build before 'foo' and 'bar'?
>
>> Is ADD_DEPENDENCIES the only option? Maybe a clever hack exists to
>> built the given target *before* all
>> other project's targets?
>
> That is what dependency tracking is for. And that should be handled
> automatically by the add_custom_target.
>
> --
> kind regards, Esben
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.cmake.org/pipermail/cmake/attachments/20080916/64d30350/attachment-0001.htm>


More information about the CMake mailing list