Not really. If your configuration flags depend on each other, CMakeDependentOption might be able to help wrangle them at “declaration” time at least (usually works better for AND chains though). But if it really is “any of these n things”, there’s not much available AFAIK.
Those config flags share the same prefix, for example CONFIG_TEST_XXX.
Can CMake support to check if any config flag with prefix CONFIG_TEST_ is ON?
If it can be implemented, perhaps it can help shorten the long if () statement.
No, CMake has no such metaprogramming facilities. Possibly this if you can stomach it:
set(options A B C)
set(conditional)
foreach (option IN LISTS options)
list(APPEND conditional "COMMON_PREFIX_${option}")
endforeach ()
# (ab)use the list representation
string(REPLACE ";" ";OR;" conditional "${conditional}")
if (${conditional})
# code that should work for any `option` being true
endif ()
@tbacarrot I have another suggestion/idea: Use a function + cmake_language(CALL) to handle the config variants and their implementation separately. Could look something like this:
function(my_config_variant)
# args
cmake_parse_arguments(_ARG "" "PREFIX;CALL" "WHEN;CALL_ARGS" ${ARGN})
if(_ARG_PREFIX)
string(REGEX REPLACE "[A-Za-z0-9_/.+-]+" "${_ARG_PREFIX}\\0" _ARG_WHEN "${_ARG_WHEN}")
endif()
# some regex magic to transform the WHEN argument to a valid if condition
string(REGEX REPLACE "\\(;" "(" _ARG_WHEN "${_ARG_WHEN}")
string(REGEX REPLACE ";\\)" ")" _ARG_WHEN "${_ARG_WHEN}")
string(REGEX REPLACE "!;?" "NOT;" _ARG_WHEN "${_ARG_WHEN}")
string(REPLACE "&&" "AND" _ARG_WHEN "${_ARG_WHEN}")
string(REPLACE "||" "OR" _ARG_WHEN "${_ARG_WHEN}")
# check condition and call implementing function/macro
if(${_ARG_WHEN})
cmake_language(CALL ${_ARG_CALL} ${_ARG_CALL_ARGS})
endif()
endfunction()
# config options
option(MY_CONF_A "" ON)
option(MY_CONF_B "" OFF)
option(MY_CONF_C "" ON)
# config variants implementation
function(my_conf_1_impl)
# my_conf_1 implementation ...
endfunction()
function(my_conf_2_impl)
# my_conf_2 implementation ...
endfunction()
# ...
# config variants
my_config_variant(
PREFIX MY_CONF_
WHEN A && B && C # -> false
CALL my_conf_1_impl
)
my_config_variant(
PREFIX MY_CONF_
WHEN (A && B) || C # -> true
CALL my_conf_2_impl
)
my_config_variant(
PREFIX MY_CONF_
WHEN A || C # -> true
CALL my_conf_3_impl
)
my_config_variant(
PREFIX MY_CONF_
WHEN !B # -> true
CALL my_conf_4_impl
)
Depending on your use case (how many/complex config variants you have) this may help to express your config variants in a more concise way than some mile-long if-elseif-else construct. Also you could bundle all the conditions for your variants in one place whereas with if statements you have to search for them at the beginning of every branch with all the implementation in between.
Though, for a small number of config variants I would stick with straightforward if statements.
CACHE_VARIABLES isn’t likely to be deprecated, but someone doing a misspelling of -DABC_SOME_WRONG_FLAG=ON will be caught up here. It is intended for debugging and using it for logic just has unintended consequences. I think an explicit list is just better.
You also shouldn’t assume that the variable will be a cache variable. Projects may set them as regular non-cache variables and that should work too (not saying that’s always a thing you want to support, but in general, code shouldn’t care whether a variable is set as cache or non-cache unless there is a very specific reason to differentiate between the two).