[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