Language Conventions
While you can always check the CMakePPLang documentation for how to use a function, CMakePPLang strives to also make it as easy as possible to “guess” how to use functions. Key to this effort is understanding the various conventions underlying how CMakePPLang decides on APIs. This chapter goes into more details regarding CMakePPLang conventions.
Note
CMakePPLang strives to have no exceptions to these conventions. If an exception exists (and it is not documented why it is an exception) assume it is a bug and please file an issue on GitHub.
Namespaces
Both CMake and CMakePP have a concept of variable scope, but neither have a
namespace concept. The most straightforward way to introduce namespaces is to
mangle a prefix onto function and variable names. CMakePPLang uses the prefix
cpp_
for all commands that are part of the public API. This helps avoid
conflicts with existing CMake commands, commands from other modules, and
commands users may write. Similarly, CMakePPLang uses the prefix
_cpp_
for “protected” commands and __cpp_
for private commands. Note
that commands in native CMake (as well as CMakePPLang) are case-insensitive
meaning CPP_
(on a command) is still the same namespace as cpp_
.
In CMake, variables are case-sensitive. Native CMake tends to prefix their
configuration variables with CMAKE_
. CMakePPLang follows suit
with prefixes CMAKEPP_LANG_
and __CMAKEPP_LANG
respectively for public
and private configuration variables (_CMAKEPP_LANG
will be used if there
is ever need for a protected variable).
Function Argument Order
The signatures of functions found in CMakePPLang all follow the same conventions when it comes to argument orders. For a non-member CMakePP function taking \(m\) arguments and returning \(n\) values (\(n\le m\)), the first \(n\) arguments will be the \(n\) values returned by the function and the remaining \(m-n\) values will be the inputs. Neither CMake or CMakePPLang make any attempt to distinguish the value of \(n\) in the signature and the only way to know if a value is input or output is to consult the documentation (or read the source code).
Note
Native CMake uses a mix of return positions. For example, the list()
and
string()
commands tend to have the variable holding the result as the
last argument. Note that for the various string hashing operations (e.g.
string(MD5 ...)
the variable for the return actually comes before the
string to hash. Other functions, such as get_filename_component
also put
the return variable before the input arguments.
For all intents and purposes we can think of CMake’s native list()
and
string()
commands as defining APIs for calling member functions of list
and string
instances respectively. Within this view, a call like
list(LENGTH <list_instance> <return_variable>)
is calling the member
function named LENGTH
of the provided list
instance and returning the
result in the provided variable. CMakePPLang generalizes this convention to
additional types, including user-defined classes.
For member functions associated with a type T
, CMakePPLang convention
is to access the members via a function named T
whose first argument is the
name of the member function and whose second argument is the instance the
member is being called on (e.g., the this
instance in C++ or the self
instance in Python). Arguments following the object instance obey the same
ordering conventions as non-member functions (returns followed by input).