[CMake] Return values from CMake functions?

Bartlett, Roscoe A rabartl at sandia.gov
Thu Nov 20 13:19:50 EST 2008


Ken,

> -----Original Message-----
> From: Ken Martin [mailto:ken.martin at kitware.com]
> Sent: Thursday, November 20, 2008 11:08 AM
> To: Bartlett, Roscoe A; cmake at cmake.org
> Subject: RE: [CMake] Return values from CMake functions?
>
> While not super sexy, you can do what you are looking for
> with a minor twist. The following code illustrates it.
>
> function(assertdef VARNAME RESULT_NAME)
>     if(NOT DEFINED ${VARNAME})
>       message(SEND_ERROR "Error, the variable ${VARNAME} is
> not defined!")
>     endif()
>     set (${RESULT_NAME} ${VARNAME} PARENT_SCOPE)
> endfunction()
>
> # comment the next line to see the two different results set (myvar 1)
>
> assertdef(myvar varname)
> if (${varname})
>   message("${varname} is true")
> endif()

The above example you show does not solve the problem.  You are still typing 'varname' twice and therefore, you could still type:

  assertdef(myvar varname)
   if (${varnames})
     message("${varname} is true")
   endif()

and your code is wrong.  If CMake could add a mode where all variables had to be defined before being used (like with 'use strict' in Perl), then this particular use case would go away.

However, the general issue of function returns still remains and would make a good bit of CMake code a lot smaller and cleaner.

> With respect to the general question of functions returning
> values it could be done but it is a bit of a big change.
> Functions and commands look the same (and should act the same
> IMO) to the people using them. So really we are talking about
> commands returning values. This is mostly just a syntax
> issue. Right now we have
>
> command(arg arg arg...)
>
> to support return values we need something that could handle ...
>
> command (arg command2(arg arg) arg arg ...)
>
> or in your case
>
> if(assertdef(foo))
>
> or in another case
>
> set(foo get_property(...))
>
> etc. This hits the parser and the argument processing in
> CMake but I think it could be done. I guess I'm not sure if
> we *should* do it. Open to opinions here.

The suggestion I had was to use the ${SOMETHING(...)} syntax to invoke a function call.  So you would have:

  command (arg ${command2(arg arg)} arg arg ...)

instead of

  command (arg command2(arg arg) arg arg ...)

The CMake parser already has to handle ${SOMETHING} or order to extract variable values.  What I am suggesting is that you just update the logic in the handler for variable dereferencing to consider function/command invocations ${SOMEFUNCTION(...)}.  In this way, you would *not* effect the parser, just the handler for variable dereferencing.  Does that this seem reasonable?

Arguing that CMake does not need function returns is like arguing that C, C++, Perl, Python, Java, Fortran (77, 90, 95, 2003, 2008) etc. do not really need function returns.  It is a very useful programming language feature and that is way every serious language supports it.

Cheers,

- Ross



> From: cmake-bounces at cmake.org
> [mailto:cmake-bounces at cmake.org] On Behalf Of Bartlett, Roscoe A
> Sent: Thursday, November 20, 2008 11:19 AM
> To: cmake at cmake.org
> Subject: [CMake] Return values from CMake functions?
>
> Hello,
>
> Has anyone thought about the possibility of adding return
> values from CMake functions?  This would be a very useful
> language feature that the Trilinos CMake files would use everywhere.
>
> Here is an example use case.  One problem with CMake is that
> it has very loose checking.  For example, if I write:
>
>    IF (MYVARABLE)
>      ...
>    ENDIF()
>
> Instead of what I meant:
>
>    IF (MYVARIABLE)
>      ...
>    ENDIF()
>
> then my CMakeLists.txt file will not work correctly.  What I
> have been doing is to instead write an ASSERT_DEFINED(...)
> macro and then use it as:
>
>    ASSERT_DEFINED(MYVARIABLE)
>    IF (MYVARIABLE)
>      ...
>    ENDIF()
>
> Of course the problem with this is that I could misspell one
> of the uses as:
>
>    ASSERT_DEFINED(MYVARIABLE)
>    IF (MYVARABLE)
>      ...
>    ENDIF()
>
> and I am back in the same situation.  The problem is that I
> am duplicating the variable name.  This is a fundamental
> software engineering issue that needs to be addressed in some way.
>
> What I would like to be able to write is a function like:
>
>   FUNCTION(ASSERTDEF VARNAME)
>     IF(NOT DEFINED ${VARNAME})
>       MESSAGE(SEND_ERROR "Error, the variable ${VARNAME} is
> not defined!")
>     ENDIF()
>     RETURN(${VARNAME})
>   ENDFUNCTION()
>
> You could then use this function like:
>
>    IF (${ASSERTDEF(MYVARIABLE)$)
>      ...
>    ENDIF()
>
> Then, if I misspelled the variable name as:
>
>    IF (${ASSERTDEF(MYVARABLE)}$)
>      ...
>    ENDIF()
>
> I would get an error message and processing would stop immediately.
>
> Above, I assume that the syntax:
>
>    ${SOMEFUNCTION(ARGS)}
>
> Is needed to get CMake to expect a return value from the
> function and then return it, just like it would return a
> variables value.
>
> How hard would it be to all return values from CMake
> functions in this way?
>
> Thanks,
>
> - Ross
>
>
>
>
>



More information about the CMake mailing list