[CMake] Study of Cache Interaction with If Statements

Hostile Fork hostilefork at gmail.com
Fri Jun 12 13:31:08 EDT 2009


Hello cmakers,

I have been looking at some unusual ways in which values stored in the  
cache interact with the 'if' statement.  I'll start with a simple case  
that matches typical programming intuition:

	set (VAR1 ON)
	set (VAR2 OFF)
	if (VAR1)
         	set (VAR2 ON)
		message ("VAR2 is ${VAR2}")
	endif (VAR1)

This prints "VAR2 is ON".  But if we use the cache variation for both  
assignments:

	set (VAR1 ON)
	set (VAR2 OFF CACHE BOOL "Variable 2 Label A")
	if (VAR1)
         	set (VAR2 ON CACHE BOOL "Variable 2 Label B")
         	message ("VAR2 is ${VAR2}")
	endif (VAR1)

...then if doing a fresh make, this will print "VAR2 is OFF".  Running  
'cmake -DVAR2=ON' causes it to say "VAR2 is ON".  Running 'cmake -i'  
reveals the label for VAR2 as "Variable 2 Label A".

Looking at a third case:

	set (VAR1 ON)
	set (VAR2 OFF CACHE BOOL "Variable 2")
	if (VAR1)
         	set (VAR2 ON)
         	message ("VAR2 is ${VAR2}")
	endif (VAR1)

...for a fresh make will print "VAR2 is ON".  Running 'cmake - 
DVAR2=OFF' does not change this.  And just to round out the example  
set...

	set (VAR1 OFF)
	if (VAR1)
         	set (VAR2 ON CACHE BOOL "Variable 2")
	endif (VAR1)

This will give an interactive prompt for "Variable 2" when using  
("cmake -i"), even though the value is never needed.

I'll try and guess a few points:

(1) 'if' cannot control whether something is prompted for in the  
interactive mode.  one or more appearance of a 'CACHE' by an  
associated 'set' will trigger a prompt for that variable

(2) it is possible to have multiple cached "set" statements for the  
same variable... as well as to mix cached and non-cached variable  
assignments.  but each cached set will always use the cache value

(3) there is no apparent enforcement of consistency in the cache  
defaults or labeling... and which default/label wins may not be a well- 
defined behavior

I was disappointed about (1), because I have several options which are  
only relevant if another option is set.  There are also some options  
which cannot be set together.  So currently I have checks like this in  
the header file:

	#if USE_FOO
	#	if USE_BAR
	#		error Cannot have USE_BAR=1 when USE_FOO=1
	#	endif
	#else
	#	if USE_FOO_OPTIMIZATION
	#		error cannot have USE_FOO_OPTIMIZATION=1 when USE_FOO=0
	#	endif
	#endif

What makes (2) confusing is that when you use CACHE with 'set', it  
ceases to have very much in common with set(VAR VAL).  Correct me if  
I'm wrong, but its semantics seem like "Get From Cache And Ignore Val  
Unless Cache Is Empty And Then Maybe Use Val If There Are No Other Set  
With Cache Statements Which Supply A Different Val...Otherwise Who  
Knows" operator.

This might be helped by breaking 'set' into a few smaller commands,  
such as those which define cache values and which fetch them.  That  
would also mean that CMake could keep people from thinking (1) is  
possible by requiring statements which declare cache variables  
(option, "definecache(?)") to appear at top scope.

Thoughts?  I'm curious if there is any documentation which addresses  
these kinds of issues.

Thanks!
	---Brian

http://hostilefork.com


More information about the CMake mailing list