简体   繁体   English

cmake 不会编译为 C++ 11 标准

[英]cmake will not compile to C++ 11 standard

I'm new to C++ and have been struggling with compiling/making/linking/building/whatever, lets see if somebody can help me out.我是 C++ 的新手,一直在努力编译/制作/链接/构建/任何东西,看看是否有人可以帮助我。 I did some searches and found other people with similar problems but I tried their solutions with no luck, so here goes:我做了一些搜索,发现其他人也有类似的问题,但我尝试了他们的解决方案但没有运气,所以这里是:

A simple c++ program that uses C++ 11 functionality such as uniform initialization, threads, to_string , etc... generates errors that "xxx" was not declared in the scope .使用 C++ 11 功能(例如统一初始化、线程、 to_string等)的简单 C++ 程序会生成错误,即“xxx”未在 scope 中声明 Specifically right now I'd like to use to_string , and using it in the std namespace or specifically std::to_string creates the error "to_string" is not a member of STD .特别是现在我想使用to_string ,并在std命名空间或特别是std::to_string使用它会创建错误“to_string”不是 STD 的成员 So clearly it's not compiling with C++ 11.很明显,它不是用 C++ 11 编译的。

So here's my make file:所以这是我的制作文件:

#####################################
cmake_minimum_required (VERSION 2.8)
project (raspicam_test)
find_package(raspicam REQUIRED)
find_package(OpenCV)

IF  ( OpenCV_FOUND AND raspicam_CV_FOUND)
        MESSAGE(STATUS "COMPILING OPENCV TESTS")
        add_executable (main main.cpp)
        #target_compile_features(main PRIVATE cxx_range_for)
        set_property(TARGET main PROPERTY CXX_STANDARD 11)
        target_link_libraries (main ${raspicam_CV_LIBS})
ELSE()
        MESSAGE(FATAL_ERROR "OPENCV NOT FOUND IN YOUR SYSTEM")
ENDIF()
#####################################

As you can see I'm playing around with OpenCV on a raspberry pi.如您所见,我正在树莓派上使用 OpenCV。 But without the C++11 functions the program compiles and runs no issues.但是没有 C++11 函数,程序编译和运行都没有问题。 But I would like to add threads and other goodies from C++11.但我想从 C++11 添加线程和其他好东西。 I added the line set_property(TARGET main PROPERTY CXX_STANDARD_REQUIRED 11) according to the CMAKE documentation:我根据 CMAKE 文档添加了set_property(TARGET main PROPERTY CXX_STANDARD_REQUIRED 11)行:

https://cmake.org/cmake/help/v3.1/prop_tgt/CXX_STANDARD.htmlhttps://cmake.org/cmake/help/v3.1/prop_tgt/CXX_STANDARD.html

And it made no difference in the errors generated.它对生成的错误没有影响。 I did it first without the _REQUIRED and then with it.我首先在没有_REQUIRED情况下完成了_REQUIRED ,然后使用了它。 I also tried target_compile_features() instead but CMAKE returned with "unknown CMAKE command".我也尝试过target_compile_features()但 CMAKE 返回了“未知的 CMAKE 命令”。

Other details: -Compiling on a raspberry pi 3 running debian jessie -CXX compiler is GNU 4.9.2 -CMAKE 3.0.2其他详细信息:-在运行 debian jessie 的 raspberry pi 3 上编译 -CXX 编译器是 GNU 4.9.2 -CMAKE 3.0.2

In CMake versions earlier than 3.1 , we use3.1 之前的CMake 版本中,我们使用

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

to add compile options to the compiler call as described in the CMake Docs .将编译选项添加到编译器调用中,如CMake Docs 中所述

That's propably not as portable as the one in Alvaro's answer, but it's more readable and since you are on you RasPi, I guess, GCC and Clang as target compilers will do.这可能不像 Alvaro 的答案中的那样可移植,但它更具可读性,而且因为你在你的 RasPi 上,我猜,GCC 和 Clang 作为目标编译器会做。

Edit: For the sake of completeness: In CMake version 3.1 and newer , if you want to force C++11, you need the following lines:编辑:为了完整起见:在 CMake 3.1 及更新版本中,如果要强制使用 C++11,则需要以下几行:

set(CMAKE_CXX_STANDARD 11) # C++11...
set(CMAKE_CXX_STANDARD_REQUIRED ON) #...is required...
set(CMAKE_CXX_EXTENSIONS OFF) #...without compiler extensions like gnu++11

This enables the options for all targets following this declaration during compilation.这将在编译期间启用此声明之后的所有目标的选项。 If you want to control this more fine-grained, see Alvaro's answer or the CMake Docs of set_taget_properties() , which then looks something like this:如果您想更细粒度地控制它,请参阅 Alvaro 的答案或set_taget_properties()的 CMake Docs,它看起来像这样:

set_target_properties(myTarget PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED ON
    CXX_EXTENSIONS OFF
)

Edit: But beware that C++11 support in GCC 4 is not complete and there might be things that behave differently from the defined standard.编辑:但请注意 GCC 4 中的 C++11 支持并不完整,并且可能存在与定义标准不同的行为。

CMake add support for CXX_STANDARD and CXX_STANDARD_REQUIRED properties on 3.1 version. CMake 在 3.1 版本上添加了对CXX_STANDARDCXX_STANDARD_REQUIRED属性的支持。 CXX_STANDARD : Take one of CMAKE_CXX_STANDARD values and they are 98, 11 and 14 . CXX_STANDARD :取CMAKE_CXX_STANDARD值之一,它们是CMAKE_CXX_STANDARD 98, 11 and 14 If you pass CXX_STANDARD 11 and you compiler do not support c++11 CXX_STANDARD become 98 automatically and cmake do not give you any error if CXX_STANDARD_REQUIRED is OFF or unset.如果您通过CXX_STANDARD 11并且您的编译器不支持 c++11 CXX_STANDARD自动变为 98 并且如果CXX_STANDARD_REQUIREDOFF或未设置,cmake 不会给您任何错误。 If your set CXX_STANDARD_REQUIRED "ON" CXX_STANDARD specific value become as a required property to build and cmake handle this.如果您设置CXX_STANDARD_REQUIRED "ON" CXX_STANDARD特定值成为构建和 cmake 处理此问题的必需属性。

In orde to use CHECK_CXX_COMPILER_FLAG you nedd to include CheckCXXCompilerFlag module:为了使用CHECK_CXX_COMPILER_FLAG您需要包含 CheckCXXCompilerFlag 模块:

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if(COMPILER_SUPPORTS_CXX11)
    message(STATUS "${COMPILER_SUPPORTS_CXX11}")
else(COMPILER_SUPPORTS_CXX11)
    message(FATAL_ERROR "${COMPILER_SUPPORTS_CXX11}")
endif(COMPILER_SUPPORTS_CXX11)

If you have a old cmake you need handle complicate and not portable flags from compilers sush as:如果您有一个旧的 cmake,您需要处理来自编译器的复杂且不可移植的标志,如下所示:

function(suported_compilers)
  if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
    execute_process(
      COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
    if(NOT(GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7))
      message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.")
    endif(NOT(GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7))
  elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
  else()
    message(FATAL_ERROR "Your compiler is supported in the build set?, please "
                  "contact the maintainer.")
  endif()
endfunction(suported_compilers)
function(set_targets_compilers_flags target_list)
  suported_compilers()
  foreach(tg ${target_list})
    if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
      set_target_properties(${tg} PROPERTIES COMPILE_FLAGS "-g -std=c++14 -Wall -Wextra -Werror")
    elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
      set_target_properties(${tg} PROPERTIES COMPILE_FLAGS "/W4 /WX /EHsc")
    endif()
  endforeach()
endfunction(set_targets_compilers_flags)

Since the current cmake release is 3.10, I thought it may be appropriate to identify the newer method.由于当前的 cmake 版本是 3.10,我认为识别较新的方法可能是合适的。 While the suggestion to use add_compiler_虽然建议使用 add_compiler_

For anyone looking here at a more modern version of cmake (3.1+), The most appropriate answer is not to identify a version of a given compiler but to let CMAKE know what features need to be available.对于在这里查看更现代版本的 cmake (3.1+) 的任何人来说,最合适的答案不是确定给定编译器的版本,而是让 CMAKE 知道需要提供哪些功能。

target_compile_features(engine
    PRIVATE cxx_range_for
    )

I always enable c++11 in my code using CMake this way:我总是以这种方式使用 CMake 在我的代码中启用 c++11:

set(CMAKE_CXX_FLAGS "-std=c++11")

My compiler is gcc (Debian 4.9.2-10) 4.9.2, however in my workplace I also use other versions and this approach always works.我的编译器是 gcc (Debian 4.9.2-10) 4.9.2,但是在我的工作场所我也使用其他版本,这种方法总是有效。

EDIT (to avoid variable overwriting):编辑(以避免变量覆盖):

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM