Включает ли set_target_properties в CMake переопределение CMAKE_CXX_FLAGS?
В начале моего проекта CMake я устанавливаю общие флаги компиляции в переменной CMAKE_CXX_FLAGS, например
set(CMAKE_CXX_FLAGS "-W -Wall ${CMAKE_CXX_FLAGS}")
Впоследствии мне нужно добавить дополнительные флаговые компиляции для конфигурации (хранящиеся в BUILD_FLAGS). Могу ли я использовать для этого следующую команду:
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${BUILD_FLAGS})
или мне нужно добавить CMAKE_CXX_FLAGS вручную:
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BUILD_FLAGS}")
чтобы предотвратить перезапуск CMAKE_CXX_FLAGS с помощью BUILD_FLAGS?
Ответы
Ответ 1
Использовать первую:
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS ${BUILD_FLAGS})
Флаги, хранящиеся в BUILD_FLAGS, добавляются после CMAKE_CXX_FLAGS при компиляции источников TARGET. Документация подсказывает это, но я просто попробовал это сделать.
COMPILE_FLAGS
Additional flags to use when compiling this target sources.
The COMPILE_FLAGS property sets additional compiler flags used to
build sources within the target. Use COMPILE_DEFINITIONS to
pass additional preprocessor definitions.
Полная командная строка будет эквивалентна:
${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS} -o foo.o -c foo.cc
И как сказал Рамон, вы всегда можете проверить с помощью make VERBOSE=1
.
Ответ 2
Принятый ответ все еще работает, но устарел с 2013 года.
Этот ответ основан и на новых функциях из CMake v2.8.12, v3.3 и v3.13.
Начиная с CMake-2.8.12 (2013)
Две новые команды для установки CMAKE_CXX_FLAGS
:
Документация последней версии не сильно изменилась со времени cmake-2.8.12:
В вашем случае вы можете использовать:
target_compile_options(${TARGET} PRIVATE ${BUILD_FLAGS})
Или просто, если у вас есть одна цель:
add_compile_options(${BUILD_FLAGS})
Больше примеров
target_compile_options(mylib PRIVATE -O2) # only internal
target_compile_options(mylib INTERFACE -gl) # only external
target_compile_options(mylib PUBLIC -g) # same as PRIVATE + INTERFACE
# multiple targets and flags
target_compile_options(mylib1 mylib2 PRIVATE -Wall -Wextra)
target_compile_options( mylib PUBLIC -DUSEXX) # Bad
target_compile_definitions(mylib PUBLIC -DUSEXX) # OK
add_compile_options(-Wall -Wextra) # for all targets in current directory
add_compile_options(-DUSEXX) # Bad
add_definitions(-DUSEXX) # OK
Устаревшие COMPILE_FLAGS
Документация по cmake-3.0 помечает COMPILE_FLAGS
как устаревшую:
COMPILE_FLAGS
Дополнительные флаги, которые нужно использовать при компиляции этих источников.
Свойство COMPILE_FLAGS
устанавливает дополнительные флаги компилятора, используемые для создания источников внутри цели. Используйте COMPILE_DEFINITIONS
чтобы передать дополнительные определения препроцессора.
Это свойство устарело. COMPILE_OPTIONS
свойство COMPILE_OPTIONS
или команду target_compile_options
.
Если вы все еще хотите использовать set_target_properties()
вы можете использовать COMPILE_OPTIONS
вместо COMPILE_FLAGS
:
set_target_properties(${TARGET} PROPERTIES COMPILE_OPTIONS ${BUILD_FLAGS})
Начиная с CMake-3.3 (2015)
Антон Петров предлагает использовать генераторные выражения, представленные в ответе ar31.
Выражения генератора CMake применяют ваш ${BUILD_FLAGS}
к:
- C++ язык с использованием
$<COMPILE_LANGUAGE:CXX>
(также может быть C
, CUDA
...) - Clang-компилятор с использованием
$<CXX_COMPILER_ID:Clang>
(также может быть GNU
для gcc
или MSVC
для Visual C++... см. полный список)
(вместо этого используйте $<C_COMPILER_ID:Clang>
если язык - C) - и многое другое как поддерживаемая функция C++ или версия компилятора... (см. документацию)
В вашем случае вы можете использовать:
target_compile_options(${TARGET} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:${BUILD_FLAGS_FOR_CXX}>
$<$<COMPILE_LANGUAGE:C>:${BUILD_FLAGS_FOR_C}>)
или о компиляторах:
target_compile_options(${TARGET} PRIVATE
$<$<CXX_COMPILER_ID:Clang>:${BUILD_FLAGS_FOR_CLANG}>
$<$<CXX_COMPILER_ID:GNU>:${BUILD_FLAGS_FOR_GCC}>
$<$<CXX_COMPILER_ID:MSVC>:${BUILD_FLAGS_FOR_VISUAL}>)
Начиная с CMake-3.13 (2018)
Новая функция target_link_options()
позволяет передавать параметры компоновщику, как упомянул Крейг Скотт.
Различные параметры для файлов C и C++
Лучший способ - различать файлы C и C++, используя две разные цели.