CMake is not a programming language, so I’m somewhat wary of efforts to build advanced high-level features into the language itself. At the risk of sounding dismissive, I’ll note that beyond assertions of “a lot of pain and limitations” caused by the lack of an arbitrary key-value datatype, nobody’s really provided even a single concrete example of why it’s needed. Desired, sure, but not unavoidably necessary.
(The blog post linked above — which also fails to demonstrate the actual need for a dict type — is even more dismissive:
Perhaps this might change in the future, and we’ll get a real honest to god dictionary type, but don’t hold your breath. I’d rather see the CMake language go away entirely than get a dictionary type.
So I don’t feel so bad, I guess is what I’m saying.)
Besides, for non-arbitrary key-value pairings, CMake’s existing list and string variables already serve. This sort of pattern is used all the time in Find modules:
foreach(name record1 record2 record3 record4)
foreach(k key1 key2 key3 key4)
set(_${name}_${k} <something to determine ${k} value for ${name}>)
endforeach()
endforeach()
Yes, the list of keys has to be predefined, you can’t easily have each record contain different keys, or arbitrary keys that are only determined at runtime. (Though any of the _${name}_${k}
variables can certainly be empty, if that key isn’t needed for a particular ${name}
.)
Can key-value pairs be passed between CMake contexts easily? No. Can they be passed with a little work? Most likely yes, using target PROPERTIES
(which can, recall, be arbitrary). There’s nothing to stop you from later doing this:
foreach (name ...)
add_custom_target(${name})
foreach (k ...)
set_target_properties(${name} PROPERTIES ${k} "${_${name}_${k}}")
endforeach()
endforeach()
Then, as the set_target_properties()
documentation notes, “You can use any prop value pair you want and extract it later with the get_property()
or get_target_property()
command.”
So, if you were to include the above code in a “dict.cmake” file, and then later in your CMakeLists.txt
you were to call:
set(CMAKE_MODULE_PATH ".")
include(dict)
include(CMakePrintHelpers)
cmake_print_properties(TARGETS record1 record2 PROPERTIES key1 key2)
Well, I just tried it, so I can tell you. Using this as my modified “dict creation” loop:
foreach(name record1 record2 record3 record4)
foreach(n 1 2 3 4)
set("_${name}_key${n}" "${name}.value${n}")
endforeach()
endforeach()
I get this:
$ cmake .
--
Properties for TARGET record1:
record1.key1 = "record1.value1"
record1.key2 = "record1.value2"
Properties for TARGET record2:
record2.key1 = "record2.value1"
record2.key2 = "record2.value2"
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp
Effectively, each target is a dict of its properties.