47

我的 CMakeLists.txt 中有以下内容:

project( Matfile )

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

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

add_library(
        Matfile
        ${SOURCES}
)

正如您可能想象的那样,我想做的是使用标志 -std=c++0x 编译我的 C++ 源代码(我正在使用 gcc,我需要 C++11 功能)。不幸的是,这不起作用,因为当我使用 cmake 生成 makefile 时,变量 CMAKE_CXX_FLAGS 完全无效。

如何在项目文件中设置此变量?

这似乎是一个非常愚蠢的问题,但我花了不少于两个小时试图弄清楚这一点。

4

11 回答 11

61

add_compile_options()如果您使用的是 2.8.12 或更高版本,则应该使用最直接的解决方案。对于旧版本,您可以“滥用” add_definitions()。虽然它仅用于添加 -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 或 C++):

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

但是,这不适用于 Visual Studio 生成器,因此请确保仅将其用于 Make/Ninja 生成器或使用target_compile_options()在每个目标范围内设置它。

于 2014-02-04T19:35:38.747 回答
27

在 CMake 3.1 及更高版本中设置 C++ 标准的正确方法是:

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED on)

也可以为一个单独的目标指定标准

set_property(TARGET mylib PROPERTY CXX_STANDARD 11)

从 CMake 3.8开始,该命令有一个新选项target_compile_features,允许为目标设置所需的标准:

target_compile_features(mylib PUBLIC cxx_std_11)

优点是它将需求传播到依赖目标。如果您编译具有cxx_std_11所需功能的库,则链接到它的任何二进制文件都将自动具有此要求集。

于 2017-09-20T19:32:54.423 回答
14

FORCE使用国旗有帮助吗?

SET ( CMAKE_CXX_FLAGS "-std=c++0x" CACHE STRING "compile flags" FORCE)
于 2013-02-27T01:06:21.683 回答
5

也许这会更好:

set_source_files_properties(${SOURCES}
       PROPERTIES
       COMPILE_FLAGS  "-std=c++0x")
于 2013-02-26T22:17:39.267 回答
3

要扩展一点 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)
于 2016-11-20T19:31:29.410 回答
2

在需要编译器特定标准的特定情况下,cmake 3.1 通过提供一种请求标准版本或一组编译器功能的方法来解决该问题。请参阅此答案官方文档

于 2015-04-27T16:43:04.173 回答
1

检查ucm的ucm_add_flagsucm_print_flags宏- 将编译器标志添加到适当的 cmake 变量并检查结果

于 2016-10-05T21:22:32.733 回答
0

我想出了一种适用于旧版本 cmake 的更好方法,例如 Ubuntu 14 有 2.8.12,目标表达式是 3.3 功能。

以下是设置一些 C++ 特定标志的方法:

STRING(REGEX REPLACE "<FLAGS>" "<FLAGS> -std=gnu++11 -fpermissive -fexceptions " CMAKE_CXX_COMPILE_OBJECT ${CMAKE_CXX_COMPILE_OBJECT})
于 2017-02-20T22:31:06.560 回答
0

这是我目前使用的解决方案:

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")
于 2018-01-02T21:35:28.690 回答
0

我在 C++ / clr 项目中遇到过这种情况,我需要修改两个变量 -CMAKE_CXX_FLAGSCMAKE_CXX_FLAGS_DEBUG. CMAKE_CXX_FLAGS可以使用 修改set_source_files_properties / COMPILE_FLAGS,但不能CMAKE_CXX_FLAGS_DEBUG。我已经得出结论,在单独的文件夹中创建单独的、项目特定的 cmake 文件。如果项目是孤立的 - 那么变量修改将仅在当前 C++/clr 项目中起作用。

我想如果你想拥有多个 C++ 项目和多个 C++/clr 项目,至少将它们分开在两个不同的文件夹中(如果不是更多的话)是有意义的——特定于本机 C++,特定于托管 C++。

以类似的方式,您可以在 cmake 测试应用程序中找到: https ://github.com/Kitware/CMake/blob/master/Tests/CSharpLinkToCxx/CMakeLists.txt

这是同样的事情,只是有更多的解释:

# These variables affects also other C++ projects, that's why separate cmake for this c++ dll

# Clr compiling requires these:

# "Enable C++ Exceptions" - "Yes (/EHsc)" => "Yes with SEH Exceptions (/EHa)"
string(REPLACE "/EHsc" "/EHa" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

# "Basic Run-time checks" - "Both (/RTC1, equiv. to /RTCsu) (/RTC1)" => "Default"
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")

这是一种方法。但是,如果您想在循环中生成本机 c++ 和托管 c++ 项目 - 一种方法是禁用全局标志:

# Disable global flag, configure on per project basis, using target_compile_options, target_link_options
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/INCREMENTAL" "" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
#string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

然后为每个项目单独配置每个项目设置,例如:

if(${is_managed})
    # Managed C++ code
    set_target_properties(${project} PROPERTIES VS_GLOBAL_CLRSupport "true")
    set_property(TARGET ${project} PROPERTY VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.7.2")

    # Being able to debug dll
    target_link_options(${project} PRIVATE "$<$<CONFIG:Debug>:/ASSEMBLYDEBUG>")

    # Disable incremental linking
    target_link_options(${project} PRIVATE "$<$<CONFIG:Debug>:/INCREMENTAL:NO>")

    # "Enable C++ Exceptions" - "Yes with SEH Exceptions (/EHa)"
    set(compile_flags /EHa)
else()
    # Native C++ code
    # "Basic Run-time checks" - "Both (/RTC1, equiv. to /RTCsu) (/RTC1)" => "Default"
    target_compile_options(${project} PRIVATE "$<$<CONFIG:Debug>:/RTC1>")

    # Enable incremental linking
    target_link_options(${project} PRIVATE "$<$<CONFIG:Debug>:/INCREMENTAL>")

    # "Enable C++ Exceptions" - "Yes (/EHsc)"
    set(compile_flags /EHsc)
endif()
set_target_properties(${project} PROPERTIES COMPILE_FLAGS ${compile_flags})
于 2020-04-26T07:51:22.403 回答
0

我有类似的问题-lstdc++fs

最后,解决我的问题是target_link_libraries

set(CMAKE_CXX_STANDARD 17)

add_executable(main main.cpp)

target_link_libraries(main -lstdc++fs)
于 2021-11-13T00:43:26.473 回答