Я использую CMake v3.13.4 с генератором Visual Studio 2017 Win64, и мне нужно изменить параметры командной строки для библиотеки Visual Studio (для библиотеки объектов CMake).
Для этого CMake предлагает целевое свойство STATIC_LIBRARY_OPTIONS, которое можно установить с помощью команды set_property и set_target_properties.
В документации указано, что STATIC_LIBRARY_OPTIONS поддерживает выражения генератора:
Contents of
STATIC_LIBRARY_OPTIONSmay use “generator expressions” with the syntax$<...>. See the cmake-generator-expressions(7) manual for available expressions. See the cmake-buildsystem(7) manual for more on defining buildsystem properties.
Но: Что бы я ни пытался, значения не экранируются должным образом, например.
set_property(TARGET object_library PROPERTY STATIC_LIBRARY_OPTIONS $<$<CONFIG:Release>:/WX /NOLOGO /LTCG /ERRORREPORT:NONE>)
приводит к следующему в Visual Studio:
All Options: `/OUT:"..." /LTCG /MACHINE:X64 /NOLOGO
Additional Options: %(AdditionalOptions) /machine:x64 ""$"<1:/WX" "/ERRORREPORT:NONE>"
Я пробовал следующее, все они, похоже, терпят неудачу.
set_property(TARGET object_library PROPERTY
STATIC_LIBRARY_OPTIONS $<$<CONFIG:Release>:/WX /NOLOGO /LTCG /ERRORREPORT:NONE>
#STATIC_LIBRARY_OPTIONS "$<$<CONFIG:Release>:/WX /NOLOGO /LTCG /ERRORREPORT:NONE>"
#STATIC_LIBRARY_OPTIONS $<$<CONFIG:Release>:"/WX /NOLOGO /LTCG /ERRORREPORT:NONE">
#STATIC_LIBRARY_OPTIONS $<$<CONFIG:Release>:/WX /NOLOGO /LTCG /ERRORREPORT:NONE>
#STATIC_LIBRARY_OPTIONS $<$<CONFIG:Release>:/WX;/NOLOGO;/LTCG;/ERRORREPORT:NONE>
#STATIC_LIBRARY_OPTIONS $<$<CONFIG:Release>:"/WX;/NOLOGO;/LTCG;/ERRORREPORT:NONE">
#STATIC_LIBRARY_OPTIONS "$<$<CONFIG:Release>:/WX;/NOLOGO;/LTCG;/ERRORREPORT:NONE>"
)
Итак, мой вопрос: как я могу передать несколько значений с помощью выражений генератора в STATIC_LIBRARY_OPTIONS с помощью команды set_property или set_target_properties?





Благодаря @Tsyvarev я смог решить эту проблему. Решение состоит в том, чтобы преобразовать обернуть каждое значение в собственное выражение генератора:
set_property(TARGET object_library PROPERTY
STATIC_LIBRARY_OPTIONS
$<$<CXX_COMPILER_ID:MSVC>:/WX>
$<$<CXX_COMPILER_ID:MSVC>:/NOLOGO>
$<$<CXX_COMPILER_ID:MSVC>:/ERRORREPORT:NONE>
$<$<CXX_COMPILER_ID:MSVC>:$<$<CONFIG:Release>:/LTCG>>
)
Ниже вы найдете мой ответ, который, как мне помог понять @Tsyvarev, не помогает в ситуации вопроса. Пожалуйста, вместо этого рассмотрите его ответ. Поскольку я нашел его комментарии ниже полезными, я оставлю ответ здесь, чтобы вы могли прочитать комментарии.
Этот ответ предназначен для будущих читателей с более новым cmake: Как подробно описано в этот ответ от @firmament, в зависимости от версии cmake также может быть возможно поместить все значения в список через
set(my_option_list /WX /NOLOGO /LTCG /ERRORREPORT:NONE)
и передайте этот список в выражение генератора:
"<$<CONFIG:Release>:${my_option_list}>"
Это работает на cmake 3.18.4 с выражениями генератора clang и gcc.
Я протестировал этот подход. Ваше генераторное выражение в конфигурации Release внутренне производит "/WX;/NOLOGO;/LTCG;/ERRORREPORT:NONE". Для некоторых команд это эквивалентно списку этих опций: /WX /NOLOGO /LTCG /ERRORREPORT:NONE, так что все работает. Среди них команда add_compile_options от ваш вопрос. Но для некоторых других команд это не работает. Например. add_custom_target(my_target COMMAND echo "<$<CONFIG:Release>:${my_option_list}>" печатает точки с запятой между вариантами. (Вместо того, чтобы печатать их через пробел).
Спасибо, что дал мне знать! Я думаю, это делает недействительным мой ответ на этот вопрос. Каков наилучший план действий? Должен ли я удалить его? Видимо, это неправильный ответ на этот вопрос.
«По-видимому, это неправильный ответ на этот вопрос». - Почему вы так думаете? Вы отвечаете отвечает на текущий вопрос, он отвечает на ваш вопрос. На самом деле, это решает проблему add_custom_target, но с дополнительным ключевым словом COMMAND_EXPAND_LISTS: stackoverflow.com/a/65231456/3440745. Я только что объяснил некоторые... особенности вашего подхода. Кстати, я проголосовал за ваш ответ, а не против.
Я имел в виду, что использование только моего ответа не приводит к желаемому результату, и поэтому будущие читатели не получат от этого пользы. Я думаю, мне следует удалить его, чтобы не сбивать с толку людей, которым лучше использовать ваш ответ. Поскольку я плохо разбираюсь в SO, я подожду от вас комментария, будет ли это глупо или нет.
Также, может быть, текущее поведение следует зарегистрировать как ошибку? Меня, например, очень сбивает с толку то, как по-разному работают выражения генератора для разных команд. Но я не уверен в своих способностях и их отсутствии с помощью cmake, чтобы на самом деле подать его.
«почему выражения генератора работают так по-разному для разных команд». - Нет, генератор выражений самих себя работает точно так же. И ваше генераторное выражение всегда выдает "/WX;/NOLOGO;/LTCG;/ERRORREPORT:NONE". Но такой строка, разделенная точкой с запятой обрабатывается разными командами по-разному. Кажется, что многие команды (которые поддерживают выражения генератора) обрабатывают эту строку как список, и это желаемое поведение. Команда add_custom_target относится к этому по-разному... но есть способ официальный для изменения этого поведения. Я не вижу в этом проблемы.
Я думаю, что ваши комментарии могут быть полезны, поэтому я не буду удалять свой ответ, чтобы они остались. Я обновлю его, чтобы направить всех к вашему ответу.
Предполагая, что у вас есть список вариантов:
set(option_list /WX /NOLOGO /LTCG /ERRORREPORT:NONE)
вы можете создать для них список генераторных выражений одной командой:
list(TRANSFORM option_list
REPLACE ".+" "$<$<CXX_COMPILER_ID:MSVC>:\\0>"
OUTPUT_VARIABLE option_list_msvc
)
Полученный список можно использовать напрямую:
set_property(TARGET object_library PROPERTY STATIC_LIBRARY_OPTIONS ${option_list_msvc})
Поток команд список(ПРЕОБРАЗОВАНИЕ) доступен, начиная с CMake 3.12.
«Как я могу передать несколько значений, используя выражения генератора?» - Оберните каждое значение в собственное выражение генератора:
$<$<CONFIG:Release>:/WX> $<$<CONFIG:Release>:/NOLOGO> ....