CMake: Как установить выражение генератора на основе опции (и конфигурации компилятора / сборки) - PullRequest
0 голосов
/ 20 мая 2018

У меня работает следующее выражение генератора, которое устанавливает флаг /GS, если компилятор MSVC, и устанавливает его для конфигураций сборки RelWithDebInfo и Release:

target_compile_options(mytarget PRIVATE "$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>")

Теперь я также хочу позволить пользователю настроить это, и я добавил option: option(MYTARGET_ENABLE_GS "Enable /GS" OFF)

Итак, теперь я (очевидно) хочу включить /GSфлаг если пользователь включил эту опцию, и если они это сделали, я хочу добавить ее если компилятор MSVC, и он должен быть добавлен к Release и RelWithDebInfoконфигурации.

Это довольно много, и я не могу понять, как это правильно.Это насколько я получил:

target_compile_options(mytarget PRIVATE "$<$<BOOL:MYTARGET_ENABLE_GS>:$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>>") Редактировать: Исправлено, см. Ниже.

Мне пришлось использовать $<$<BOOL:...>>, потому что это "переводит"option (который может быть вкл / выкл или true / false, до 0 или 1, в котором нуждается выражение генератора. Однако вышеприведенная строка не работает: она не добавляет (или не добавляет)/GS.

Я хотел бы знать:

1) Где моя ошибка?Как это сделать?И

2) Подобные вещи приводят к довольно запутанным вложенным выражениям, которые действительно трудно читать - представьте, что через 6 месяцев снова читаете эту строку кода, даже если это задокументировано.И это так просто - потерять > или что-то в этом роде.Я мог бы, вероятно, использовать «ручной» if s, чтобы сделать это более читабельным, но представьте, что у вас есть 5-10 таких опций - запись if / end с target_compile_options внутри приводит к 15-30 строкамif / end код, на который тоже не очень приятно смотреть.Какой лучший способ сделать это?

Редактировать: Я был почти там.Переменные должны быть заключены в ${...} в выражениях генератора.Так, например: target_compile_options(mytarget PRIVATE "$<$<BOOL:${MYTARGET_ENABLE_GS}>:$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>>"), и это прекрасно работает.

Что все еще оставляет пункт "2)", о котором я бы хотел узнать.

Ответы [ 2 ]

0 голосов
/ 20 мая 2018

Всякий раз, когда вы можете использовать команду if, используйте ее.Выражения генератора - , а не замена для команды if.

Выражения генератора позволяют использовать условия, зависящие от тип сборки .Поскольку в системах с несколькими конфигурациями, таких как Visual Studio, тип сборки неизвестен на этапе настройки, вы не можете использовать это условие в команде if.

Но выражения генератора некрасиво , поэтому не используйте их, когда они не нужны.

В

if(MYTARGET_ENABLE_GS)
    target_compile_options(mytarget PRIVATE "$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>")
endif()

нет ничего плохого. Если вы хотите проверить опцию в начале, но создать цель позже, выможет сохранить выражение генератора в переменной и использовать эту переменную позже:

set(additional_options)

# Depending on parameters, add options to 'additional_options' list.
if(MYTARGET_ENABLE_GS)
    list(APPEND additional_options "$<$<CONFIG:Release>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>$<$<CONFIG:RelWithDebInfo>:$<$<CXX_COMPILER_ID:MSVC>:/GS>>")
endif()

if(<other option>)
   list(APPEND additional_options <...>)
endif()
# ...
target_compile_options(mytarget PRIVATE ${additional_options})
0 голосов
/ 20 мая 2018

Когда вы генерируете решение MSVC, тип сборки (Release, Debug и т. Д.) Неизвестен до тех пор, пока вы фактически не запустите сборку.Таким образом, если использовать выражение генератора для этого корректно.

Но для 2 других переменных (устанавливает ли пользователь MYTARGET_ENABLE_GS в положение OFF и выполняется ли генерация для MSVC), они разрешаются во время конфигурации.Таким образом, вам не нужно проверять их в выражении генератора.Вы можете просто написать:

if(MSVC AND MYTARGET_ENABLE_GS)
    target_compile_options(mytarget PRIVATE "$<$<OR:$<CONFIG:Release>, $<CONFIG:RelWithDebInfo>>:/GS>")
endif()

Это решение также использует выражение генератора $<OR:?[,?]...> для перегруппировки под тем же выражением в обоих случаях, которые вы строите в Release OR RelWithDebInfo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...