[cmake-developers] RFC: add version to project() call

Alexander Neundorf neundorf at kde.org
Tue Jan 28 16:20:43 EST 2014

On Tuesday 28 January 2014, Brad King wrote:
> On 01/23/2014 04:08 PM, Alexander Neundorf wrote:
> > Any more comments left ?
> Moving the discussion from
>  http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/9156/focu
> s=9158
> back to the thread where it belongs:
> On 01/27/2014 04:58 PM, Stephen Kelly wrote:
> > Though I still don't like the behavior in the topic with project()
> > commands without a specified VERSION and the
> > why all the complexity is needed.
> > 
> > From what I understand, the reason it was added is related to using
> > add_subdirectory to add a self-contained/standalone project to host
> > buildsystem.
> My main concern that the VERSION complexity solves is for changing
> behavior of existing projects that are *not* modified at all.  We've
> established that a project() without VERSION needs to unset the
> PROJECT_VERSION variables because otherwise they would not correspond
> to the current PROJECT_NAME.  However, an existing project could do
>  # CMakeLists.txt
>  project(Top)
>  set(PROJECT_VERSION 1.0.0)
>  add_subdirectory(Sub)
>  # Sub/CMakeLists.txt
>  project(Sub)
>  message(STATUS "Top version = ${PROJECT_VERSION}")
> Since previous versions of CMake documented no special behavior
> for the PROJECT_VERSION variable this code is completely fine
> now, but would suddenly change in behavior if project() started
> So our options are
> (1) Design new behavior in a way that requires a change to the
>     project to activate.
> (2) Add a policy.  The policy should only trigger when the
>     project() command is about to unset a PROJECT_VERSION
>     variable that was set by user code and not by a previous
>     project() command.

I think my current version fits (1).
If nothing is changed in a project, the behaviour will not change at all (if 
it does, I have overseen something).

Things only start to change once a VERSION is added to a project() call.
Then, if a following project() call without VERSION sees the PROJECT_VERSION 
variable set, and sees that CMAKE_PROJECT_VERSION_SET_BY_PROJECT_COMMAND is 
set to TRUE, it unsets the PROJECT_VERSION.
This means it does not unset it if the user has manually set the variable and 
not added VERSION to any project() call.

The only condition where things will break (but still only after the user has 
actually modifed the project), is the following:


project(Foo VERSION 1.2.3)




IMO this is not the place for a policy, since the behaviour of the existing, 
unchanged project did not change, it is still working as it did before.

The issue above (which is probably unlikely), can be worked around by manually 
unsetting the guard variable:

project(Foo VERSION 1.2.3)




That's not too nice, but IMO a reasonable solution for fixing that hopefully 
rare error case.

Regarding (2): how should I detect whether PROJECT_VERSION has been set 
manually ?
I had some code which did that, but only if the version set via SET() was 
different than the version set via PROJECT(). I.e. it would work almost 
always, but in the cases where it wouldn't work, it would be very weird and 
hard to find. I don't think this would have been good behaviour.
Alternatively probably something could be done with variable_watch, but to me 
this seems a bit heavy for this purpose. I mean, it's only a rare breakage 
after a manual change to a project, and then all set() calls would be checked, 

I still think what I merged into next is Ok.
I can add a few more test cases, no problem.
I asked for more comments last Thursday, and there were none until I merged 
into next on Saturday.

I know that it would have been nice to squash the two actual code commits into 
I tried that two weeks ago or so, and I (or git, depending on how you see it) 
messed up my branches.
Asking google verified that squashing anything into the first commit of a 
branch is not really supported by git.
I didn't consider it worth it to try to follow the recipes suggested here 
commits or in other places just to merge the two commits into one.
The history is not messy, it's just one commit which could have been squashed. 
But even as they are they are not really hard to read.


More information about the cmake-developers mailing list