[CMake] How to generate a source file with unpredictable dependency

jlh jlh at gmx.ch
Tue May 13 17:16:28 EDT 2008


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.
All help appreciated!

Thanks in advance,
jlh


More information about the CMake mailing list