5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

長野高専Advent Calendar 2021

Day 25

CMakeでお手軽ビルド環境構築

Last updated at Posted at 2021-12-24

はじめに

この記事は長野高専 Advent Calendar 2021の25日目の記事です。

改めてこんにちは、しゅんです。3日目ぶりの投稿です。当初は書く予定がありませんでしたが、アドベントカレンダーなのに25日に記事がないのもさみしいので投稿します。

さて皆さんはC言語でプログラミングをするとき、どのようにソースコードのビルドを行っていますか?C言語を学校で習った方はgccコマンドでビルドを行っているかもしれません。しかしgccコマンドのみを使用した場合、ソースコードが複数あった場合や多数のコンパイラオプションを使用しているときに非常にコマンドが長くなったり複数のコマンドを実行する必要があったりします。

今回はこれらの煩雑な作業を軽減することができるCMakeを紹介します。CMakeを用いてビルドの効率を上げ、開発速度を上げていきましょう!

CMakeとは

Wikipediaにはこのように書いてあります。

CMakeは、コンパイラに依存しないビルド自動化のためのフリーソフトウェアであり、様々なオペレーティングシステムで動作させることができる。CMakeは階層化ディレクトリや複数のライブラリを利用するアプリケーションをサポートするよう設計されている。実際のビルドにおいては、make、Xcode、Visual Studioのようなネイティブのビルド環境が利用される。CMake自身は最小限の依存関係を持つよう設計されており、ビルドするにはC++コンパイラのみを必要とする。

ここに書いてあるようにCMakeはビルド自動化のためのソフトウェアです。実はCMake自体はビルドを行いません。実際にビルドする場合はCMakeによって作られたビルド環境を使用してビルドを行います。makeコマンドやVisual Studioは聞いたことがある人も多いと思います。しかしこれらのビルド環境は特定のプラットフォームのみのサポートのことが多く、多数のOSに対応させることは難しいです。そこでCMakeというマルチプラットフォームなソフトウェアを使用することによってそれぞれのビルド環境の差異を吸収し、簡単にビルド環境のマルチプラットフォーム化ができます。

CMakeによるビルドの流れ

まずCMakeにはCMakeLists.txtというファイルが必要です。このファイルにはどのようなファイルをコンパイルするかやライブラリ、オプションなどの各種設定を記述します。
CMakeLists.txtを書いたらcmakeコマンドを使用してビルド環境を構築します。このときどのようなビルド環境を使用するかを設定することができ、makeNinjaVisual Studioなど様々なビルド環境を選択することができます。私の手元のmacOS環境では以下のビルド環境が使用できるようです。

$ cmake -G
CMake Error: No generator specified for -G

Generators
* Unix Makefiles               = Generates standard UNIX makefiles.
  Ninja                        = Generates build.ninja files.
  Ninja Multi-Config           = Generates build-<Config>.ninja files.
  Watcom WMake                 = Generates Watcom WMake makefiles.
  Xcode                        = Generate Xcode project files.
  CodeBlocks - Ninja           = Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles  = Generates CodeBlocks project files.
  CodeLite - Ninja             = Generates CodeLite project files.
  CodeLite - Unix Makefiles    = Generates CodeLite project files.
  Eclipse CDT4 - Ninja         = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files.
  Kate - Ninja                 = Generates Kate project files.
  Kate - Unix Makefiles        = Generates Kate project files.
  Sublime Text 2 - Ninja       = Generates Sublime Text 2 project files.
  Sublime Text 2 - Unix Makefiles
                               = Generates Sublime Text 2 project files.

ビルド環境ができれば後は好みのビルド環境のコマンドを使用してビルドを行えます。また、cmakeコマンド自体にもビルドのコマンドがあり、それぞれのビルド環境専用のコマンドを実行しなくともビルドすることができます。

CMakeのインストール

CMakeは各OSのパッケージマネージャにてインストールすることができます。Windowsの場合はscoopを使用してインストールすることもできますし、公式サイトからダウンロードすることも可能です。

CMakeを使ってみる

それではCMakeを使ってみましょう。今回は単純な3ファイル構成のプロジェクトを使用して解説します。先にソースコード全文を掲載します。

add.h
#pragma once

int add(int, int);
add.c
#include "add.h"

int add(int x, int y) { return x + y; }
main.c
#include <stdio.h>

#include "add.h"

int main(void) {
  int x = 3;
  int y = 5;

  printf("%d + %d = %d\n", x, y, add(x, y));

  return 0;
}

それではCMakeLists.txtを作りましょう。

CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(hello-cmake LANGUAGES C)

add_executable(main main.c add.c)

cmake_minimum_requiredはこのCMakeLists.txtが必要としているCMakeのバージョンを指定します。あまり新しい文法を使わないのであれば3.1あたりを指定しておけば問題ありません。

projectはプロジェクト名や使用する言語、バージョンなどのプロジェクト全体の設定を行います。
hello-cmakeがプロジェクト名、LANGUAGES Cが言語の指定です。詳細なオプションに関しては公式リファレンスを参照してください。
add_executableで実行形式ファイルのビルドを設定します。はじめの名前が出力ファイル名、後がソースコードのパス名です。add_executableや後に紹介するadd_libraryなどで設定するビルド対象のことをCMakeではターゲットと言います。複数のターゲットがある場合、CMakeでビルドするときにターゲットを絞ってビルドすることが可能になります。

CMakeLists.txtができたら後はビルドするだけです。先程も言いましたが、CMake自体はビルドを行わないため、まずビルドツリーを構築する必要があります。

cmake <CMakeLists.txtが存在するディレクトリパス>でビルドツリーを構築できます。デフォルトではワーキングディレクトリ上にビルドツリーを構築するのでcmake .みたいにするとソースコードがある場所にビルドツリーができてしまいやり直したいときなどに非常に面倒です。そこでbuild/のようなディレクトリを追加で作り、そこにビルドツリーを構築しましょう。CMakeの-Bオプションを使用することでビルドツリーの構築先を指定できるため、cmake . -B buildというように実行するのがおすすめです。

$ cmake . -B build
-- The C compiler identification is AppleClang 13.0.0.13000029
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/shun_shobon/tmp/hello-cmake/build

このとき-Gオプションでビルド環境の指定をできます。macOSやLinuxではデフォルトでUnix Makefilesが使用されますが、Ninjaなどが使用したい場合はお好みで設定してください。

ビルドツリーが構築できたらあとはビルドするだけです。ビルドはビルドツリー上でビルド環境独自のコマンドを入力してもビルドできますし、CMake上からもビルドできます。CMake上でビルドする場合はcmake --build <ビルドツリーへのパス>でビルドできます。

$ cmake --build build
[ 33%] Building C object CMakeFiles/main.dir/main.c.o
[ 66%] Building C object CMakeFiles/main.dir/add.c.o
[100%] Linking C executable main
[100%] Built target main

なお、デフォルトではターゲット全てがビルドされますが、特定のターゲットのみにしたい場合は-t <ターゲット名>で行えます。

ビルド成果物はビルドツリー下に生成されるのでお好みで実行してください。

$ ./build/main
3 + 5 = 8

コンパイルオプションを設定する

コンパイルオプションを設定したい場合はadd_compile_optionsを使用します。

cmake_minimum_required(VERSION 3.1)
project(hello-cmake LANGUAGES C)

add_compile_options(-Wall -O3)

add_executable(main main.c add.c)

ライブラリを作る

複数の実行ファイルがある場合、いちいちadd_executableの後にソースコードを並べるのは効率が悪いです。add_libraryを使えばライブラリを作成することができ、target_link_librariesで各種ターゲットにライブラリをリンクできます。

cmake_minimum_required(VERSION 3.1)
project(hello-cmake LANGUAGES C)

add_compile_options(-Wall -O3)

add_library(add add.c)

add_executable(main main.c)
target_link_libraries(main add)

終わりに

CMakeを使えばプラットフォームに依存しないビルド環境を作ることができ、保守性も高まります。CMakeLists.txtのコマンドは非常に多く、今回はその一部を紹介しましたが、公式リファレンスに詳細が載っているため詳しく見たい方はそちらを参照してください。公式チュートリアルには多数のユースケースに向けたチュートリアルがあるためこちらを見ることもおすすめします。

5
1
2

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
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?