[CMake] function and raise_scope commands
Miguel A. Figueroa-Villanueva
miguelf at ieee.org
Fri Jan 18 10:22:47 EST 2008
On Dec 28, 2007 12:52 PM, Miguel A. Figueroa-Villanueva wrote:
> On Dec 28, 2007 11:36 AM, Ken Martin wrote:
> > > > > 1. CMake crashes if I use the same variable name as the argument and
> > > > > raise the scope later. That is, for the following function:
>
> <snip>
>
> > Specifically
> >
> > Variable value
> > --------------------
> > is_changed is_changed
> > set(${is_changed} "some_result")
> > is_changed some_result
> > raise_scope(${is_changed})
> >
> > well this last line becomes raise_scope(some_result) and since there is no
> > local variable named some_result it yerks. I have fixed the crash and it now
> > prints a nice warning message (on my local copy of cmake, not checked in
> > yet) but I'm not sure that is all the solution. I think a safer fix may be
> > to change the raise scope command to look like the following:
> >
> > raise_scope(var_name value var_name value ...)
> >
> > with a convention that you do not set variables that are to be returned (aka
> > passed by reference). In this case that would be is_changed. You leave
> > is_changed alone and only use it in the raise scope command. So the
> > resulting code would look like.
> >
> > function(track_find_variable cache_variable is_changed)
> > set(changed "some_result")
> > raise_scope(${is_changed} "${changed}")
> > endfunction(track_find_variable)
> >
> > which is safer. But I am still want to think about it a bit before I commit
> > the change.
>
> Well, I think the above is fine, but it's the convention of not using
> the variable that is solving the problem not the command syntax. That
> is, if you do a set(is_changed ...) before the raise_scope you still
> get into trouble.
>
> I think printing a warning when the argument contains the same name as
> the variable, and just have the convention of putting an underscore in
> front of the argument should work as well:
>
> function(track_find_variable _cache_variable _is_changed)
>
> At least, that is what I'm doing and it is simple to stick to it.
Hello Ken,
I see that you have applied the changes to cmake/cvs. With the new
syntax of raise_scope I now run to an unintuitive behaviour, which
should at least be emphasized in the documentation.
The problem is that when you do a raise_scope(var value), you don't
get a local copy of the variable. This is fine when you have direct
access to the variable, but when you are doing things in a loop it
gets into problematic behavior. I guess it is easier to demonstrate
with an example (pseudo-code/simplified version of my actual code):
# valid args: MAIN_INPUT;BIBFILES;...
foreach(arg ${ARGN})
if(${arg} ... is valid ...)
raise_scope(${arg} ${current_arg_list})
set(current_arg_list)
else(${arg} ... is valid ...)
list(APPEND current_arg_list ${arg})
endif(${arg} ... is valid ...)
endforeach(LIB)
# now some are not only valid, but required
if(${MAIN_INPUT} ...is empty...) # PROBLEM: here the local
MAIN_INPUT will always be empty
message(FATAL_ERROR "You need to provide a MAIN_INPUT file!")
endif(${MAIN_INPUT} ...is empty...)
Of course, you can solve this by doing a local set of MAIN_INPUT_LOCAL
(if you set a local variable with the same name, MAIN_INPUT, then we
are facing the same problem we were solving) in parallel with the
raise_scopes. That is:
# valid args: MAIN_INPUT;BIBFILES;...
foreach(arg ${ARGN})
if(${arg} ... is valid ...)
set(LOCAL_${arg} ${current_arg_list})
raise_scope(${arg} ${current_arg_list})
set(current_arg_list)
else(${arg} ... is valid ...)
list(APPEND current_arg_list ${arg})
endif(${arg} ... is valid ...)
endforeach(LIB)
# now some are not only valid, but required
if(${LOCAL_MAIN_INPUT} ...is empty...) # PROBLEM: here the local
MAIN_INPUT will always be empty
message(FATAL_ERROR "You need to provide a MAIN_INPUT file!")
endif(${LOCAL_MAIN_INPUT} ...is empty...)
Again, I think this behaviour is a quite unintuitive and should be
well documented, at least.
--Miguel
More information about the CMake
mailing list