9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【初心者向け】0から分かるMake・CMake

Last updated at Posted at 2024-03-19

はじめに

MakeやCMakeは様々なプロジェクトで使われている,c/c++コードのコンパイルを手助けしてくれる基盤技術です.
でも初心者には取っつきにくいですよね.チュートリアル通りにやったらなんか上手くいったけど,何やってるかよく分かんない!だから自分なりに変更できないし,エラーが出ても対処できない…ってことありませんか?(私はこれまでずっとそうでした…)
個人的にプロジェクトを立ち上げるにあたりMakeやCMakeについて初めてちゃんと知ったので,備忘録をかねてまとめておきます.同じ状況の初心者の助けになればと思います.

Makeとは?なぜ使うの?

ソースファイルが1つだけの時,そのコンパイルはごく簡単です.

g++ main.cpp -o main

これでmainという実行ファイルが生成されます.

では次のようにもっとたくさんのファイルがある時にはどうなるでしょう?

  • ソースファイル
    • main.cpp
    • file1.cpp
    • file2.cpp
  • ヘッダファイル
    • file1.hpp
    • file2.hpp

この場合,コンパイルのコマンドは次のようになります.

g++ -c main.cpp -o main.o
g++ -c file1.cpp -o file1.o
g++ -c file2.cpp -o file2.o
g++ main.o file1.o file2.o -o main

ちょっと面倒ですねー…ファイルが増えたりコンパイラオプションを追加したりすることになったら,もっと面倒です.

そこで活躍するのがMakeです.上記のファイル一式をMakeでコンパイルにはどうすればいいのか見てみましょう.MakeではまずMakefileいう名前のファイルを用意し,その中に次のように記載します.

SRC = main.cpp file1.cpp file2.cpp # source files
OBJ = $(SRC:.cpp=.o) # object files

CXX = g++ # compiler
CXXFLAGS = -Wall -std=c++11 # compile options (flags)

main: $(OBJ)
  $(CXX) $(CXXFLAGS) -o main $(OBJ) # command to generate exe file

# How the object files are related
main.o: main.cpp file1.hpp file2.hpp
file1.o: file1.cpp file1.hpp
file2.o: file2.cpp file2.hpp

# clean
clean:
  rm -f $(OBJ) main

ここで中身を理解する必要はありませんが,大体の感じは見て分かると思います.設定を記述すれば,Makeがコンパイルのための複雑なコマンドを生成してくれるのです.
Makefileが作成できたら,次のコマンドを打ちます.

make

これだけです.ずいぶん楽になりましたね.

Makeを使うことの利点は次のようにまとめられます.

  • 複雑なコンパイルコマンドを入力する必要がない
  • ファイルが追加された場合はMakefileに追記すればいい
  • コンパイルオプションを変更する場合はMakefileを変更すればいい

加えて,Makeには変更が加えられたファイルのみを再コンパイルしてくれます.従ってたくさんのファイルがある場合には普通にコンパイルするよりも速く済むという大きな利点もあります.

ちなみに,このようにコンパイルの手助けをしてくれる仕組みのことを(特にCMakeの文脈で)ビルドシステムと呼びます.CMakeのほかに,MSBuild(Microsoft Build engine)やNinjaもビルドシステムの一種です.

CMakeとは?なぜ使うの?

これまでMakeを使うとコンパイルが楽になることを見てきましたが,Makeで十分コンパイルが楽になるならなぜCMakeも必要なのでしょうか?

実はMakeのみを使ったプロジェクトには次のような懸念事項があるんです.

  • 世の中には他にもビルドシステムがあり,それぞれに適した設定ファイル(MakeでいうMakefile)が必要です.提供するプロジェクトの他のユーザーがMakeではなくMSBuildやNinjaを使いたい場合には,それぞれに適した設定ファイルを用意する必要があります.
  • ビルドシステムの設定ファイルは複雑で,独特な記法を採用していることが多いです.上記のMakefileの例も初見じゃよく分かんないですよね.

特に最初の点はチーム開発の際に問題となります.だってファイル追加するだけで全部のビルドシステム用の設定ファイルを書き換えるわけにいかないですよね.

CMakeはこういった問題を解決してくれます.CMakeの機能を端的にいえば「ユーザーが指定したビルドシステムが使う設定ファイルを用意する」ことです.例えばユーザーがMakeを使いたいならCMakeはMakefileを生成してくれるということですね.

CMakeを使うには,CMakeLists.txtという設定ファイルを用意します.その中身は先ほどのプロジェクトの例では次のようになります.

cmake_minimum_required(VERSION 3.10)

project(MyProject VERSION 1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_executable(main main.cpp file1.cpp file2.cpp)

さっきのMakefileに比べてめっちゃ簡単になってますよね!

CMakeLists.txtが準備できたら,次のコマンドを打ちます.

cmake -S . -B build

引数-Spath-to-sourceを意味しており,CMakeLists.txtを含むソースファイル一式が含まれたディレクトリへのパスを指定します.-Bpath-to-buildを意味しており,ビルドシステム用の設定ファイルが生成される場所を指定します.上記のコマンドを打てば,build/Makefilesが生成されるわけです.
ちなみに,よく次のように紹介されることもありますが,これも同じことをしています.

mkdir build
cd build
cmake ..

この場合だと一度buildディレクトリを生成し,そこに移動してから,1階層上のCMakeLists.txtを参照しています.先述の方法の方が端的で良いと思うのですが,CMakeのバージョンが古い場合には-S-Gを使うことができず,このやり方しかできないみたいです.

どのビルドシステムを使うかは,引数-Gで指定します.-Gはビルドシステムへの設定ファイルを生成する役割を持つCMake Generatorを意味しています.例えば,

cmake -S . -B build -G "Unix Makefiles"

はMakeが使うMakefileを生成しますし,

cmake -S . -B build -G "Visual Studio 17 2022"

はMSBuildが使うVisual Studio 2022のプロジェクトファイル一式を生成しますし,

cmake -S . -B build -G "Ninja"

はNinjaが使うbuild.ninjaファイルを生成します.ご自身の環境でどのビルドシステムが使えて,-Gに何を渡せばいいかは,cmake --helpで確認できます.

引数-Gは任意です.-Gが渡されなかった場合,CMakeはプラットフォームの状態に応じて決められたデフォルトのビルドシステムを採用します.現在のデフォルトはcmake --helpで確認できます.

CMakeを導入すれば,

  • 設定ファイル(CMakeLists.txt)の記述が楽になる
  • プロジェクトをプラットフォームに依存しない形にできる

ということがお分かり頂けたのではないでしょうか.CMakeLists.txtファイルさえ作ってしまえば,ユーザーがどのOS,どのビルドシステムを使っていたとしても対応できちゃうんです!

ワークフロー

では最後にCMakeとMakeを使ったコンパイルの手順を確認しておきましょう.最終的なコマンドは次のようになります.

cmake -S . -B build -G "Unix Makefiles" # build/Makefileを生成
cd build # buildディレクトリへ移動
make # 生成されたMakefileを使って実行ファイルを生成

もっと簡単に,こんな風にコンパイルすることもできます.

cmake -S . -B build -G "Unix Makefiles"
cmake --build build

この場合Makeは呼び出しませんでしたが,cmake --build buildによってCMakeが自動的にMakeを呼び出し,実行ファイルの生成までやってくれます.

参考

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?