Каков современный метод установки общих флагов компиляции в CMake?

86

CMake предлагает несколько механизмов для передачи флагов компилятору:

Есть ли один метод, который предпочтительнее другого в современном использовании? Если да, то почему? Кроме того, как этот метод можно использовать с несколькими системами конфигурации, такими как MSVC?

Питер Кларк
источник

Ответы:

97

Для современного CMake (версии 2.8.12 и выше) вы должны использовать target_compile_options, который внутренне использует целевые свойства.

CMAKE_<LANG>_FLAGS- это глобальная переменная, которая наиболее подвержена ошибкам в использовании. Он также не поддерживает выражения генератора , что может очень пригодиться.

add_compile_options основан на свойствах каталога, что в некоторых случаях нормально, но обычно не самый естественный способ указания параметров.

target_compile_optionsработает для каждой цели (путем установки свойств COMPILE_OPTIONSи INTERFACE_COMPILE_OPTIONStarget), что обычно приводит к наиболее чистому коду CMake, поскольку параметры компиляции для исходного файла определяются тем, к какому проекту принадлежит файл (а не в какой каталог он помещен. на жестком диске). Это имеет дополнительное преимущество, заключающееся в том, что он автоматически заботится о передаче опций зависимым целям, если они запрошены.

Несмотря на то, что они немного более подробны, команды для каждой цели позволяют достаточно детально контролировать различные параметры сборки и (по моему личному опыту) с наименьшей вероятностью вызовут головную боль в долгосрочной перспективе.

Теоретически вы также можете установить соответствующие свойства напрямую set_target_properties, но target_compile_optionsобычно это более читабельно.

Например, чтобы установить параметры компиляции цели fooна основе конфигурации с использованием выражений генератора, вы можете написать:

target_compile_options(foo PUBLIC "$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>")
target_compile_options(foo PUBLIC "$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")

В PUBLIC, PRIVATEи INTERFACEключевые слова определяют сферу вариантов . Например, если мы ссылаемся fooна barс target_link_libraries(bar foo):

  • PRIVATEпараметры будут применяться только к самой цели ( foo), а не к другим библиотекам (потребителям), связывающимся с ней.
  • INTERFACE параметры будут применяться только к целевой цели bar
  • PUBLICпараметры будут применены как к исходной цели, так fooи к целевой целиbar
ComicSansMS
источник
12
Обратите внимание, что target_compile_options добавьте параметры, чтобы вы могли изменить последнюю строку таким образом, чтобы сделать ее более читаемой)
2
@ComicSansMS Отличный ответ и лучшее (и самое последнее), что я мог найти в Интернете. Благодаря!
Ela782 05
1
@ user3667089 Целевые свойства обычно инициализируются переменной или свойством каталога. На странице руководства по соответствующему свойству указано, какое именно. В случае параметров компиляции это COMPILE_OPTIONSделает свойство каталога. Вы можете использовать add_compile_optionsкоманду, чтобы установить это. Вариантов, для которых это хороший подход, обычно немного.
ComicSansMS
6
@ComicSansMS Какая польза от PUBLICв target_compile_options?
Рамана Редди
1
@RamanaReddy Я добавил PUBLICк ответу дополнительное объяснение ключевого слова.
Стефан Профантер
0

Эти три способа служат для разных целей, поэтому ни один из них не предпочтительнее других. Это CMAKE_<LANG>_FLAGSпеременная, которую пользователь может определить для передачи флагов при вызове CMake для проекта. Два других используются в проекте. Один для установки флагов для конкретной цели, другой для всего каталога или выражения генератора.

Связанный вопрос: разница между add_compile_options и SET (CMAKE_CXX_FLAGS ...)

usr1234567
источник
1
Связанный вопрос не объясняет target_compile_optionsпуть. ИМХО target_compile_optionsследует предпочесть, поскольку он позволяет детально контролировать параметры и позволяет использовать выражения генератора. add_compile_optionsустанавливает флаги для всего каталога. Не могли бы вы подробнее рассказать об этом факте? Также есть различные сайты, где упоминается, что target_compile_optionsследует предпочесть.
Stefan Profanter