Изменение CMAKE_CXX_FLAGS в проекте

У меня есть следующий контент в моем CMakeLists.txt:

project( Matfile )

SET ( CMAKE_CXX_FLAGS "-std=c++0x" )

set ( SOURCES
      "foo.cpp"
      "bar.cpp"
    )

add_library(
        Matfile
        ${SOURCES}
)

Как вы можете себе представить, я хочу скомпилировать мои источники С++, используя флаг -std = С++ 0x (я использую gcc, и мне нужны функции С++ 11). К сожалению, это не работает в том смысле, что, когда я использую cmake для создания make файлов, переменная CMAKE_CXX_FLAGS полностью недействительна.

Как установить эту переменную в файле проекта?

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

Ответ 1

Наиболее простым решением должно быть использование add_compile_options(), если вы используете версию 2.8.12 или новее. Для более старых версий вы можете "злоупотреблять" add_definitions(). Хотя он предназначен только для флагов add -D, он также работает с любым другим флагом компилятора. Однако, я думаю, он не предназначен для использования таким образом и может сломаться в будущей версии.

add_compile_options(-std=c++0x) # CMake 2.8.12 or newer

или

add_definitions(-std=c++0x) # CMake 2.8.11 or older

Начиная с CMake 3.3 вы также можете сделать этот флаг применимым только к определенному языку (например, только C или С++), используя синтаксис выражений странных генераторов:

 add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-std=c++14> $<$<COMPILE_LANGUAGE:C>:-std=c99>)

Однако это будет не работать с генератором Visual Studio, поэтому обязательно используйте это для генераторов Make/Ninja или используйте target_compile_options(), чтобы установить его в целевой области.

Ответ 2

Помогает ли это использовать флаг FORCE?

SET ( CMAKE_CXX_FLAGS "-std=c++0x" CACHE STRING "compile flags" FORCE)

Ответ 3

Возможно, это будет работать лучше:

set_source_files_properties(${SOURCES}
       PROPERTIES
       COMPILE_FLAGS  "-std=c++0x")

Ответ 4

Правильный способ установки стандарта С++ в CMake >= 3.1.0:

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED on)

Ответ 5

В конкретном случае, требующем конкретного стандарта для компилятора, cmake 3.1 решает проблему, предоставляя способ запросить стандартную версию или набор функций компилятора. См. этот ответ и официальную документацию

Ответ 6

Чтобы развернуть бит в ADD_COMPILE_OPTIONS() с ответом на выражение генератора от ar31, вы можете столкнуться с проблемой, когда хотите добавить несколько флагов, разделенных пробелами, поскольку cmake имеет неприятная ошибка в выражениях генератора.

Решением, которое я использовал, был цикл FOREACH, вот пример из проекта, над которым я работаю:

IF(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    # common flags
    SET(MY_C_AND_CXX_FLAGS -mtune=generic -pipe -fPIC -Wformat -Wformat-security -fomit-frame-pointer -fstack-protector-strong --param ssp-buffer-size=4 -fexceptions -D_FORTIFY_SOURCE=2 -feliminate-unused-debug-types)

    SET(MY_C_FLAGS   ${MY_C_FLAGS}   ${MY_C_AND_CXX_FLAGS})
    SET(MY_CXX_FLAGS ${MY_CXX_FLAGS} ${MY_C_AND_CXX_FLAGS})

    IF(MINGW)
        SET(MY_C_FLAGS   ${MY_C_FLAGS}   -static-libgcc)
        SET(MY_CXX_FLAGS ${MY_CXX_FLAGS} -static-libgcc -static-libstdc++)
    ENDIF(MINGW)

    IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
        SET(MY_C_FLAGS   ${MY_C_FLAGS}   -g2 -Wall)
        SET(MY_CXX_FLAGS ${MY_CXX_FLAGS} -g2 -Wall)
    ELSE()
        SET(MY_C_FLAGS   ${MY_C_FLAGS}   -O2 -Wno-error)
        SET(MY_CXX_FLAGS ${MY_CXX_FLAGS} -O2 -Wno-error)
    ENDIF()

    FOREACH(C_COMPILE_FLAG ${MY_C_FLAGS})
        ADD_COMPILE_OPTIONS($<$<COMPILE_LANGUAGE:C>:${C_COMPILE_FLAG}>)
    ENDFOREACH()

    FOREACH(CXX_COMPILE_FLAG ${MY_CXX_FLAGS})
        ADD_COMPILE_OPTIONS($<$<COMPILE_LANGUAGE:CXX>:${CXX_COMPILE_FLAG}>)
    ENDFOREACH()

    # for the gcc -fstack-protector* flags we need libssp
    # clang does not have this
    IF(CMAKE_COMPILER_IS_GNUCXX)
        SET(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -lssp")
        SET(CMAKE_C_LINK_EXECUTABLE   "${CMAKE_C_LINK_EXECUTABLE}   -lssp")
    ENDIF()
ENDIF()

# Assembler flags

IF(ASM_ENABLED)
    FOREACH(ASM_FLAG -I${CMAKE_SOURCE_DIR}/src/filters/hq/asm/ -O1 -w-orphan-labels)
        ADD_COMPILE_OPTIONS($<$<COMPILE_LANGUAGE:ASM_NASM>:${ASM_FLAG}>)
    ENDFOREACH()
ENDIF(ASM_ENABLED)

Ответ 7

выйдите из ucm_add_flags и ucm_print_flags макросы ucm - добавлять флаги компилятора к соответствующим переменным cmake и проверять результаты

Ответ 8

Я придумал лучший метод, который работает в более старых версиях cmake, например. Ubuntu 14 имеет 2,8.12, а целевые выражения - 3.3.

Вот как вы установили бы определенные флаги С++:

STRING(REGEX REPLACE "<FLAGS>" "<FLAGS> -std=gnu++11 -fpermissive -fexceptions " CMAKE_CXX_COMPILE_OBJECT ${CMAKE_CXX_COMPILE_OBJECT})

Ответ 9

Это решение, которое я использую в настоящее время:

if(CMAKE_COMPILER_IS_GNUCXX)
    add_definitions(-std=c++0x)
    add_definitions(-std=gnu++11)
endif()

Или, если у вас установлена ​​более старая версия cmake, и вы хотите увидеть ее в cmake-gui:

set_property(CACHE CMAKE_CXX_FLAGS PROPERTY VALUE "-std=c++0x")