Datatypes¶
There Are No Datatypes, Basta¶
Everything is a string
Can be interpreted as numeric, boolean, path, … (see if, And Conditions for full ranting)
My impressions is: although other languages are not typed either, no language does a job as bad as CMake’s (even the good ol’ shell is somewhat cool)
Not all is as hard as
if
booleans though“Methods” provided for strings that are interpreted as
Strings
Lists
Regular expressions
…
Complication: where methods in other languages have return values (such as a str.substring(0,5)), CMake sets output variables (there is no return value in the language)
Rule: variable names are passed to method unquoted
string(APPEND variable "value")
Attention: Inconsistencies All Over¶
What follows is a relatively random list of “methods” on strings and lists. Please read the documentation to get an impression of what is available.
CMake is not very consistent! Be sure to test your code, if possible, using standalone scripts before you integrate it into a project build!
The string(FIND...)
method, for example, requires us to pass the
string content - not the variable name - for it to work.
set(some_variable "Mississippi")
string(FIND "${some_variable}" "ss" position_found)
On the contrary, the list(LENGTH...)
method wants me to pass the
variable name that contains the list.
set(some_variable "a" "b" "c")
list(LENGTH some_variable length)
Strings¶
Many methods for string modification ⟶ variable passed unquoted (c/f “per-reference”)
Many methods for string examination ⟶ variable passed quoted (c/f “per-copy”)
Strings: In-Place Modification Of A Variable (Use Unquoted Names)¶
Variable is passed for modification
⟶ per-reference
⟶ unquoted
set(some_string "Hello")
string(APPEND some_string " ")
string(APPEND some_string "String")
message("${some_string}")
$ cmake -P string-inplace-simple.cmake
Hello String
Pitfall: In-Place Modification Of Undefined Variable¶
Appending to an undefined variable creates that variable
string(APPEND some_string "Hello")
message("${some_string}")
$ cmake -P string-append-undefined.cmake
Hello
Attention
This is not only true for string operations, but is a pattern across the language!
Pitfall: Quoted Variable Names For In-Place Modification¶
Passing a variable in quotes ("${some_variable}"
) is rarely what’s
wanted
Evaluates
"${some_variable}"
Operates on that variable
⟶ undefined, mostly
set(some_string "Hello")
string(APPEND ${some_string} " ")
string(APPEND ${some_string} "String")
message("Variable 'some_string': >${some_string}<")
message("Variable 'Hello' created: >${Hello}<")
$ cmake -P string-pitfall-quote-varname.cmake
Variable 'some_string': >Hello<
Variable 'Hello' created: > String<
Strings: Non-Modifying Operations (Use Quoted Names)¶
Non-modifying methods work best on copies of variables
⟶ quoting/evaluation
Note how the to-be-created output variable is passwd
set(some_string "Mississippi")
string(FIND "${some_string}" "ss" position_found)
message("${position_found}")
$ cmake -P string-substring.cmake
2
Pitfall: Unquoted Variable Names For Non-Modifying Operations¶
set(some_string "Mississippi")
string(FIND some_string "ss" position_found)
message("${position_found}")
$ cmake -P string-substring-unquoted.cmake
-1
Strings: Methods, By Example¶
Find a substring (returns position)
set(some_string "Mississippi") string(FIND "${some_string}" "ss" position_found) message("${position_found}")
$ cmake -P string-substring.cmake 2
set(some_string "Mississippi") string(FIND "${some_string}" "ss" position_found REVERSE) message("${position_found}")
$ cmake -P string-substring-reverse.cmake 5
Joining a number of strings
string(JOIN " " joined_string "Hello" "World") message("${joined_string}")
$ cmake -P string-join.cmake Hello World
Comparing strings (and storing a boolean value for later use)
set(lhs "Faschingbauer") set(rhs "Zeilinger") string(COMPARE LESS "${lhs}" "${rhs}" is_less) if (is_less) message("${lhs} < ${rhs}") endif()
$ cmake -P string-compare.cmake Faschingbauer < Zeilinger
Lists¶
A list is a string where the list items are separated with semicolons (
";"
)Created using
set()
…set(some_list "a" "b" "c") message("${some_list}")
$ cmake -P list-create-with-set.cmake a;b;c
… or with any of the modifying list commands
list(APPEND some_list "a" "b" "c") message("${some_list}")
$ cmake -P list-create-with-append.cmake a;b;c
Various commands (
message()
) take lists, implicitly. Best by example.set(some_list "a" "b") message("some_list as string: >${some_list}<") message("some_list as string: >" ${some_list} "<") set(some_string "a b") message("some_string, interpolated: >${some_list}<") message("some_string, unquoted: >" ${some_list} "<")
$ cmake -P list-message.cmake some_list as string: >a;b< some_list as string: >ab< some_string, interpolated: >a;b< some_string, unquoted: >ab<
Lists: Iteration (foreach
Loop)¶
foreach()
operates on elements, not on lists (see foreach Loops)Separators can either be spaces (
" "
) or semicolons (";"
)⟶ Unquoted string reference (clearly 🐷)
list(APPEND some_list "a" "b" "c")
foreach (loop_var ${some_list})
message("${loop_var}")
endforeach()
$ cmake -P list-iterate.cmake
a
b
c
Lists: Methods, By Example¶
Appending elements to a list
set(some_list "a" "b") list(APPEND some_list "c" "d") message("${some_list}")
$ cmake -P list-append.cmake a;b;c;d
Length of a list
set(some_list "a" "b") list(LENGTH some_list some_length) message("${some_length}") list(LENGTH "${some_list}" some_length) message("${some_length}")
$ cmake -P list-length.cmake 2 0
Remove element at position
set(some_list "a" "b" "c" "d") list(REMOVE_AT some_list 2) message("${some_list}")
$ cmake -P list-remove-at.cmake a;b;d