The name "cmake_command" is overloaded

You are right but even in this situation it will be possible to distinguish variable from command by the difference in syntax: command has form <name> '(' [ args ] ')' and variable is just <name> or '${' <name> '}'.

For example, if hypothetically commands can return a value we will have:

set (item "data")
function (item)
...
return ("data")  # tentative syntax :)
endfunction()

`if (item() AND item)
  ...
endif()

Part of my point is that we don’t actually have to place this restriction on ourselves. If we can find an equally suitable name for the command, we haven’t reduced our future options. I’m mindful that this feature has been there for a little while on master now, but not in the last release. It isn’t too late to consider a different name if we wanted to (cmake_code() anyone?).

I missed the whole development and review of this feature due to other commitments, so I’m only just catching up now. I understand if people consider it too late to revisit.

I don’t think it is too late but cmake_code is a bit disappointing in the following form cmake_code(EVAL CODE ...). One can wonder why to re-specify CODE?

Just $0.02 from an ordinary user, but how about cmake_exec? exec and eval are both terms commonly used for such “dynamic code” functionality.

Just to fuel the discussion: cmake_call()? Dunno if I like it myself though.

I’d like to stick with cmake_command(). It is the clearest of the proposed names for its role. I think that is more important than the tiny risk of future conflicts with the CMAKE_COMMAND variable.

1 Like

Ok. Would the name duplication be a problem for any syntax highlighting scenarios? Maybe we should update the vim syntax highlighter as some sort of verification?

Except in arguments to invocations of cmake_command() itself, the command name is always followed by ( and the variable name is not.

CMake’s command parser and variable parsers are two completely separate things. The first is an unnecessarily complicated lax/yacc generated thing that does balanced parentheses, comment, and quote/square brackets computations to find the last parenthesis. This returns a command name and a string to split into arguments cmMakefile::ExpandVariableInString then takes the argument list and expands arguments where some other routine then picks up and splits it into actual arguments (with quoting information). This proposed syntax would need to merge these somehow which seems…unlikely. Given CMake’s wonky argument semantics, is this allowed?

function (thought_experiment)
  return (somevar STREQUAL)
endfunction ()

if (though_experiment() "a string")
  message("hmm")
else ()
  message(
    "functions can't return lists? "
    "returned lists are not expanded at their use site? "
    "what is the exception here? "
    "is this just another `if` special case? why?")
endif ()

So I think any such real-world collision has far more problems than the name collision to consider. The syntax parser would hopefully have which is which be 100% unambiguous anyways (if is a bit special here, but any other variable naming occurs within a $key{ style expansion, so that should be unambiguous. You probably lose on ${thought_experiment()}, but even that may be an acceptable future since () are invalid characters in literal variable names today anyways:

set("thought_experiment()" value)
set(varname "thought_experiment()")
set(expanded "${varname}") # expands to "value"

But explaining the difference between the above and ${though_experiment()} is going to be tricky, so probably not the best idea.

In addition if cares about the quoting used in the argument list. With list expansion, you probably can only get unquoted arguments, so there’s no way to use this mechanism to make the "a string" part of the example without looking up the a string variable.

Not quite:

if(COMMAND CMAKE_COMMAND)
if(DEFINED CMAKE_COMMAND)

My experiences with my book and the CMake syntax highlighting coming from things like pygments, rouge, code ray, etc. has taught me that highlighters sometimes try to highlight all the way into command arguments, with varying degrees of success. I am not super familiar with their parsing rules, but the above is one example for which I’m wondering how they would go. The context makes it clear what type of name is expected, but I don’t know if the highlighters are that smart.

Or another example (does this even work?):

cmake_command(INVOKE cmake_command message hello)

And that last comment of mine nicely demonstrates what I mean: the CMake highlighting of my code example has indeed reached into the command arguments and identified message as a command. Let me try another one:

cmake_command(INVOKE CMAKE_COMMAND MESSAGE hello)

When the highlighter for this forum is updated to learn about the cmake_command() command, what should it do with CMAKE_COMMAND? Treat it as a variable or as a command?

I think these are fine. The first only takes names of commands and the second only takes names of variables. Given a variable named /usr, is this also ambiguous?

if (EXISTS "/usr")
if (IS_ABSOLUTE "/usr")
if (DEFINED "/usr")

The former 2 take paths, the last is a variable name. If syntax highlighters want to try and interpret CMake argument lists as the corresponding command actually does, I wish them the best of luck.

I’d say variable is safer since ScreamMake is “over” is the better option, but it is fundamentally undecidable without the syntax highlighter knowing what cmake_command does (other than that it is a token on the left side of a top-level ( character). Highlighters for CMake are always going to be disadvantaged. I get keywords to ExternalProject_add highlighted as “keywords” no matter what function they’re used in making some functions look pretty odd if they share some keywords with other CMake APIs.

For highlighting, I’ve learned to live with the mistakes and corner cases you get, but I’m also much more familiar with EVIS than most to know that emulating CMake parsing is…hard.

cmake_command() operates on cmake commands. The name is consistent with the terminology used in the cmake-language(7) manual. I don’t think any other command name will be as clear. We should not sacrifice that clarity just because the CMAKE_COMMAND variable exists already. I don’t think it will cause confusion in practice.

I’m not concerned about syntax highlighting of raw mentions of CMAKE_COMMAND. Syntax highlighting of variables outside ${} is ad-hoc anyway.

Actually, my line of thinking here has only been in the context of cmake_command(INVOKE ...) which was originally the only signature. The cmake_command(EVAL CODE ...) signature does not operate just on cmake commands but also on arbitrary cmake language code.

How about the name cmake_lang()?

  • cmake_lang(CALL <command> <args>...)
  • cmake_lang(EVAL CODE <code>...)

Ok for me but why would you want to truncate language? no other CMake command use truncation. So I prefer cmake_language().

cmake_language is fine too:

  • cmake_language(CALL <command> <args>...)
  • cmake_language(EVAL CODE <code>...)
1 Like

I quite like those two, including the change from INVOKE to CALL.

Thanks folks. I’ve opened CMake Issue 20732 to track this rename.