[CMake] How to rerun cmake if a file changes

Vladislav Vaintroub vvaintroub at googlemail.com
Tue Nov 23 16:16:42 EST 2010



> -----Original Message-----
> From: Eric Noulard [mailto:eric.noulard at gmail.com]
> Sent: Dienstag, 23. November 2010 21:07
> To: Vladislav Vaintroub
> Cc: cmake at cmake.org
> Subject: Re: [CMake] How to rerun cmake if a file changes
> 
> 2010/11/23 Vladislav Vaintroub <vvaintroub at googlemail.com>:
> > Hello,
> > we use a text file as input for out build to store version info.  The
> > content of this file is
> > ./VERSION:
> >
> > MYSQL_VERSION_MAJOR=5
> > MYSQL_VERSION_MINOR=5
> > MYSQL_VERSION_PATCH=8
> > MYSQL_VERSION_EXTRA=
> >
> > During cmake run, the information is extracted, parsed,
> > CPACK_PACKAGE_FILE_NAME is generated,  and some other things
> happen,
> > e.g we configure a header file mysql_version.h.
> > So far, it works nicely, the only problem  with it is that cmake is
> > not rerun when this file changes. I made an attempt to fix it by
> > introducing custom command and custom target
> >
> > ADD_CUSTOM_COMMAND(
> >   OUTPUT  ${CMAKE_BINARY_DIR}/VERSION.dep
> >   COMMAND ${CMAKE_COMMAND} ${CMAKE_BINARY_DIR}
> >   COMMAND ${CMAKE_COMMAND} -E touch
> ${CMAKE_BINARY_DIR}/VERSION.dep
> >   DEPENDS ${CMAKE_SOURCE_DIR}/VERSION
> >   )
> > ADD_CUSTOM_TARGET(check_version ALL DEPENDS
> > ${CMAKE_BINARY_DIR}/VERSION.dep)
> >
> > This seems to work but is not without problems. For example the very
> > first build with rerun cmake to generate VERSION.dep.  It takes some
> > seconds with Makefiles,  this is not a big problem, however in Visual
> > Studio (I'm using
> > VS2010) the very first build would tell me "N  solutions regenerated,
> > you want to rebuild?", and then  I clicking "OK" a COM error would
> > popup (the build would actually still continue run successfully
> > despite popups and COM error).
> >
> > So the question is if there is a nicer way to accomplish what I want to
do.
> > I'm aware that if VERSION had CMake syntax with
> > SET(MYSQL_MAJOR_VERSION 5) etc, then I could just INCLUDE this file,
> > and this would fix  problems I have.  I'm however more interested in a
> > solution that would not force that file to be written in CMake syntax.

Hi Eric,
thanks for looking.

> Do you want to preserve  the "content" of the file or you don't want to
write
> MYSQL_VERSION_xxx in CMake syntax?

One of the  wishes now that autotools-based build system is gone completely,
was to be able to simply identify version ,e.g in with shell syntax
source ./VERSION 
(use MYSQL_VERSION_XXX in my favorite shell script)

Until recently, this was done with parsing   ./configure.in, even
CMake-based build would extract this info from some AC_INIT(...) to find out
the major, minor and patch version
     
 
> If you only want to preserve this particular file you could generate it
file from
> your main CMakeLists.txt if you add version definition in CMakeLists.txt:
> 
> SET(MYSQL_VERSION_MAJOR 5)
> SET(MYSQL_VERSION_MINOR 5)
> SET(MYSQL_VERSION_PATCH 8)
> SET(MYSQL_VERSION_EXTRA "")
> 
> some VERSION.in file contains;
> MYSQL_VERSION_MAJOR=@MYSQL_MAJOR_VERSION@
> MYSQL_VERSION_MINOR=@MYSQL_VERSION_MINOR@
> MYSQL_VERSION_PATCH=@MYSQL_VERSION_PATCH@
> MYSQL_VERSION_EXTRA=@MYSQL_VERSION_EXTRA@
> 
> 
> configure_file(${CMAKE_SOURCE_DIR}/VERSION.in
>                     ${CMAKE_BINARY_DIR}/VERSION}
>                     @ONLY)
> 
> if "VERSION" file has to be in source tree (would be better to avoid
that):
> 
> configure_file(${CMAKE_SOURCE_DIR}/VERSION.in
>                     ${CMAKE_SOURCE_DIR}/VERSION}
>                     @ONLY)
> 
> If you don't want that you should already be generating mysql_version.h
> using this file and may be some custom command/target and I bet the rest
of
> the build depends on mysql_version.h?

I understand the idea, and yes, it sounds like solution, though not for
exactly  my problem :) I would still prefer some way to do it without
generating VERSION, but considering it as build input instead.  Some people
would prefer to  run "source ./VERSION" prior to "cmake", or perhaps without
cmake at all 

And I guess I found a way around it after some experimentation. It seems to
work If I do this for example
CONFIGURE_FILE(
  ${CMAKE_SOURCE _DIR}/VERSION 
  ${CMAKE_BINARY_DIR}/VERSION.junk
)

I'd never use output file VERSION.junk, but CONFIGURE_FILE alone seems to
have the desired side-effect, it will force cmake to rerun if  VERSION file
changes.

> So may be your custom command used to generate mysql_version.h is
> lacking a file dep?

For mysql_version.h , there was no dependency and no special target, it was
just parsing  ./VERSION (and, prior to that ./configure.in) and
CONFIGURE_FILE.  Yes, this lacked a dependency.  But simple custom target
would not solve our problems either, we do other things with version
numbers, generating CMAKE_PACKAGE_FILE_NAME for example. Changing this
variable would require rerunning cmake in my understanding

So far missing dependency this was never considered  important, as the
version numbers change rarely, and probability that something goes wrong is
very low. It worst case, rerun cmake per hand, et viola.  And our automated
builds would build everything from scratch anyway. While it is  rather minor
annoyance,  I was just curious if there is  an established way to declare
"rerun cmake if this file changes"-dependency  for non-CMake file.

> By the way I cannot find any VERSION file on a fresh update of lp:mysql-
> server ?

Try
 bzr branch lp:~mysql/mysql-server/mysql-trunk-bugfixing 

It is not in "main" branch of trunk series yet.

> --
> Erk
> Membre de l'April - « promouvoir et défendre le logiciel libre » -
> http://www.april.org



More information about the CMake mailing list