Как определить поддержку C ++ 11 компилятора с CMake

Есть ли способ позволить CMake автоматически определять, поддерживает ли компилятор C ++ 11 или нет?

Как было бы неплохо сообщить пользователям во время запуска CMake, что код не будет компилироваться, так как компилятор не поддерживает C ++ 11. На данный момент я установил флаги C ++ 11. Однако, если компилятор не поддерживает его, пользователь получает ошибки компиляции вместо ошибки во время запуска CMake.

Идеальным было бы то, что работает какfind_package(), Однако я не нашел ни одного модуля или функции, которые бы обеспечивали необходимую функциональность.

Дополнительно было бы неплохо иметь возможность определять, нужны ли компилятору флагиstd=c++0x или жеstd=c++11.

Есть ли что-то доступное или мне нужно разработать это самостоятельно?

Ниже приведен код, который я использую до сих пор, однако он работает только с компиляторами GCC GNU. Было бы неплохо, если бы было более общее решение.

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)
 Li Dong04 мар. 2014 г., 04:20
Зачем использоватьadd_definitions команда вместо настройкиCMAKE_CXX_FLAGS установить параметры компилятора?

Ответы на вопрос(7)

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)

* I have not tried this on CMake 3.1, but have verified it works in CMake 3.3. The документация для 3.1 документирует это так, чтобы оно работало

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()

http://www.guyrutenberg.com/2014/01/05/enabling-c11-c0x-in-cmake/ с небольшими изменениями

 13 февр. 2018 г., 23:29
Здравствуйте! К сожалению, ваше решение работает только для компиляторов, которые поддерживают указанные флаги для установки стандартной версии C ++. В случае компилятора, который поддерживает C ++ 11, но не поддерживает эти флаги, ваше решение выдаст ложный минус. Например, MS VS 2015 не пройдет.

идеале вы должны указать проект C ++ 11 следующим образом:

project(foo CXX11)

в начале вашегоCMakeLists.txt, НоCXX11 Тип проекта не существует (пока). До этого вы можете использовать двухэтапную технику:

Determine the compiler type and version Adjust build flags accordingly.

Например, это то, что я использую для поддержки C ++ 11 с Clang и GCC:

# 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 ()
 31 янв. 2013 г., 19:07
Прошло уже более шести месяцев с момента вашего ответа, знаете ли вы какие-либо обновления? Кажется странным, что эта проблема еще не решена.
 17 окт. 2014 г., 23:27
Круто, как только это станет более распространенным, я обновлю ответ. Похоже, теперь можно связать версию C ++ с целью CMake черезset_property(TARGET tgt PROPERTY CXX_STANDARD 11).
 06 окт. 2015 г., 21:20
Время для обновления. Теперь это широко используется.
 01 февр. 2013 г., 03:31
К сожалению, я до сих пор не знаю лучшего решения. Может быть, это поможет поднять эту проблему в списке рассылки CMake.
 13 окт. 2014 г., 17:09
Привет, Джек и Матиас, я знаю, что этот комментарий очень поздний, но похоже, что некоторая поддержка C ++ 11 была наконец добавлена в CMake:public.kitware.com/Bug/view.php?id=13842 Насколько я понимаю, это будет частью CMake 3.1, выпуск которого запланирован на начало ноября.
Решение Вопроса

вы можете определить, какие функции 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()

Но обычно вам не нужно использовать переменную CMakeCMAKE_CXX_COMPILE_FEATURES в ваших скриптах CMake. Вместо этого есть два способа сказать CMake, по какому стандарту C ++ ваши файлы C ++ должны быть скомпилированы, либо указание стандарта C ++ в явном виде или путем указания необходимых функций C ++ и позволить CMake индуцировать стандарт C ++. CMake убедится, что компилятор C ++ вызывается с правильными флагами командной строки (например, -std = c ++ 11).

1. Specifying the C++ standard explicitly

Вы можете указать стандарт C ++ явно, установив свойства CMake CXX_STANDARD  а также CXX_STANDARD_REQUIRED для вашей цели CMake.

$ 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
$
2. Specifying the required C++ features and let CMake induce the C++ standard

Вы можете использовать команду CMaketarget_compile_features указать функции C ++, которые используются в вашей цели CMake. Из этого списка CMake будет стимулировать использование стандарта C ++. Глобальное свойство CMakeCMAKE_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()

Например, эта программа C ++ с именем файлаmain.cc использует возможности C ++ 11: cxx_strong_enums, cxx_constexpr, cxx_auto_type

#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})
 10 июн. 2015 г., 14:49
Немного больно, что это нужно делать для каждой цели. Было бы удобно сказать «просто используйте C ++ 11 везде» и покончим с этим.
 01 июл. 2016 г., 04:21
@RaphaelMiedl Я задал этот вопрос и получил ответ. увидетьlink, В основном вы используете SET (CMAKE_CXX_EXTENSIONS OFF).
 20 авг. 2015 г., 15:28
Похоже наCXX_STANDARD 11 не работает сGLOBAL свойство области, которая полностью отстой.
 27 янв. 2016 г., 12:55
У меня все еще есть некоторые проблемы с этим подходом, так как он добавляет-std=gnu++11 и включает нестандартные расширения. Мне действительно нравится толькоstd=c++11 и получаю ошибку, если я пытаюсь использовать одно из этих нестандартных расширений, в первую очередь переносимость.
 24 сент. 2015 г., 01:06
@MarcGlisse @abergmeier Чтобы определить его в текущей области видимости CMake, вы можетеset(CMAKE_CXX_STANDARD 11)

этот скрипт CMake который утверждает, что делает именно то, что вам нужно. Он также может проверить отдельные функции C ++ 11. Я не думаю, что это может решить междуstd=C++0x а такжеstd=C++11 хоть.

 23 мар. 2013 г., 15:22
Хороший вопрос ... Я согласен
 21 апр. 2013 г., 01:15
Теперь, когда мы вышли после GCC 4.8, ситуация такая же?
 12 февр. 2018 г., 07:48
Ссылка не работает на данный момент. Вы знаете, где найти работу, как?
 10 дек. 2015 г., 21:08
По сути, да. Или может понадобиться добавить определение компилятора и т. Д. Более подробная информация для GCC 5 находится здесь:developerblog.redhat.com/2015/02/05/gcc5-and-the-c11-abi
 23 февр. 2018 г., 19:36
 13 февр. 2018 г., 23:29
Здравствуйте! К сожалению, ваше решение работает только для компиляторов, которые поддерживают указанные флаги для установки стандартной версии C ++. В случае компилятора, который поддерживает C ++ 11, но не поддерживает эти флаги, ваше решение выдаст ложный минус. Например, MS VS 2015 не пройдет.
 tune2fs11 июн. 2012 г., 20:09
Спасибо за ссылку, я тоже это обнаружил. Однако она подходит для моей проблемы не идеально, так как я не хочу тестировать определенные функции и делать код зависимым от них. Но я думаю, что с некоторыми изменениями это может удовлетворить мою проблему.

который вы можете найти здесь:
https://github.com/NitroShare/CXX11-CMake-Macros

Он все еще находится в стадии разработки, но мы используем его для ряда проектов Qt, ориентированных на Windows / Linux / Mac. В настоящее время поддерживаются только MSVC ++, GCC и Clang.

Example:

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()

(до GCC 4.8), это может быть не очень хорошая идея, чтобы обнаружить флаги C ++ 11 и добавить их. Это потому, что изменение стандарта (по крайней мере, для GCC)нарушает совместимость ABI, что может привести к ошибкам ссылки.

Следовательно, использование стандарта C ++ 11 должно быть явно указано с настройкой компилятора во времяначальная конфигурация CMake проектанапример,

CXX='g++ -std=c++11' cmake /path/to/source

То есть использование -std = c ++ 11 должно рассматриваться как отдельный компилятор, который нельзя смешивать или изменять в проекте.

 23 мар. 2013 г., 15:22
Хороший вопрос ... Я согласен
 21 апр. 2013 г., 01:15
Теперь, когда мы вышли после GCC 4.8, ситуация такая же?
 10 дек. 2015 г., 21:08
По сути, да. Или может понадобиться добавить определение компилятора и т. Д. Более подробная информация для GCC 5 находится здесь:developerblog.redhat.com/2015/02/05/gcc5-and-the-c11-abi

Ваш ответ на вопрос