[CMake] How to generate a source file with unpredictable dependency
Alexander Neundorf
a.neundorf-work at gmx.net
Tue May 13 17:31:37 EDT 2008
On Tuesday 13 May 2008, jlh wrote:
> Hello list!
>
> I just switched to cmake from another build system, so I'm still
> very new to cmake. I'm using git for source control and want my
> executable to include the commit ID. CVS and Subversion can do
> this with keyword substitution, but that is considered a no-no in
> the git world. Git teaches that this is a task to be done by your
> build system and not by your source control software. I agree
> with this and doing it their way proved to be a lot more flexible
> than keywords anyway (in a different project, where I wrote
> Makefiles manually). However, I have troubles getting this done
> with cmake.
>
> I want a file version.cpp (containing commit ID, time stamps and
> other info) to be automatically generated by a script called
> makeversion, which shall be run any time the main target gets
> build. makeversion will update version.cpp if required, but not
> touch it if the content doesn't change. I have tried this:
>
> ADD_CUSTOM_COMMAND(OUTPUT version.cpp COMMAND ./makeversion
> COMMENT "Checking version.cpp" VERBATIM)
> SET_SOURCE_FILES_PROPERTIES(version.cpp PROPERTIES GENERATED TRUE)
>
> The problem is that version.cpp has no dependencies and thus gets
> generated once and then will never be considered outdated as long
> as it exists. I want the command to be run every time, because
> ./makeversion might want to update version.cpp based on
> unpredictable (from cmake's point of view) facts, for example the
> current date. There's no meaningful file I could add with DEPENDS
> to above command.
>
> Then there's ADD_CUSTOM_TARGET(), which does just what I want: Its
> target is considered to always be out of date, so that the command
> is always run. But conceptually, this feels wrong to me, because
> it's meant for targets and version.cpp is not a target, it's a
> generated dependency. But I tried anyway:
>
> ADD_CUSTOM_TARGET(version.cpp ./makeversion
> COMMENT "Checking version.cpp" VERBATIM)
> SET_SOURCE_FILES_PROPERTIES(version.cpp PROPERTIES GENERATED TRUE)
>
> This worked like a charm for a while! makeversion gets executed
> every time and version.cpp is recompiled whenever its content
> changed. But then I found out that this fails to work when
> version.cpp doesn't exist yet at all. It fails like this:
>
> make[2]: *** No rule to make target `version.cpp', needed by
> `CMakeFiles/project.dir/depend.make.mark'. Stop.
>
> Since version.cpp is now a target, running "make version.cpp" does
> what it's supposed to. While working as a target, it fails to
> work as a dependency.
>
> So how would I make this work? I'm using cmake 2.4.8 on linux.
ADD_CUSTOM_TARGET(make_version_target ${CMAKE_CURRENT_SOURCE_DIR}/makeversion
COMMENT "Checking version.cpp" VERBATIM)
SET_SOURCE_FILES_PROPERTIES(version.cpp PROPERTIES GENERATED TRUE)
create your target...
ADD_EXECUTABLE(foo main.cpp version.cpp)
ADD_DEPENDENCIES(foo make_version_target)
Now make_version_target is a target which your executable explicitely depends
on and will always be built before the executable (ok, I didn't test).
Alex
More information about the CMake
mailing list