1. ホーム
  2. メイヴン

cmakeの使用例と仕上がりのまとめ

2022-02-26 07:02:51

この記事のコードは、githubにホストされています。  cmake_demo

cmake のいくつかの定義済み変数

  • PROJECT_SOURCE_DIR プロジェクトのルートディレクトリです。
  • PROJECT_BINARY_DIR cmakeコマンドが実行されるディレクトリで、通常は ${PROJECT_SOURCE_DIR}/build になります。
  • CMAKE_INCLUDE_PATH 環境変数、cmake 変数ではありません。
  • CMAKE_LIBRARY_PATH 環境変数
  • CMAKE_CURRENT_SOURCE_DIR 現在処理中の CMakeLists.txt が置かれているパスです。
  • CMAKE_CURRENT_BINARY_DIR ターゲットコンパイルディレクトリ
    この変数の値を変更するには、ADD_SURDIRECTORY(src bin)を使用します。
    SET(EXECUTABLE_OUTPUT_PATH <new path>)はこの変数には影響せず、最終ターゲットファイルが格納されているパスを変更するだけです。
  • CMAKE_CURRENT_LIST_FILE は、この変数が呼び出された CMakeLists.txt へのフル パスを出力します。
  • CMAKE_CURRENT_LIST_LINE この変数が配置されている行を出力します。
  • CMAKE_MODULE_PATH 自分のcmakeモジュールがある場所のパスを定義します。
    SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) とすると、INCLUDEコマンドを使って、自分のモジュールを呼び出すことができます。
  • EXECUTABLE_OUTPUT_PATH は、ターゲットバイナリの実行ファイルの場所を再定義します。
  • LIBRARY_OUTPUT_PATH ターゲットのリンクされたライブラリー・ファイルの場所を再定義します。
  • PROJECT_NAME は、PROJECT ディレクティブで定義されたプロジェクトの名前を返します。
  • CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS は IF ELSE 文の記述方法を制御するために使用されます。

システム情報

  • CMAKE_MAJOR_VERSION cmake のメジャーバージョン番号、例えば 2.8.6 の場合は 2
  • CMAKE_MINOR_VERSION cmake のマイナーバージョン番号、例えば 2.8.6 の場合は 8
  • CMAKE_PATCH_VERSION cmake のパッチレベル、例えば 2.8.6 では 6 です。
  • CMAKE_SYSTEM システム名、例:Linux-2.6.22
  • CAMKE_SYSTEM_NAME バージョンを除いたシステム名(例:Linux)。
  • CMAKE_SYSTEM_VERSION システムのバージョン、例:2.6.22
  • CMAKE_SYSTEM_PROCESSOR プロセッサ名、例:i686
  • UNIX OS X や cygwin を含むすべての UNIX 系プラットフォームでは TRUE
  • WIN32 cygwin を含むすべての win32 プラットフォームで TRUE となります。

スイッチオプション

  • BUILD_SHARED_LIBSは、デフォルトのライブラリのコンパイル方法を制御します。これが設定されておらず、ADD_LIBRARYを使用する際にライブラリのタイプが指定されていない場合、デフォルトのライブラリはスタティックライブラリとしてコンパイルされます(これはt3の小さな修正で確認することができます)。
  • CMAKE_C_FLAGS Cコンパイルオプションの設定
  • CMAKE_CXX_FLAGS C++のコンパイルオプションを設定します。

cmake共通コマンド

基本的な構文ルール
  • cmake変数は値を取るために${}メソッドを使用しますが、IF制御文では変数名を直接使用します。
  • 環境変数は $ENV{} で取得し、SET(ENV{VAR} VALUE)で代入します。
  • ディレクティブ(パラメータ1 パラメータ2...)
    パラメータは括弧で囲み、スペースまたはセミコロンで区切ります。

    Take the ADD_EXECUTABLE directive as an example.
    ADD_EXECUTABLE(hello main.c func.c) or
    ADD_EXECUTABLE(hello main.c;func.c)
    
    
    
  • ディレクティブは大文字と小文字を区別しません。パラメータと変数は大文字と小文字を区別します。大文字と小文字を区別します。 大文字 ディレクティブを使用します。

共通コマンドの一部です。
  • PROJECT
    PROJECT(プロジェクト名 [CXX] [C] [Java])
    プロジェクト名を指定すると、そのプロジェクトがサポートする言語を指定することができます。対応言語のリストは無視することもでき、デフォルトですべての言語がサポートされます
  • SET
    set(var [value] [cache type docstring [force]])
    変数の定義(複数のVALUEを定義可能、例:SET(SRC_LIST main.c util.c reactor.c))。
  • メッセージ
    MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "表示するメッセージ" ...)
    ユーザー定義のメッセージまたは変数の値を端末に出力する
    SEND_ERROR、エラーを発生させ、生成処理をスキップする
    STATUS, -を先頭にしたメッセージを出力します。
    FATAL_ERROR:すべての cmake プロセスを直ちに終了させます。
  • ADD_EXECUTABLE
    ADD_EXECUTABLE(bin_file_name ${SRC_LIST})
    実行ファイルを生成する
  • ライブラリの追加
    ADD_LIBRARY(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] SRC_LIST)
    ダイナミックまたはスタティック・ライブラリの生成
    SHARED ダイナミックライブラリ
    STATIC 静的ライブラリ
    MODULEはdyldを使用するシステムで有効です。dyldがサポートされていない場合はSHAREDと同等です。
    EXCLUDE_FROM_ALL は、そのライブラリがデフォルトでビルドされないことを意味します。
  • set_target_properties
    出力の名前を設定し、ダイナミックライブラリのバージョンとAPIのバージョンを設定する
  • cmake_minimum_required
    CMAKE_MINIMUM_REQUIRED(VERSION version_number [FATAL_ERROR])
    CMake のバージョン要件を宣言する
  • サブディレクトリを追加する
    ADD_SUBDIRECTORY(src_dir [binary_dir] [EXCLUDE_FROM_ALL])
    現在のプロジェクトに、ソースファイルが格納されるサブディレクトリを追加し、中間バイナリやターゲットバイナリが格納される場所を指定することができます。
    EXCLUDE_FROM_ALL とは:このディレクトリをコンパイルプロセスから除外する。
  • サブディレクトリ
    非推奨、もはや推奨されない
    (hello sample) は、それぞれ ADD_SUBDIRECTORY(hello),ADD_SUBDIRECTORY(sample) と書くのと同じ意味です。
  • インクルードディレクトリー
    INCLUDE_DIRECTORIES([AFTER | BEFORE] [SYSTEM] dir1 dir2 ...)
    特定のヘッダー検索パスを、スペースで区切って複数プロジェクトに追加します。スペースが含まれる場合は、パスを二重引用符で囲んでください。検索パスが追加される場所を制御する方法は2つあります。
    • CMAKE_INCLUDE_DIRECTORIES_BEFORE、この cmake 変数を on に設定することで、追加したヘッダー検索パスを既存のパスの前に配置することができます。
    • AFTERまたはBEFOREパラメータを使用すると、追加するか前置するかを制御することもできます。
  • リンク先ディレクトリ
    LINK_DIRECTORIES(dir1 dir2 ...)
    非標準の共有ライブラリ検索パスの追加
  • target_link_libraries
    TARGET_LINK_LIBRARIES(target lib1 lib2 ...)
    リンクが必要な共有ライブラリをターゲットに追加します。
  • 追加定義
    C/C++コンパイラーへの-D定義の追加
    ADD_DEFINITIONS(-DENABLE_DEBUG -DABC)、パラメータはスペースで区切られる
  • 追加_依存関係
    ADD_DEPENDENCIES(target-name depend-target1 depend-target2 ...)
    ターゲットが依存する他のターゲットを定義し、ターゲットがビルドされる前に依存するターゲットがビルドされていることを確認します。
  • aux_source_directoryを指定します。
    AUX_SOURCE_DIRECTORY(dir VAR)
    ディレクトリ内のすべてのソースファイルを検出し、そのリストを変数に格納します。
    カレントディレクトリの全ソースコードファイル名を変数DIR_HELLO_SRCSに代入する
  • EXEC_PROGRAM
    EXEC_PROGRAM(実行ファイル [実行場所] [ARGS <args>] [OUTPUT_VARIABLE <var>] [RETURN_VALUE <value>]))
    指定されたディレクトリ(デフォルトは CMakeLists.txt があるカレントディレクトリ)でプログラムを実行し、ARGS でパラメータを追加し、OUTPUT_VARIABLE と RETURN_VALUE で出力と戻り値を得るために使用します(以下の例)。

    # Run the ls command in src and add to src/CMakeLists.txt
    EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUE LS_RVALUE)
    IF (not LS_RVALUE)
        MESSAGE(STATUS "ls result: " ${LS_OUTPUT}) # Indent for aesthetics only, no syntax required
    ENDIF(not LS_RVALUE)
    
    
    
  • インクルード
    INCLUDE(file [OPTIONAL])は、CMakeLists.txt ファイルを読み込むために使用されます。
    INCLUDE(module [OPTIONAL])は、定義済みのcmakeモジュールをロードするために使用されます。
    OPTIONALパラメータはファイルが存在しなくてもエラーになりません
    ファイルをロードすることも、定義済みモジュールをロードすることもできます(モジュールは CMAKE_MODULE_PATH で指定されたパス内を検索します)。
    読み込まれた内容は、INCLUDE文への処理時に直接実行されます。

  • FIND_

    • FIND_FILE(<VAR> name path1 path2 ...)
      VAR変数は、ファイル名を含む、見つかったファイルへのフルパスを表します。
    • FIND_LIBRARY(<VAR> name path1 path2 ...)
      VAR変数は、ライブラリのファイル名を含む、見つかったライブラリへのフルパスを表します。

      FIND_LIBRARY(libX X11 /usr/lib)
      IF (NOT libx)
          MESSAGE(FATAL_ERROR "libX not found")
      ENDIF(NOT libX)
      
      
      
    • FIND_PATH(<VAR> name path1 path2 ...)
      VAR変数は、このファイルを含むパスを表します。

    • FIND_PROGRAM(<VAR> name path1 path2 ...)
      VAR 変数は、このプログラムを含むフルパスを表します。
    • FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED | COMPONENTS] [componets ...]])
      CMAKE_MODULE_PATH で定義されている Find<name>.cmake モジュールを呼び出すために使用します。または、独自の Find<name>
      モジュールは、SET(CMAKE_MODULE_PATH dir)でプロジェクト内のディレクトリに配置し、プロジェクトで使用するようにします。
  • IF
    構文

    IF (expression)
        COMMAND1(ARGS ...)
        COMMAND2(ARGS ...)
        ...
    ELSE (expression)
        COMMAND1(ARGS ...)
        COMMAND2(ARGS ...)
        ...
    ENDIF (expression) # Must have ENDIF corresponding to IF
    
    

    IF (expression), expression is not: null,0,N,NO,OFF,FALSE,NOTFOUND or <var>_NOTFOUND, true。
    IF (not exp)、上記と逆の場合
    IF (var1 AND var2)
    IF (var1 OR var2)
    IF (COMMAND cmd) cmd が本当にコマンドであり、起動可能であれば真
    IF (EXISTS dir) IF (EXISTS file) ディレクトリまたはファイルが存在すれば真。
    IF (file1 IS_NEWER_THAN file2), file1 が file2 より新しい場合、または file1/file2 のいずれかが存在しない場合、ファイル名にはフルパスが使用される必要があります。
    IF (IS_DIRECTORY dir) は、dir がディレクトリである場合に真となります。
    IF (DEFINED var) 変数が定義されている場合、真になる
    IF (var MATCHES regex) ここで var は var の名前か ${var} のどちらかです。
    IF (文字列 MATCHES 正規表現)

    True when the given variable or string can match the regular expression regex. For example.
    IF ("hello" MATCHES "ell")
        MESSAGE ("true")
    ENDIF ("hello" MATCHES "ell")
    
    
    

    数値比較式
    IF (変数 LESS 数)
    IF (文字列 LESS 数)
    IF (変数 GREATER 数値)
    IF (文字列 GREATER 番号)
    IF (変数 EQUAL 番号)
    IF (文字列 EQUAL 番号)

    アルファベット順で比較する
    IF (変数 STRLESS 文字列)
    IF (文字列 STRLESS 文字列)
    IF (変数 STRGREATER 文字列)
    IF (文字列 STRGREATER 文字列)
    IF (変数 STREQUAL 文字列)
    IF (文字列 STREQUAL 文字列)

    A small example, to determine the platform difference.
    IF (WIN32)
        MESSAGE(STATUS "This is windows.")
    ELSE (WIN32)
        MESSAGE(STATUS "This is not windows")
    ENDIF (WIN32)
    The above code is used to control different platforms for different controls, but it is not so comfortable to read, ELSE (WIN32) and other statements are easy to cause ambiguity.
    You can SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
    This time it can be written as :
    IF (WIN32)
    ELSE ()
    ENDIF ()
    Used in conjunction with ELSEIF, this is a possible way to write it:
    IF (WIN32)
        #do something related to WIN32
    ELSEIF (UNIX)
        #do something related to UNIX
    ELSEIF (APPLE)
        #do something related to APPLE
    ENDIF (WIN32)
    
    
    
  • WHILE
    構文

    WHILE(condition)
        COMMAND1(ARGS ...)
        COMMAND2(ARGS ...)
        ...
    ENDWHILE(condition)
    
    
    

    真偽の条件はIFディレクティブにあります。

  • FOREACH
    FOREACHコマンドは、3つの形式で使用することができます。
    1. リスト
      シンタックス
      FOREACH(loop_var arg1 arg2 ...)
           COMMAND1(ARGS ...)
           COMMAND2(ARGS ...)
       ...
      ENDFOREACH(loop_var)
      
      
      
      AUX_SOURCE_DIRECTORY(. SRC_LIST)
      FOREACH(F ${SRC_LIST})
           MESSAGE(${F})
      ENDFOREACH(F)
      
      
      
    2. 範囲
      構文
      FOREACH(loop_var RANGE total)
          COMMAND1(ARGS ...)
          COMMAND2(ARGS ...)
          ...
      ENDFOREACH(loop_var)
      
      
      
      
      Step from 0 to total in steps of 1
      FOREACH(VAR RANGE 10)
         MESSAGE(${VAR})
      ENDFOREACH(VAR)
      Output.
      012345678910
      
      
    3. 範囲とステップ

      シンタックス
      FOREACH(loop_var RANGE start stop [step])
          COMMAND1(ARGS ...)
          COMMAND2(ARGS ...)
          ...
      ENDFOREACH(loop_var)
      
      
      
      startで開始、stopで終了、ステップで終了。
      注意事項 ENDFOREACH 命令に遭遇するまで、ステートメントブロック全体は実際には実行されません。
      FOREACH(A RANGE 5 15 3)
          MESSAGE(${A})
      ENDFOREACH(A)
      Output.
      581114
      
      

cmakeでダイナミックライブラリとスタティックライブラリを生成する方法

参考 ADD_LIBRARY と SET_TARGET_PROPERTIES の使用法
t3例

cmakeでダイナミックライブラリとスタティックライブラリを使用する方法(ライブラリへのパスを探す)

INCLUDE_DIRECTORIES、LINK_DIRECTORIES、TARGET_LINK_LIBRARIES の使用法を参照する。
t4 ダイナミックライブラリまたはスタティックライブラリを使用した例
t5 定義済み cmake モジュールの使用例 (FindCURL.cmake でデモ)
t6 カスタム cmake モジュールの使用例 (カスタム FindHELLO.cmake を使用して記述)
備考 CMakeLists.txt と FindHELLO.cmake の t5 と t6 のコメント欄を読んでください。

cmakeで生成されたファイルの出力パスを指定する方法

  • 上記のようにADD_SUBDIRECTORY時にターゲットバイナリファイルの出力パスを指定する(以下を推奨)。
  • SETコマンドでEXECUTABLE_OUTPUT_PATHとLIBRARY_OUTPUT_PATH変数を再定義して、最終的なバイナリファイルの場所を指定します。
    SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
    SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
    
    
    
    上記の2つのコマンドは、通常、ADD_EXECUTABLEとADD_LIBRARYの後に、同じCMakeLists.txtに書かれている

cmakeでコンパイルオプションを追加する方法

CMAKE_C_FLAGS 変数を使用して C コンパイル オプションを追加する。
CMAKE_CXX_FLAGS 変数を使用して、C++ コンパイル オプションを追加します。
ADD_DEFINITIONを使用して追加します。

cmakeでヘッダーファイルのパスを追加する方法

INCLUDE_DIRECTORIESコマンドの使用方法を参照してください。

cmakeで画面に情報を表示させる方法

参考 MESSAGE の使用方法

cmakeで変数に値を割り当てる方法

SETとAUX_SOURCE_DIRECTORYの使い方を参照する。

提案 : プロジェクトのルートディレクトリにビルドを作成し、ビルドフォルダでcmake ...を実行します。これらの自動生成されたファイルが必要ない場合は、単にビルドフォルダを削除してください。