[CMake] (no subject)

Ken Martin ken.martin at kitware.com
Wed May 25 16:32:28 EDT 2005


> I have yet another question about something in cmake :)  For some
> reason, variables seem to have different actions depending on where it
> is used.  I'm trying to make a build system for our product and it seems
> that dereferencing variables doesn't work in one place, but does in
> another...
 
> 
> As far as ENV{} goes, sometimes it seems to need the $ENV{A}, sometimes
> it uses the bare variable name ENV{A} and sometimes it needs the quotes
> around them to work.  For example, STREQUAL sometimes doesn't work with
> the quotes and sometimes does.  Can anyone give a clear description of
> variable usage, including deferencing and such?  It's getting kind of
> confusing..
> 

This can be a bit confusing and could probably stand some cleanup. The basic
idea is that if a variable is dereferenced in a command invocation then it
will be replaced with its value prior to invoking the command (this is true
of all commands that do not implement InvokeInitialPass) the commands that
typically do not expand arguments prior to invocation are commands like
FOREACH and WHILE.

So what about the IF command? It stores its arguments prior to expansion
(for matching with the ENDIF) but then expands them prior to calling the IF
logic. Long story short, generally assume arguments (e.g. ${FOO} will be
evaluated prior to invoking a command.

Now what does this mean? Well for an IF statement it means that

SET (FOO)
SET(BAR 1)
IF (${FOO} AND ${BAR})

Will be expanded to

IF (AND 1)

Which will result in a syntax error (open beer, take a swig). That is why
logical arguments to IF are typically not provided with a ${ } because you
are really passing the name of a variable not its value (i.e. pass by
reference). In the above example IF (FOO AND BAR) is really what you want.
In longhand for the IF command with logical operations it really stands for
something like

IF ( IS_VARIABLE_DEFINED_AND_TRUE(FOO) AND IS_VARIABLE_DEFINED_AND_TRUE(BAR)
)

The same issue applies to the string comparisons in the IF command. For
example:

IF (${FOO} STREQUALS "fubar")

Will expand to

IF (STREQUALS "fubar")

and another syntax error (yuck, take another swig). When what you really
want is to make sure that there is a first argument even if FOO is not set.
So you do

IF ("${FOO}" STREQUALS "fubar")

Which will expand to IF ("" STREQUALS "fubar") which is a valid syntax. So
depending on how the argument is used in the IF command you may want to
leave it alone or quote it. Occasionally you may want to evaluate it (e.g.
${FOO}) For most commands a good rule of thumb is to dereference the
variable but when in doubt look at what the command invocation would look
like with your dereferenced variables expanded. If it looks like a bad
signature then you probably want to quote the variable or not dereference
it. The IF command is the main troublemaker with this.

Hope this helps. Now you can relax with a beer and enjoy your rather nicely
commented CMakeLists file. 

Thanks
Ken

P.S. Should probably add this to the FAQ if something like that isn't there.




More information about the CMake mailing list