如何使用CMake检测编译器的C++11支持

0yycz8jy  于 2022-11-11  发布在  其他
关注(0)|答案(6)|浏览(290)

有没有办法让CMake自动检测编译器是否支持C11?
因为在CMake运行期间通知用户代码将不会被编译是很好的,因为编译器不支持C
11。现在我设置了C++11标志。但是,如果编译器不支持它,用户将得到编译错误,而不是在CMake运行期间的错误。
Perfect将是像find_package()一样工作的东西。但是,我还没有找到任何模块或函数来提供所需的功能。
此外,如果有一个功能可以检测编译器是否需要std=c++0xstd=c++11标志,那就更好了。
是否有可用的内容,或者我需要自己开发?
下面是我目前使用的一些代码,但是它只适用于GNU'c GCC编译器。如果有更通用的解决方案就更好了。

if(CMAKE_COMPILER_IS_GNUCXX)
   execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
   if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
        message(STATUS "C++11 activated.")
        add_definitions("-std=gnu++11")
   elseif(GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3)
        message(WARNING "C++0x activated. If you get any errors update to a compiler which fully supports C++11")
        add_definitions("-std=gnu++0x")
   else ()
        message(FATAL_ERROR "C++11 needed. Therefore a gcc compiler with a version higher than 4.3 is needed.")   
   endif()
else(CMAKE_COMPILER_IS_GNUCXX)
   add_definitions("-std=c++0x") 
endif(CMAKE_COMPILER_IS_GNUCXX)
tvz2xvvm

tvz2xvvm1#

如果您有CMake 3.1.0版或更高版本,则可以检测C编译器支持哪些C功能

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(foobar CXX)
message("Your C++ compiler supports these C++ features:")
foreach(i ${CMAKE_CXX_COMPILE_FEATURES})
  message("${i}")
endforeach()

但是通常你不需要在你的CMake脚本中使用CMake变量CMAKE_CXX_COMPILE_FEATURES,而是有两种方法告诉CMake你的C文件应该在哪种C标准下编译,通过显式指定C标准,或者通过指定所需的C功能并让CMake引入C标准。CMake将确保C使用正确的命令行标志(例如-std=c11)调用编译器。
1.显式指定C
标准
您可以通过为CMake目标设置CMake属性CXX_STANDARDCXX_STANDARD_REQUIRED来显式指定C++标准。

$ cat /tmp/src/CMakeLists.txt
project(foobar CXX)
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
add_executable(prog main.cc)
set_property(TARGET prog PROPERTY CXX_STANDARD 11)
set_property(TARGET prog PROPERTY CXX_STANDARD_REQUIRED ON)
$ cat /tmp/src/main.cc
int main() {
  return 0;
}
$ mkdir /tmp/build
$ cd /tmp/build
$ cmake /tmp/src
-- The CXX compiler identification is GNU 4.8.2
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/build
$ make VERBOSE=1 | grep main.cc | grep -- "-c"
/usr/bin/c++    -std=gnu++11 -o CMakeFiles/prog.dir/main.cc.o -c /tmp/src/main.cc
$

1.指定所需的C功能,并让CMake引入C标准
您可以使用CMake命令target_compile_features来指定要在CMake目的中使用的C功能。CMake将从此清单中归纳出要使用的C标准。CMake全域属性CMAKE_CXX_KNOWN_FEATURES列出您可以选择的C++功能。

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
message("Your CMake version supports these C++ features:")
get_property(known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
foreach(i ${known_features})
  message("${i}")
endforeach()

例如,这个文件名为main.cc的C程序利用了C11的特性:cxx_强枚举cxx_常量表达式cxx_自动类型


# include <cstdlib>

int main(int argc, char *argv[]) {
  enum class Color { Red, Orange, Yellow, Green, Blue, Violet };
  constexpr float a = 3.1415f;
  auto b = a;
  return EXIT_SUCCESS;
}

此CMakeLists.txt文件将构建它

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(foobar CXX)
add_executable(foobar main.cc)                                                                                                                                                                                                                                                     
set(needed_features
    cxx_strong_enums
    cxx_constexpr
    cxx_auto_type)
target_compile_features(foobar PRIVATE ${needed_features})
deikduxw

deikduxw2#

在这一点上,CMake没有一个方便的形式来支持C11。理想情况下,您应该像这样指定一个C11项目:

project(foo CXX11)

但是CXX11项目类型还不存在。在此之前,您可以使用两个阶段的技术:
1.确定编译器类型和版本
1.相应地调整构建标志。
例如,我使用Clang和GCC来支持C++11:


# Initialize CXXFLAGS.

set(CMAKE_CXX_FLAGS                "-Wall -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG          "-O0 -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE        "-O4 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")

# Compiler-specific C++11 activation.

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 ()
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
else ()
    message(FATAL_ERROR "Your C++ compiler does not support C++11.")
endif ()
pvcm50d1

pvcm50d13#

在写(pre-GCC 4.8)的时候,检测C11标志并添加它们可能不是一个好主意。这是因为改变标准(至少对于GCC)breaks ABI compatibility,这可能会导致链接错误。
因此,在项目的初始CMake配置期间,应通过编译器设置明确指定C
11标准的使用,例如:
CXX='g++ -std=c++11' cmake /path/to/source
也就是说,-std=c++11的使用应被视为一个单独的编译器,不应在一个项目中混合或更改。

svujldwt

svujldwt4#

用途:

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
    message(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} has no C++11 support.")
endif()

这是对 Enabling C11 (C0x) in CMake 进行的微小更改。

0lvr5msh

0lvr5msh5#

如果您使用的是CMake 3.8或更高版本,则可以使用cxx_std_11功能,该功能要求 *C++11或更高版本 *:

target_compile_features(Hello PUBLIC cxx_std_11)

在CMake 3.1* 及更新版本中,正确而简单的方法是使用指定目的的CXX_STANDARD属性。例如,使用auto(名为main.cpp)的简单范例:


# include <iostream>

int main() {
    auto num = 10;
    std::cout << num << std::endl;
    return 0;
}

以下CMakeLists.txt将启用C++11支持:

cmake_minimum_required(VERSION 3.3)
project(Hello CXX)

set(SOURCE_FILES main.cpp)
add_executable(Hello ${SOURCE_FILES})

set_property(TARGET Hello PROPERTY
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED ON
)

这将添加任何必要的标志,如-std=c++11。请注意,CXX_STANDARD_REQUIRED属性将防止该标准退化到早期版本。
另一种指定您使用的CMAKE_CXX_KNOWN_FEATURES的适当但不简单的方法,例如cxx_auto_type

cmake_minimum_required(VERSION 3.3)
project(Hello CXX)

set(SOURCE_FILES main.cpp)
add_executable(Hello ${SOURCE_FILES})
target_compile_features(Hello PRIVATE cxx_auto_type)
  • 我还没有在CMake 3. 1上尝试过这一点,但已经验证了它在CMake 3. 3中的工作原理。documentation for 3.1确实记录了这一点,所以它应该可以工作。
zf9nrax1

zf9nrax16#

我们编写了一个CMake模块,用于检测和启用C11支持,您可以在此处找到该模块:
https://github.com/NitroShare/CXX11-CMake-Macros
它仍然是一个正在进行中的工作,但我们正在使用它的一些Qt项目,目标Windows/Linux/Mac。目前只支持MSVC
,GCC和Clang。

范例:

include(CXX11)

check_for_cxx11_compiler(CXX11_COMPILER)

# If a C++11 compiler is available, then set the appropriate flags

if(CXX11_COMPILER)
    enable_cxx11()
endif()

相关问题