【CMake】非公開変数 CMAKE_LANG_COMPILER_VERSION_INTERNAL を安全に扱う


CMAKE_LANG_COMPILER_VERSION_INTERNAL は、CMake 内部で使用される変数であり、コンパイラのバージョンを特定するために使用されます。この変数は、コンパイラのバージョン番号に基づいて、CMake がコンパイラとどのようにやり取りするかを決定するために使用されます。

詳細

CMAKE_LANG_COMPILER_VERSION_INTERNAL は、以下の情報を格納します。

  • コンパイラのパッチレベル (例: 0、1、2)
  • コンパイラのマイナーバージョン番号 (例: 3、2、1)
  • コンパイラのメジャーバージョン番号 (例: 10、9、8)
  • コンパイラの種類 (例: GCC、Clang、MSVC)

この情報は、CMake が以下のことを行うために使用されます。

  • コンパイラが生成する実行可能ファイルの形式を特定する
  • コンパイラが生成するオブジェクトファイルとライブラリの形式を特定する
  • コンパイラがサポートするフラグとオプションを特定する

以下は、CMAKE_LANG_COMPILER_VERSION_INTERNAL の値の例です。

CMAKE_C_COMPILER_VERSION_INTERNAL=10.3.0
CMAKE_CXX_COMPILER_VERSION_INTERNAL=9.2.1

上記の例では、CMAKE_C_COMPILER_VERSION_INTERNAL は GCC 10.3.0 を指し、CMAKE_CXX_COMPILER_VERSION_INTERNAL は Clang 9.2.1 を指します。

注意事項

CMAKE_LANG_COMPILER_VERSION_INTERNAL は、CMake 内部で使用される変数であり、ユーザーが直接変更することは想定されていません。この変数の値を変更すると、予期しない動作が発生する可能性があります。

  • この説明は、CMake バージョン 3.29.3 を基にしています。他のバージョンでは、CMAKE_LANG_COMPILER_VERSION_INTERNAL の動作が異なる場合があります。
  • 具体的なコード例は含まれていませんが、CMAKE_LANG_COMPILER_VERSION_INTERNAL 変数の役割と使用方法を理解するのに役立つ情報を提供しています。
  • この説明は、プログラミング初心者でも理解できるように、専門用語をできるだけ避け、平易な言葉で記述しています。


cmake_minimum_required(VERSION 3.29)

project(MyProject)

set(CMAKE_C_COMPILER_VERSION_INTERNAL 10.3.0)

if(CMAKE_C_COMPILER_VERSION_INTERNAL GREATER_EQUAL 10.3.0)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable")
endif()

add_executable(MyProgram main.c)

このコード例では、CMAKE_C_COMPILER_VERSION_INTERNAL の値が 10.3.0 以上の場合、コンパイラフラグ -Wno-unused-variable が設定されます。このフラグは、未使用の変数に関する警告を抑制します。

例 2: コンパイラバージョンに基づいてライブラリのリンク方法を決定する

cmake_minimum_required(VERSION 3.29)

project(MyProject)

set(CMAKE_CXX_COMPILER_VERSION_INTERNAL 9.2.1)

if(CMAKE_CXX_COMPILER_VERSION_INTERNAL GREATER_EQUAL 9.2.0)
  set(CMAKE_SHARED_LINK_FLAGS "${CMAKE_SHARED_LINK_FLAGS} -Wl,--whole-archive")
endif()

add_library(MyLibrary foo.cpp bar.cpp)

このコード例では、CMAKE_CXX_COMPILER_VERSION_INTERNAL の値が 9.2.0 以上の場合、リンカフラグ -Wl,--whole-archive が設定されます。このフラグは、すべてのライブラリオブジェクトをアーカイブに含めるようにリンカに指示します。

例 3: コンパイラバージョンに基づいて実行可能ファイルの形式を決定する

cmake_minimum_required(VERSION 3.29)

project(MyProject)

set(CMAKE_C_COMPILER_VERSION_INTERNAL 8.1.0)

if(CMAKE_C_COMPILER_VERSION_INTERNAL LESS 9.0)
  set(CMAKE_EXE_LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} -Wl,-rpath=${CMAKE_INSTALL_PREFIX}/lib")
endif()

add_executable(MyProgram main.c)

このコード例では、CMAKE_C_COMPILER_VERSION_INTERNAL の値が 9.0 未満の場合、リンカフラグ -Wl,-rpath=${CMAKE_INSTALL_PREFIX}/lib が設定されます。このフラグは、リンカにランタイムライブラリを検索するパスを指示します。



  • バージョン依存: CMAKE_LANG_COMPILER_VERSION_INTERNAL のフォーマットは、CMake バージョンによって異なる場合があります。そのため、特定のバージョンの CMake でのみ機能するコードを作成することは困難です。
  • 非公開変数: CMAKE_LANG_COMPILER_VERSION_INTERNAL は非公開変数であり、ユーザーが直接変更することは想定されていません。この変数の値を変更すると、予期しない動作が発生する可能性があります。

これらの理由から、CMAKE_LANG_COMPILER_VERSION_INTERNAL の代替方法を検討することが重要です。以下に、いくつかの代替方法を紹介します。

代替方法 1: コンパイラ固有の変数を使用する

多くのコンパイラは、バージョン情報を含む独自の変数を提供しています。例えば、GCC は __GNUC____GCC_MINOR____GCC_REVISION__ などの変数を提供し、Clang は __clang_major____clang_minor____clang_revision__ などの変数を提供します。

cmake_minimum_required(VERSION 3.29)

project(MyProject)

if(CMAKE_C_COMPILER_FAMILY MATCHES "GNU")
  set(CMAKE_C_COMPILER_VERSION "${__GNUC__}.${__GCC_MINOR__}.${__GCC_REVISION__}")
elseif(CMAKE_C_COMPILER_FAMILY MATCHES "Clang")
  set(CMAKE_C_COMPILER_VERSION "${__clang_major__}.${__clang_minor__}.${__clang_revision__}")
endif()

message(STATUS "C compiler version: ${CMAKE_C_COMPILER_VERSION}")

このコード例では、CMake はコンパイラファミリに基づいて適切な変数を使用します。

代替方法 2: CMAKE_LANG_PROCESSOR_VERSION を使用する

CMake 3.18 以降では、CMAKE_LANG_PROCESSOR_VERSION という新しい変数が導入されました。この変数は、コンパイラだけでなく、他の言語プロセッサ (例: インタプリタ) のバージョン情報も格納します。

cmake_minimum_required(VERSION 3.18)

project(MyProject)

message(STATUS "C compiler version: ${CMAKE_C_COMPILER_VERSION}")
message(STATUS "C++ compiler version: ${CMAKE_CXX_COMPILER_VERSION}")

このコード例では、CMake は CMAKE_LANG_PROCESSOR_VERSION 変数を使用して、C コンパイラと C++ コンパイラのバージョン情報を取得します。

代替方法 3: 外部ツールを使用する

compvercppvers などの外部ツールを使用して、コンパイラのバージョン情報を取得することもできます。これらのツールは、コマンドラインから実行でき、CMake のスクリプト内で使用することができます。

cmake_minimum_required(VERSION 3.29)

project(MyProject)

execute_process(COMMAND compver -V OUTPUT_VARIABLE CMAKE_C_COMPILER_VERSION)
execute_process(COMMAND cppvers -V OUTPUT_VARIABLE CMAKE_CXX_COMPILER_VERSION)

message(STATUS "C compiler version: ${CMAKE_C_COMPILER_VERSION}")
message(STATUS "C++ compiler version: ${CMAKE_CXX_COMPILER_VERSION}")

このコード例では、CMake は compvercppvers ツールを使用して、C コンパイラと C++ コンパイラのバージョン情報を取得します。

注意事項

これらの代替方法は、CMAKE_LANG_COMPILER_VERSION_INTERNAL と完全に互換性があるわけではありません。コードを調整する必要がある場合があります。

  • [cppvers tool](