CMakeはどのように使用されますか?[閉まっている]


95

初心者としてCMakeに関する有用な情報を入手することは非常に難しいことで有名です。これまでのところ、いくつかの非常に基本的なプロジェクトを設定する方法に関するチュートリアルをいくつか見てきました。ただし、これらはどれも、そこに示されているものの背後にある理由を説明しておらず、常に埋めるべき多くの穴が残っています。

CMakeListsでCMakeを呼び出すとはどういう意味ですか?ビルドツリーごとに一度呼び出されることになっていますか?すべてが同じソースの同じCMakeLists.txtファイルを使用する場合、ビルドごとに異なる設定を使用するにはどうすればよいですか?各サブディレクトリに独自のCMakeListsファイルが必要なのはなぜですか?プロジェクトのルートにあるもの以外のCMakeLists.txtでCMakeを使用することは理にかなっていますか?もしそうなら、どのような場合に?独自のサブディレクトリのCMakeListsファイルから実行可能ファイルまたはライブラリを構築する方法を指定することと、すべてのソースのルートにあるCMakeListsファイルでそれを実行することの違いは何ですか?-GCMakeを呼び出すときにオプションを変更するだけで、Eclipse用のプロジェクトとVisual Studio用のプロジェクトを作成できますか?それはどのように使用されていますか?

これまでに見たチュートリアル、ドキュメントページ、質問/回答のいずれも、CMakeの使用方法を理解する上で役立つ洞察を提供していません。例は完全ではありません。どんなチュートリアルを読んだとしても、何か重要なことを忘れているように感じます。

私のようなCMake初心者がこれを明示的に尋ねない多くの質問がありますが、それは、newbとして、私たちはCMakeの扱い方やそれをどうするかわからないという事実を明らかにしています。


8
代わりにブログ投稿を書くべきでしょう。
steveire 2014

2
私は「広すぎる」と投票しようとしています...これは、stackoverflowにぴったりというより、CMakeに関する個人的なエッセイのように感じられます。これらの質問すべてを別々の質問に入れなかったのはなぜですか?そして、あなたの質問と答えは他の多くのものとどのように異なりますか。たとえば、stackoverflow.com / q / 20884380 / 417197stackoverflow.com / q / 4745996/ 417197stackoverflow.com / q / 4506193/417197
アンドレ

13
@Andreなぜこの質問:私はCMakeを理解するために1週間費やしましたが、チュートリアルは完了していませんでした。あなたが指摘したこれらのリンクは良いですが、CMakeListの束を内部に持つプロジェクトを投げつけられたためにCMakeを見つけた人にとっては、CMakeがどのように機能するかについてはあまり明かされません。私は正直に言って、CMakeの学習を始めたときに自分に返送できるようにと答えたいと思っています。そして、サブ質問は私がそれらの疑問を持たないために私が知っておくべきことは何であるかを実際に尋ねようとしていることを示すことを意図しています。正しい質問をするのは難しいです。
leinaD_natipaC 2014

2
答えではありませんが、jaws.rootdirectory.deをご覧になることをお勧めします。CMakeドキュメンテーション(および受け入れられた回答...)は、あなたができることを一口サイズのスニペットで示しています、私は(決して「完全」または「完璧」ではない)基本的な設定を書きました。 IMHOは、CMake(およびCTest、CPack、CDash ...)ができることを紹介します。すぐに構築でき、プロジェクトのニーズに合わせて簡単に調整/拡張できます。
DevSolar 2015

9
そのような質問が今日閉じられているのは残念です。回答のようなチュートリアルが必要だが、文書化が不十分/あいまいなトピックに関する幅広い質問(別の例はTorch7 C apiです)と研究レベルの質問は開いたままにする必要があると思います。それらは、サイトを悩ませている典型的な「ちょっと、おもちゃのプロジェクトを作っているときにセグメンテーションフォールトを持っている」よりもずっと興味深いものです。
Ash

回答:


137

CMakeの目的は何ですか?

ウィキペディアによると:

CMakeは、コンパイラに依存しない方法を使用してソフトウェアのビルドプロセスを管理するための[...]ソフトウェアです。複数のライブラリに依存するディレクトリ階層とアプリケーションをサポートするように設計されています。make、AppleのXcode、Microsoft Visual Studioなどのネイティブビルド環境と組み合わせて使用​​されます。

CMakeを使用すると、コンパイラ/ビルド環境に固有の個別の設定を維持する必要がなくなります。あなたは持っている1つの構成を、そしてそのために働く多くの環境。

CMakeは、何も変更せずに同じファイルからMicrosoft Visual Studioソリューション、Eclipseプロジェクト、またはMakefile迷路を生成できます。

CMakeは、コードが含まれている多数のディレクトリがある場合、プロジェクトをコンパイルする前に、プロジェクトに必要なすべての依存関係、ビルド順序、その他のタスクを管理します。実際には何もコンパイルしません。CMakeを使用するには、(CMakeLists.txtと呼ばれる構成ファイルを使用して)コンパイルする必要がある実行可能ファイル、リンクするライブラリ、プロジェクト内のディレクトリとその中にあるもの、およびフラグなどの詳細を指示する必要がありますまたは必要な他のもの(CMakeは非常に強力です)。

これが正しく設定されている場合は、CMakeを使用して、選択した「ネイティブビルド環境」がその作業を行うために必要なすべてのファイルを作成します。Linuxでは、デフォルトでMakefileを意味します。したがって、CMakeを実行すると、独自に使用するためのファイルといくつかMakefileのsのファイルが作成されます。その後、コードの編集が完了するたびに、ルートフォルダーからコンソールに「make」と入力するだけで、コンパイルおよびリンクされた実行可能ファイルが作成されます。

CMakeはどのように機能しますか?それは何をするためのものか?

以下は、私が全体的に使用するプロジェクトのセットアップ例です。

simple/
  CMakeLists.txt
  src/
    tutorial.cxx
    CMakeLists.txt
  lib/
    TestLib.cxx
    TestLib.h
    CMakeLists.txt
  build/

各ファイルの内容を示し、後で説明します。

CMakeは、プロジェクトのルート に従ってプロジェクトをセットアップし、コンソールでCMakeLists.txt実行cmakeしたディレクトリにセットアップします。プロジェクトのルートではないフォルダーからこれを行うと、いわゆるアウトオブソースビルドが生成されます。つまり、コンパイル中に作成されたファイル(objファイル、libファイル、実行可能ファイルなど)は、そのフォルダーに配置されます、実際のコードとは別に保管します。これは混乱を減らすのに役立ち、他の理由からも推奨されます。

cmakeルート以外で実行するとどうなるかわかりませんCMakeLists.txt

この例では、すべてをbuild/フォルダー内に配置したいので、まずそこに移動してから、ルートがCMakeLists.txt存在するディレクトリにCMakeを渡します。

cd build
cmake ..

デフォルトでは、これは私が言ったようにMakefileを使用してすべてを設定します。ビルドフォルダーは次のようになります。

simple/build/
  CMakeCache.txt
  cmake_install.cmake
  Makefile
  CMakeFiles/
    (...)
  src/
    CMakeFiles/
      (...)
    cmake_install.cmake
    Makefile
  lib/
    CMakeFiles/
      (...)
    cmake_install.cmake
    Makefile

これらのファイルはすべて何ですか? 心配する必要があるのは、Makefileとプロジェクトフォルダだけです。

src/lib/フォルダに注意してください。これらはsimple/CMakeLists.txt、コマンドを使用してポイントするために作成されましたadd_subdirectory(<folder>)。このコマンドは、CMakeに別のCMakeLists.txtファイルを探してそのフォルダーを調べ、そのスクリプトを実行するように指示ます。そのため、この方法で追加されたすべてのサブディレクトリには、ファイルが含まれている必要がありCMakeLists.txtます。このプロジェクトでsimple/src/CMakeLists.txtは、実際の実行可能ファイルsimple/lib/CMakeLists.txtを構築する方法とライブラリを構築する方法について説明します。がCMakeLists.txt記述するすべてのターゲットは、デフォルトでビルドツリー内のサブディレクトリに配置されます。だから、簡単に

make

から実行されるコンソールでbuild/、いくつかのファイルが追加されます:

simple/build/
  (...)
  lib/
    libTestLib.a
    (...)
  src/
    Tutorial
    (...)

プロジェクトがビルドされ、実行可能ファイルを実行する準備ができました。実行可能ファイルを特定のフォルダに入れたい場合はどうしますか? 適切なCMake変数を設定するか、特定のターゲットのプロパティを変更します。CMake変数については後で詳しく説明します。

CMakeにプロジェクトのビルド方法を伝えるにはどうすればよいですか?

以下に、ソースディレクトリ内の各ファイルの内容を説明します。

simple/CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

project(Tutorial)

# Add all subdirectories in this project
add_subdirectory(lib)
add_subdirectory(src)

必要でない場合にCMakeがスローする警告に従って、最低限必要なバージョンを常に設定する必要があります。CMakeのバージョンが何であれ使用します。

プロジェクトの名前は後で使用でき、同じCMakeファイルから複数のプロジェクトを管理できるという事実へのヒントになります。ただし、詳しくは説明しません。

前述のように、add_subdirectory()プロジェクトにフォルダを追加します。つまり、CMakeはそれがCMakeLists.txt内部にあることを期待し、続行する前に実行されます。ちなみに、CMake関数が定義されている場合はCMakeLists.txt、サブディレクトリの他のから使用できますが、使用する前に定義するadd_subdirectory()必要があります。そうしないと、見つかりません。CMakeはライブラリについてはより賢いので、この種の問題に遭遇するのはおそらくこのときだけです。

simple/lib/CMakeLists.txt

add_library(TestLib TestLib.cxx)

独自のライブラリを作成するには、ライブラリに名前を付けて、それから作成されたすべてのファイルをリストします。簡単です。foo.cxxコンパイルするために別のファイルが必要な場合は、代わりにを記述しadd_library(TestLib TestLib.cxx foo.cxx)ます。これは、たとえば、他のディレクトリにあるファイルでも機能しますadd_library(TestLib TestLib.cxx ${CMAKE_SOURCE_DIR}/foo.cxx)。後でCMAKE_SOURCE_DIR変数について詳しく説明します。

これで実行できるもう1つのことは、共有ライブラリが必要であることを指定することです。例:add_library(TestLib SHARED TestLib.cxx)。恐れる必要はありません。ここでCMakeがあなたの人生を楽にし始めます。共有されているかどうかにかかわらず、この方法で作成されたライブラリを使用するために処理する必要があるのは、ここで指定した名前だけです。このライブラリの名前はTestLibになり、プロジェクトのどこからでも参照できます。CMakeはそれを見つけます。

依存関係をリストするより良い方法はありますか? 間違いなくはい。これについて詳しくは、以下をチェックしてください。

simple/lib/TestLib.cxx

#include <stdio.h>

void test() {
  printf("testing...\n");
}

simple/lib/TestLib.h

#ifndef TestLib
#define TestLib

void test();

#endif

simple/src/CMakeLists.txt

# Name the executable and all resources it depends on directly
add_executable(Tutorial tutorial.cxx)

# Link to needed libraries
target_link_libraries(Tutorial TestLib)

# Tell CMake where to look for the .h files
target_include_directories(Tutorial PUBLIC ${CMAKE_SOURCE_DIR}/lib)

コマンドadd_executable()はとまったく同じように機能しますが、add_library()もちろん、代わりに実行可能ファイルが生成されます。この実行可能ファイルは、などのターゲットとして参照できるようになりましたtarget_link_libraries()。tutorial.cxxはTestLibライブラリにあるコードを使用するので、次のようにCMakeを指すようにします。

同様に、ソースと同じディレクトリにないソースに含まれadd_executable()ている.hファイルは、何らかの方法で追加する必要があります。コマンド用でない場合、チュートリアルのコンパイル時に見つかりません。そのため、#includesを検索するために、フォルダー全体がインクルードディレクトリに追加されます。すべての実行可能ファイルに対してグローバルに設定するため、ターゲットを指定する必要がないことを除いて、同様に機能するコマンドが表示される場合もあります。もう一度、CMAKE_SOURCE_DIRについては後で説明します。target_include_directories()lib/TestLib.hlib/include_directories()

simple/src/tutorial.cxx

#include <stdio.h>
#include "TestLib.h"
int main (int argc, char *argv[])
{
  test();
  fprintf(stdout, "Main\n");
  return 0;
}

「TestLib.h」ファイルがどのように含まれているのかに注意してください。完全なパスを含める必要はありません。CMakeは、のおかげですべてを裏で処理しtarget_include_directories()ます。

技術的にはあなたがなしで行うことができ、このような単純なソースツリーに言えば、CMakeLists.txt下のlib/src/、ちょうどのようなもの追加することadd_executable(Tutorial src/tutorial.cxx)にしsimple/CMakeLists.txt。それはあなたとあなたのプロジェクトのニーズ次第です。

CMakeを適切に使用するために他に知っておくべきことはありますか?

(あなたの理解に関連するAKAトピック)

パッケージを見つけて使用するこの質問への答えは、私がこれまでにないほどよく説明しています。

変数と関数の宣言、制御フローの使用など:CMakeが提供する必要があるものの基本を説明するこのチュートリアルをチェックしてください

CMake変数:たくさんありますので、正しい道に進むためのクラッシュコースを次に示します。CMake wikiは、変数や表面上は他のものについてのより詳細な情報を入手するのに適した場所です。

ビルドツリーを再構築せずに一部の変数を編集することができます。これにはccmakeを使用します(CMakeCache.txtファイルを編集します)。c変更が完了したらonfigureを実行gし、更新された構成でmakefile を列挙することを忘れないでください。

以前に参照したチュートリアルを読んで、変数の使用について学習しますが、簡単に言えば set(<variable name> value)、変数を変更または作成します。 ${<variable name>}それを使用する。

  • CMAKE_SOURCE_DIR:ソースのルートディレクトリ。前の例では、これは常に/simple
  • CMAKE_BINARY_DIR:ビルドのルートディレクトリ。前の例では、これはと同じですがsimple/build/cmake simple/などのフォルダから実行した場合、そのビルドツリー内のfoo/bar/etc/すべての参照CMAKE_BINARY_DIRはになり/foo/bar/etcます。
  • CMAKE_CURRENT_SOURCE_DIR:現在のディレクトリCMakeLists.txtです。つまり、全体が変化します。これをsimple/CMakeLists.txtyields /simpleから出力し、simple/src/CMakeLists.txtyields から出力します/simple/src
  • CMAKE_CURRENT_BINARY_DIR:あなたはアイデアを得ます。このパスは、ビルドがあるフォルダだけでなく、現在のCMakeLists.txtスクリプトの場所にも依存します。

なぜこれらが重要なのですか?ソースファイルは明らかにビルドツリーにはありません。target_include_directories(Tutorial PUBLIC ../lib)前の例のようなものを試した場合、そのパスはビルドツリーからの相対パスになります。つまり${CMAKE_BINARY_DIR}/lib、のようになり、内部を調べますsimple/build/lib/。そこには.hファイルがありません。多くてもあなたは見つけるでしょうlibTestLib.a${CMAKE_SOURCE_DIR}/lib代わりにしたいです。

  • CMAKE_CXX_FLAGS:コンパイラー(この場合はC ++コンパイラー)に渡すフラグ。注目に値するのはCMAKE_CXX_FLAGS_DEBUG、がCMAKE_BUILD_TYPEDEBUGに設定されている場合に代わりに使用されることです。これらのようなものがあります。CMake wikiをチェックしください。
  • CMAKE_RUNTIME_OUTPUT_DIRECTORY:ビルド時にすべての実行可能ファイルを配置する場所をCMakeに指示します。これはグローバル設定です。たとえば、これをに設定してbin/、すべてをきちんと配置できます。EXECUTABLE_OUTPUT_PATH似ていますが、つまずいた場合に備えて非推奨です。
  • CMAKE_LIBRARY_OUTPUT_DIRECTORY:同様に、すべてのライブラリファイルを配置する場所をCMakeに指示するグローバル設定。

ターゲットのプロパティ:実行可能ファイルまたはライブラリ(またはアーカイブ...アイデアが得られます)の1つのターゲットのみに影響するプロパティを設定できます。これを使用する良い例を示します(set_target_properties()

ソースをターゲットに自動的に追加する簡単な方法はありますか? GLOB使用して、特定のディレクトリ内のすべてを同じ変数の下にリストします。構文例はFILE(GLOB <variable name> <directory>/*.cxx)です。

異なるビルドタイプを指定できますか?はい。ただし、これがどのように機能するか、またはこれの制限についてはわかりません。おそらくいくつかのif / then'ningが必要ですが、CMakeはCMAKE_CXX_FLAGS_DEBUG、たとえばのデフォルトなど、何も設定せずに基本的なサポートを提供します。CMakeLists.txtファイル内からビルドタイプを設定したりset(CMAKE_BUILD_TYPE <type>)、適切なフラグを使用してコンソールからCMakeを呼び出したりすることができますcmake -DCMAKE_BUILD_TYPE=Debug

CMakeを使用するプロジェクトの良い例はありますか?ウィキペディアには、CMakeを使用するオープンソースプロジェクトのリストがあります。これまでのところ、オンラインチュートリアルは私にとって失望に過ぎませんでしたが、このStack Overflowの質問には、かなりクールで理解しやすいCMakeの設定が含まれています。一見の価値があります。

コードでCMakeからの変数を使用する:これは、簡単で汚い例です(他のチュートリアルから適応)。

simple/CMakeLists.txt

project (Tutorial)

# Setting variables
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 1)

# Configure_file(<input> <output>)
# Copies a file <input> to file <output> and substitutes variable values referenced in the file content.
# So you can pass some CMake variables to the source code (in this case version numbers)
configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_SOURCE_DIR}/src/TutorialConfig.h"
)

simple/TutorialConfig.h.in

// Configured options and settings
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

CMakeによって生成された結果ファイルsimple/src/TutorialConfig.h

// Configured options and settings
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 1

これらを上手に使用すると、ライブラリをオフにするなどのクールなことができます。遅かれ早かれ、大規模なプロジェクトで非常に役立つと思われる少し高度なものがいくつかあるので、このチュートリアルをご覧になることをお勧めします。

それ以外のものについては、Stack Overflowは特定の質問と簡潔な回答で溢れています。これは、初心者を除くすべての人にとって素晴らしいことです。


2
私はこの回答を受け入れていますが、他の誰かがより良い、より短い回答を書いた場合、それを選択します。私はそれを自分でやりますが、CMakeにはもう十分苦しんでいます。
leinaD_natipaC 2014

6
この素晴らしい仕事をありがとう。これがより多くの票を獲得することを願っています!:)
2015年

4
控えめに言っても、CMakeを使用すると、コンパイラー/ビルド環境に固有の個別の設定を維持する必要がなくなります。あなたは持っている1つの構成を、そしてそれは、(様々なバージョンの)Visual Studioの、コードブロック、無地のUnixのMakefile、および他の多くの環境で動作します。そのため、最初にCMakeを検討していました。Autoconf、MSVC 2005/32ビット、およびMSVC 2010/64ビットの構成を同期させることは、大きな痛みになりました。そして、コツをつかんだら、ドキュメントの生成、テスト、パッケージ化など、クロスプラットフォームの方法でさらに多くのことを追加しました。
DevSolar 2015

1
@DevSolar正しい。ウィキペディアよりもこの行が好きなので、よろしければ回答に追加します。ただし、CMakeを正しく使用してその効果を得る方法については、何にも当てはまりません。これは、何が起こっているのかを知ることができるということです。
leinaD_natipaC 2015

1
@RichieHH例に従って、Makefileを使用するように最初にCMakeを構成し、次にCMakeを使用してプロジェクトのビルドに必要なファイルを生成します。最後に、ここでの作業が完了しているため、CMakeについて心配する必要はありません。つまりmake、プロジェクトを作成するために、今後bashで使用する必要があるという意味で、Makefileに「心配」していることになります。
leinaD_natipaC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.