Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary operator in CMake's generator expressions

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.

like image 887
Daniel Wolf Avatar asked Dec 21 '15 10:12

Daniel Wolf


2 Answers

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

like image 128
Lance E.T. Compte Avatar answered Sep 17 '22 11:09

Lance E.T. Compte


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}     ) 

TL;DR

ternary(var boolean value1 value2)

means, comparing to C/C++:

int var = boolean ? value1 : value2;

like image 25
thiagowfx Avatar answered Sep 17 '22 11:09

thiagowfx