コンパイラがC++ 11をサポートしているかどうかをCMakeが自動的に検出する方法はありますか?
コンパイラがC++ 11をサポートしていないため、CMakeの実行中にコードがコンパイルされないことをユーザーに通知するのは良いことです。現時点では、C++ 11フラグを設定しています。ただし、コンパイラがサポートしていない場合、CMakeの実行中にエラーではなくコンパイルエラーが発生します。
完璧はfind_package()
のように機能するものです。ただし、必要な機能を提供するモジュールまたは機能は見つかりませんでした。
さらに、コンパイラがstd=c++0x
フラグまたはstd=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)
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を使用する必要はありません。代わりに、C++標準を明示的に指定するか、必要なC++機能を指定してCMakeにC++標準を誘導させることにより、C++ファイルをコンパイルするC++標準をCMakeに伝える方法が2つあります。 CMakeは、正しいコマンドラインフラグ(-std = c ++ 11など)でC++コンパイラが呼び出されることを確認します。
CMakeプロパティを設定することで、C++標準を明示的に指定できます 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
$
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++プログラムは、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})
この時点で、CMakeにはC++ 11をサポートする便利な形式がありません。理想的には、次のようなC++ 11プロジェクトを指定します。
project(foo CXX11)
CMakeLists.txt
の先頭。ただし、CXX11
プロジェクトタイプは存在しません(まだ)。それまでは、2段階の手法を使用できます。
たとえば、これは私が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 ()
これを書いている時点で (GCC 4.8より前) 、C++ 11フラグを検出して追加するのは得策ではないかもしれません。これは、標準を変更すると(少なくともGCCの場合) ABI互換性が失われる であり、リンクエラーが発生する可能性があるためです。
したがって、C++ 11標準の使用は、 プロジェクトの初期CMake構成 の間にコンパイラー設定で明示的に指定する必要があります。
CXX='g++ -std=c++11' cmake /path/to/source
つまり、-std = c ++ 11の使用は、個別のコンパイラのように扱う必要があり、プロジェクト内で混合したり変更したりしないでください。
私は このCMakeスクリプト を見つけました。また、個々のC++ 11機能を確認することもできます。ただし、std=C++0x
とstd=C++11
の間で決定できるとは思いません。
つかいます:
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()
これは、CMakeでC++ 11(C++ 0x)を有効にするから少し変更したものです。
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では動作することを確認しました。 .1のドキュメント はこれをドキュメント化するので、動作するはずです。
ここで見つけることができるC++ 11サポートを検出および有効化するためのCMakeモジュールを作成しました。
https://github.com/NitroShare/CXX11-CMake-Macros
まだ進行中ですが、Windows/Linux/Macをターゲットとする多くのQtプロジェクトで使用しています。現在、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()