0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Professional CMake: A Practical Guideの無料部分を読む ~その3~

Posted at

PROFESSINAL CMAKE : A PRACTICAL GUIDEとは

CMake参考書紹介(2022年時点)という記事で,この電子書籍を読んでクロスプラットフォームの環境構築ができたということが書いてありました.
これを受けて,試しに無料で公開されている部分を読んで要約してみたというものです.
この本は全部で7パートから構成されており,そのうち1パート目が無料で公開されています.
その無料で公開されている部分の各チャプターに何が書いてあるのかをメモの代わりに要約しています.
概要を理解し読む気を起こすための記事なので,きちんとした内容は実際にこの公開されているものを読みに行ってください.

その1
その2

その3

その3では,Chapter4をまとめます.
ここでは,CMakeのライブラリについて説明しています.

Chapter 4. Building Simple Targets

以前の章では,add_executable()を使ってシンプルなビルドをする例を示した.
この賞では,この関数にオプションを追加して様々なプラットフォームに対応する方法を説明する.

CMakeの特徴はライブラリのリンクを管理できることだ.
static, shared, module, frameworkなどのライブラリをサポートしている.
このChapterでは,主にそれらの機能を説明する.

4.1 Executables

以下がadd_executable()のすべてのコマンドだ.

add_executable(targetName [WIN32] [MACOSX_BUNDLE]
                [EXCLUDE_FROM_ALL]
                source1 [source2 ...]
)
  • WIN32
    Windows GUIアプリを作成する際のコマンドである.
    なので実際,WinMain()が実行ファイルになる.
    他のプラットフォームでは,WIN32のコマンドは無視される.

  • MACOSX_BUNDLE
    これは,MacOSやIOSをビルドするためのコマンドである.
    CMakeは,基本的なバンドルのためのInfo.plistを生成する.
    詳細は,Section 25.2で説明する.
    他のプラットフォームでは,MACOSX_BUNDLEは無視される.

  • EXCLUDE_FROM_ALL
    基本的には,すべてのターゲットがビルドされる.
    しかし,デベロッパーツールなどたまにしか必要ないものもある.
    その場合,このコマンドを付けるとビルドから除外される.

加えて,実行ファイルを作るのではなく既存の実行ファイルに一種の参照を加えることもできる.
これについては,Chapter 19で説明する.

以下は本Chapterの例である.

# Main GUI app, built as part of the default "ALL" target
add_executable(MyApp WIN32 MACOSX_BUNDLE
main.cpp
widgets.cpp
)
# Helpful command-line tools, not built by default
add_executable(checker checker.cpp EXCLUDE_FROM_ALL)
add_executable(reporter reporter.cpp EXCLUDE_FROM_ALL)

以下の命令では,MyAppのみビルドされる.

cmake --build /path/to/build

以下の命令では,checkerもビルドされる.

cmake --build /path/to/build --target checker

4.2 Defining Libraries

CMakeでは,add_library()を使ってライブラリを定義する.
これにより,環境に寄らず同じコードでライブラリを定義できる.

add_library(targetName [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...]
)

targetNameとEXCLUD_FROM_ALLの働きはadd_executable()と同じ働きである.
対応するライブラリは,static, shared, moduleの三種類である.

  • STATIC
    Windowsでは,targetName.lib, Unix系ではlibtargetName.aが出力される

  • SHARED
    Windowsでは,targetName.dll, Mac系では,libtargetName.dylib,Unix系ではlibtargetName.soが出力される.
    詳しくは,Section 25.3 "Frameworks"で説明する.

  • MODULE
    直接リンクするのではなく,実行時に動的にロードされるコンポーネント.

ライブラリの種類は,指定する必要はない.
特に必要なければ指定せず,CMakeコマンドの引数にすべきだ.
以下で,-DBUILD_SHARED_LIBS=YESとするとSHARDになる.
そうでなければ,STATICになる.

cmake -DBUILD_SHARED_LIBS=YES -B /path/to/build

4.3 Linking Targets

CMakeでは,ライブラリのリンク関係を記述することができる.
その記述例は以下の通りである.

target_link_libraries(targetName
<PRIVATE|PUBLIC|INTERFACE> item1 [item2 ...]
[<PRIVATE|PUBLIC|INTERFACE> item3 [item4 ...]]...
)

ここでは,ライブラリAとBの関係性を例に挙げて説明する.

  • PRIVATE
    プライベートは,AはBを内部実装して使うことを意味する.
    (おそらく,C++における内部結合の使い方である)

  • PUBLIC
    パブリックは,AはBを内部的に使うだけでなく,Bをインターフェイスとしても使う.
    この場合,AはBに完全に依存する.
    (おそらく,C++の外部結合の使い方である)

  • INTERFACE
    インタフェイスは,AがBを内部的に使うのではなく,インターフェイスのみ使う.

後のChapterで他にもtarget_…()というコマンドが出てくる.
これらは,依存関係の追加情報として,ヘッダーのパス,コンパイルの定義などのオプションを追加できる.
これらの機能は,CMake 2.8.11 - 3.2で追加された.

3.12以前のCMakeを使う場合は,ライブラリのディレクトリに縛りがあるので注意が必要だ.

4.4 Linking Non-targets

ここまでのCMakeは,CMake内でリンクをしてきた.
一方,CMakeのtarget_link_libraries()はさらに柔軟にライブラリのリンクができる.

  • Full path to a library file
    CMakeはリンカーコマンドにライブラリファイルを追加する.
    これにより,ライブラリのファイルが変わった時CMakeはそのターゲットを自動で再リンクする.
  • Plain library name
    パスを指定しないで,ライブラリ名を指定するとそのライブラリを探しに行く.
    これは推奨されないときもあり,詳細はSection18.1で説明する.
  • Link flag
    -で始まる-lか-framework以外は,リンカコマンドに追加するフラグとして働く.
    使わない方が良い.

4.5 Old-style CMake

古いCMakeの解説なので省略する.
使用しない方がいいらしい.

4.6 Recommended Practices

ターゲット名はプロジェクト名と関係する必要はない.
また,ターゲット名とプロジェクト名はほぼ変わらないので変数にしない方が良い.
(変えるとそれに依存するものが影響を受ける)

以下に悪い例と良い例を示す

# BAD: Don't use a variable to set the project name, set it directly
set(projectName MyExample)
project(${projectName})
# BAD: Don't set the target name from the project name
add_executable(${projectName} ...)
# GOOD: Set the project name directly
project(MyProj)
# BAD: Don't set the target name from the project name
add_executable(${PROJECT_NAME} ...)
# GOOD: Set the project name directly
project(MyProj)
# GOOD: Target name is independent of the project name
add_executable(MyThing ...)

ライブラリのターゲットにlibと付けるとWindows以外の環境で最初にlibとついてダサくなる.
(liblibsomething...みたいなw)

STATICとSHAREDのコマンドは,そのライブラリがどちらかで決まり出ない限り使わない.
ビルド時のBUILD_SHARED_LIBSで指定できる.

古いCMake構文だとすべてpublicになっていたので,target_link_libraries()を呼ぶときはpoblic, private, interfaceを指定する.
このキーワードを記述すると,後にターゲット間の依存関係をどう処理するかに強い影響を与える.

感想

一部,なじみの無い概念がでてきてわからなかった(INTERFACEの概念など).
わかる人で間違えていたら遠慮なく指摘してほしい.

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?