Ответ 1
Обратите внимание, что cmake 3.8 добавил именно то, что вы хотите, чтобы генератор выражений...
$<IF:?,true-value...,false-value...>
true-value... if ? is 1, false-value... if ? is 0
Cmake выражения генератора позволяют мне использовать логические выражения в определенных вызовах функций. Например, если я хочу добавить флаг /MTd
компилятора в режиме отладки, могу сказать
add_compile_options($<$<CONFIG:Debug>:/MTd>)
Если CONFIG
равно "Debug", это вызовет add_compile_options
со значением "/MTd", в противном случае с пустой строкой.
Но обычно я не хочу выбирать между значением и пустой строкой, но между двумя значениями. В приведенном выше примере, если CONFIG
не является "Debug", я хочу передать /MT
(без конечного d). Мне бы хотелось иметь такой синтаксис:
add_compile_options($<$<CONFIG:Debug>:/MTd:/MT>)
Обратите внимание, что приведенный выше недействительный код соответствует спецификациям CMake. Самое лучшее, что я придумал, это на самом деле:
add_compile_options($<$<CONFIG:Debug>:/MTd>$<$<NOT:$<CONFIG:Debug>>:/MT>)
Это кажется ужасно лишним для меня. Существует ли более короткий и понятный способ выбора между двумя значениями?
Примечание. Я понимаю, что в этом специальном случае я мог бы написать это:
add_compile_options(/MT$<$<CONFIG:Debug>:d>)
Но это кажется довольно хакированным для меня и работает только в тех случаях, когда один параметр является подстрокой другого.
Обратите внимание, что cmake 3.8 добавил именно то, что вы хотите, чтобы генератор выражений...
$<IF:?,true-value...,false-value...>
true-value... if ? is 1, false-value... if ? is 0
Вот рабочий пример с макросом:
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}
)
Создайте файл CMakeLists.txt
и запустите cmake . && make print
(выражения генератора оцениваются только во время сборки).
Попробуйте изменить значение mybool
на 0
или 1
и посмотреть, что произойдет.
Следующее определение также работает, и оно яснее:
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)
означает, по сравнению с C/С++:
int var = boolean ? value1 : value2;
Давайте сделаем это более явным:
add_custom_command(TARGET myProject PRE_BUILD
COMMAND cd \"D:/projects/$<IF:$<CONFIG:Debug>,Debug,Release>\"
COMMAND call prebuild.bat)
Затем в сгенерированном Visual Studio Project, в окне свойств проекта "myProject".
Если конфигурация сборки "Отладка", процесс оценки будет следующим:
$<IF:$<CONFIG:Debug>,Debug,Release>
$<IF:1,Debug,Release>
Debug
Если для конфигурации сборки выбрано "Release", процесс оценки будет следующим:
$<IF:$<CONFIG:Debug>,Debug,Release>
$<IF:0,Debug,Release>
Release