Cmake's generator expressions allow me to use logical expressions within certain function calls. For instance, if I want to add the /MTd compiler flag in Debug mode, I can say
add_compile_options($<$<CONFIG:Debug>:/MTd>) If CONFIG equals "Debug", this will call add_compile_options with the value "/MTd", otherwise with an empty string.
But usually, I don't want to decide between a value and the empty string, but between two values. In the example above, if CONFIG is not "Debug", I want to pass /MT (without the trailing d). I'd love to have a syntax like this:
add_compile_options($<$<CONFIG:Debug>:/MTd:/MT>) Note that the above is not valid code according to the CMake specs. The best I have come up with that actually works is this:
add_compile_options($<$<CONFIG:Debug>:/MTd>$<$<NOT:$<CONFIG:Debug>>:/MT>) This seems awfully redundant to me. Is there a shorter, more readable way to decide between two values?
Note: I realize that in this special case, I could write this:
add_compile_options(/MT$<$<CONFIG:Debug>:d>) But this seems rather hacky to me and only works in those cases where one option is a substring of the other.
Note that cmake 3.8 added exactly what you want to generator expressions ...
$<IF:?,true-value...,false-value...> true-value... if ? is 1, false-value... if ? is 0 Example usage:
target_link_libraries(MyLib PUBLIC $<IF:$<CONFIG:Debug>,cppzmq,cppzmq-static> ) Where cppzmq is shared library used in Debug build and cppzmq-static is static library used in other case e.g. Release
Here's a working example, with a macro:
cmake_minimum_required(VERSION 2.8.12) macro(ternary var boolean value1 value2) set(${var} $<${${boolean}}:${value1}>$<$<NOT:${${boolean}}>:${value2}>) endmacro() set(mybool 0) ternary(myvar mybool hello world) add_custom_target(print ${CMAKE_COMMAND} -E echo ${myvar} ) Create a CMakeLists.txt file and run cmake . && make print (generator expressions are only evaluated at build time).
Try changing the value of mybool to 0 or 1 and see what happens.
The following definition also works, and it is clearer:
cmake_minimum_required(VERSION 2.8.12) macro(ternary var boolean value1 value2) if(${boolean}) set(${var} ${value1}) else() set(${var} ${value2}) endif() endmacro() set(mybool 0) ternary(myvar mybool hello world) add_custom_target(print ${CMAKE_COMMAND} -E echo ${myvar} ) ternary(var boolean value1 value2)
means, comparing to C/C++:
int var = boolean ? value1 : value2;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With