Ternary operator in CMake's generator expressions
Solution 1
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
Solution 2
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;
Daniel Wolf
I'm a software developer in Munich, Germany. Professionally, I mostly do front-end development in TypeScript. In my spare time, I work on a tool for automatic lip-sync for computer games.
Updated on June 05, 2022Comments
-
Daniel Wolf almost 2 years
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 sayadd_compile_options($<$<CONFIG:Debug>:/MTd>)
If
CONFIG
equals "Debug", this will calladd_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.
-
Florian over 8 yearsI don't think it's currently possible (as for CMake version 3.4.1), but there is already a feature request 0015585: Add support for the if / else construct to generator expressions you could support.
-
Antonio over 8 yearsFor the moment being you could define a macro, and in fact limit your call to
your_macro(Debug,/MTd,/MT)
-
thiagowfx over 7 yearsI provided a macro definition in my answer.
-
Florian about 7 yearsThe
$<IF>
operator was just added with this commit.
-
-
Florian over 7 yearsJust a hint: I think neither the first (dereferencing the variable's content) nor the second definition (
if
checking the variables content) would work, ifboolean
contains a generator expression. -
silvioprog about 6 years@Florian you are right. I've tried to fix it, however, no success. But IMHO it would be nice to have some CMake ternary module or at least an
IIF()
-style function. -
Daniel Wolf almost 5 yearsNice find! It's documented here: cmake.org/cmake/help/v3.8/manual/…
-
vulcan raven about 4 yearsThanks, but documentation does not give a single example for
$<IF..
construct which was the reason of my confusion. -
Lance E.T. Compte about 4 years@vulcanraven Indeed the cmake documentation is very short on helpful examples. Does the example that Dawid Drozd added help you enough?
-
vulcan raven about 4 years@LanceE.T.Compte, wasn't looking just for an example :) I saw a code somewhere of the form
$<IF: $<cond>, trueValue>
, without needing to specify false. I was searching for documentation on$<IF
construct and couldn't find one. To me,$<IF
sounds like a very fundamental thing to have as part of documentation in any platform. -
Lance E.T. Compte about 4 years@vulcanraven $<IF ...> is documented here: cmake.org/cmake/help/latest/manual/… Omitting the falseValue would substitute an empty string. I actually do that when adding debug flags, etc.
-
vulcan raven about 4 yearsExactly what I was trying to find. Thanks a lot! :)