C++で静的ライブラリと動的ライブラリをビルドする方法!初心者向け解説
生徒
「C++でライブラリって、どうやって作ったり使ったりするんですか?」
先生
「ライブラリには大きく分けて、静的ライブラリと動的ライブラリがあります。それぞれの作り方や使い方を理解すると、C++のプロジェクトが効率よく作れますよ。」
生徒
「静的ライブラリと動的ライブラリって何が違うんですか?」
先生
「簡単に言うと、静的ライブラリはプログラムに組み込まれて一つの実行ファイルになるもので、動的ライブラリは別ファイルとして実行時に読み込む仕組みです。それでは、順番に見ていきましょう!」
1. 静的ライブラリとは?
静的ライブラリ(.libや.aファイル)は、プログラムをビルドするときにリンクされ、実行ファイルに組み込まれます。例えば、図書館から本を借りて内容を自分のノートに書き写すイメージです。プログラム実行時にはライブラリは別に存在せず、全ての機能が実行ファイルに含まれます。
利点として、実行時に外部ファイルを必要とせず、配布が簡単です。一方で、ライブラリを更新すると、実行ファイルも再ビルドが必要になります。
2. 動的ライブラリとは?
動的ライブラリ(.dllや.soファイル)は、実行時に読み込まれる別ファイルです。例えるなら、必要なときに図書館から本を借りるようなイメージです。プログラム自体は小さく、ライブラリを共有できるので、複数のプログラムで同じライブラリを使えます。
利点は、ライブラリを更新しても実行ファイルの再ビルドが不要なことです。ただし、実行時にライブラリが存在しないと動作しません。
3. CMakeで静的ライブラリをビルドする方法
CMakeを使えば、簡単に静的ライブラリを作れます。以下は例です:
cmake_minimum_required(VERSION 3.10)
project(StaticLibExample)
set(CMAKE_CXX_STANDARD 17)
# 静的ライブラリを作成
add_library(my_static_lib STATIC
lib.cpp
lib.h
)
# 実行ファイルの作成
add_executable(main main.cpp)
target_link_libraries(main PRIVATE my_static_lib)
ポイントはadd_library(... STATIC)で静的ライブラリを指定することです。target_link_librariesで実行ファイルとリンクします。
4. CMakeで動的ライブラリをビルドする方法
動的ライブラリも同様にCMakeで作れます。SHAREDオプションを使います:
cmake_minimum_required(VERSION 3.10)
project(SharedLibExample)
set(CMAKE_CXX_STANDARD 17)
# 動的ライブラリを作成
add_library(my_shared_lib SHARED
lib.cpp
lib.h
)
# 実行ファイルの作成
add_executable(main main.cpp)
target_link_libraries(main PRIVATE my_shared_lib)
これで実行時にmy_shared_lib.dllやlibmy_shared_lib.soが使用されます。
5. 静的ライブラリと動的ライブラリの使い分け
プロジェクトの規模や配布方法によって使い分けます。小規模で単体配布する場合は静的ライブラリ、大規模で複数プログラムから共有する場合や更新頻度が高い場合は動的ライブラリが便利です。また、動的ライブラリはOS依存のファイル形式があるので、マルチプラットフォーム対応を考える場合は注意が必要です。
6. 注意点とポイント
- 静的ライブラリはリンク時に全て組み込まれるので実行ファイルが大きくなりやすいです。
- 動的ライブラリは実行時に見つからないとエラーになりますので、ライブラリパスの設定が必要です。
- CMakeを使うと、
STATICとSHAREDを切り替えるだけでビルド方法を簡単に変更できます。
これらを理解しておくと、C++で効率的にライブラリを作成・利用できるようになります。
まとめ
C++におけるライブラリのビルドと管理は、中規模以上の開発において避けては通れない非常に重要なテーマです。本記事では、静的ライブラリ(Static Library)と動的ライブラリ(Dynamic Library / Shared Library)の根本的な違いから、モダンなビルドツールであるCMakeを用いた具体的な構築手順までを詳しく解説してきました。
静的・動的ライブラリの性質を再確認
プログラムを開発する際、共通の機能を切り出して再利用可能にしたものがライブラリです。これを「どのタイミングで結合するか」によって、その後の運用コストやパフォーマンスが変わってきます。
- 静的ライブラリ(.lib / .a):ビルド時(リンク時)に実行ファイル(.exeなど)の中身としてコピーされます。実行ファイルさえあればどこでも動く「自己完結型」のプログラムを作りたい場合に最適です。ただし、ライブラリの一部を修正しただけでも、それを利用している全てのプログラムを再コンパイル・再リンクし直さなければならないという手間があります。
- 動的ライブラリ(.dll / .so):実行ファイルには「ライブラリの呼び出し口」だけを記録しておき、実際にプログラムが動き出した瞬間にメモリ上へ読み込まれます。複数のソフトで同じライブラリを共有できるため、ディスク容量やメモリの節約になります。また、ライブラリの不具合修正時に、DLLファイルを差し替えるだけで本体プログラムをいじらずにアップデートできるという強力なメリットがあります。
CMakeによるビルドの実践例
昨今のC++開発では、OS(Windows, Linux, macOS)を問わずにビルド定義を記述できるCMakeがデファクトスタンダードとなっています。今回の解説で登場したコードを、もう少し実践的な形で整理してみましょう。例えば、計算処理を行うライブラリを作成し、それをメインプログラムから呼び出す構成を考えます。
サンプルコード:静的ライブラリの定義 (CMakeLists.txt)
静的ライブラリとしてビルドする場合、add_libraryの第2引数にSTATICを指定します。これにより、ソースコードがコンパイルされた後、アーカイブ(固められた状態)として出力されます。
cmake_minimum_required(VERSION 3.10)
project(MyMathProject)
# C++17標準を使用する設定
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 1. 静的ライブラリ「math_static」を定義
# 複数のソースファイル(calc.cpp, util.cppなど)をまとめることも可能
add_library(math_static STATIC
src/calc.cpp
include/calc.h
)
# 2. 実行ファイルの作成
add_executable(app_main main.cpp)
# 3. 実行ファイルにライブラリをリンク
# これにより、app_mainの中にmath_staticの機能が取り込まれる
target_link_libraries(app_main PRIVATE math_static)
# インクルードパスを通す設定(ヘッダーファイルを見つけやすくする)
target_include_directories(math_static PUBLIC include)
サンプルコード:動的ライブラリの定義 (CMakeLists.txt)
一方で、動的ライブラリを作成する場合はSHAREDキーワードを使います。Windows環境でDLLを作成する際は、関数に__declspec(dllexport)を付けるなどのエクスポート制御が必要になる点に注意が必要ですが、CMake自体の記述は非常にシンプルです。
cmake_minimum_required(VERSION 3.10)
project(MySharedProject)
# 1. 動的ライブラリ「math_shared」を定義
add_library(math_shared SHARED
src/calc.cpp
include/calc.h
)
# 2. 実行ファイルの作成
add_executable(app_runner main.cpp)
# 3. リンク設定
target_link_libraries(app_runner PRIVATE math_shared)
エンジニアとしての使い分けの判断基準
「結局どちらを使えばいいの?」という疑問に対し、現場での判断基準を整理します。
| 項目 | 静的ライブラリ (STATIC) | 動的ライブラリ (SHARED) |
|---|---|---|
| 配布のしやすさ | ◎ 実行ファイル1つで済む | △ DLL/soファイルを同梱する必要がある |
| 実行速度 | ○ 呼び出しのオーバーヘッドが最小 | △ 起動時や呼び出し時に僅かなコスト |
| メンテナンス性 | △ 全体の再ビルドが必要 | ◎ ライブラリ単体の差し替えが可能 |
| ファイルサイズ | × プログラムごとに肥大化する | ◎ 共通化により全体サイズを削減できる |
初心者のうちは、環境構築のトラブルが少ない「静的ライブラリ」から始めるのが無難です。動的ライブラリは「パスが通っていない(DLLが見つからない)」といった実行時のエラーに悩まされることが多いためです。しかし、プラグイン機構を実装したり、巨大なフレームワークを扱うようになったりすると、動的ライブラリの柔軟性が不可欠になります。
生徒
「先生、ありがとうございました!静的ライブラリと動的ライブラリ、なんとなく『固めるか、別にするか』の違いだと分かってきました。でも、実際にビルドした時、実行結果には違いが出るんですか?」
先生
「いい質問ですね。プログラムの動作そのものは変わりませんよ。例えば、足し算をする関数をライブラリにしても、結果は同じです。見てみましょうか。」
[ビルド実行中...]
Generating build files...
Build optimized for C++17.
Linking math_static... done.
Linking app_main... done.
[プログラム実行結果]
$ ./app_main
Result: 10 + 20 = 30
(静的リンクなので、このファイル単体で動作しています)
生徒
「なるほど、中身は一緒なんですね。でも動的ライブラリの場合、もしDLLファイルを消しちゃったらどうなるんですか?」
先生
「その場合は、プログラムを起動した瞬間にOSが『ライブラリが見つかりません!』と怒って、エラーで終了してしまいます。これが動的ライブラリの注意点ですね。試しに共有ライブラリで実行してみると……」
$ ./app_runner
error: libmath_shared.so not found!
(動的ライブラリが見つからないため、起動に失敗しました)
生徒
「わあ、本当だ。実行ファイルだけあってもダメなんですね。配布するときは、ちゃんとセットにして渡さないといけないんだ。」
先生
「その通りです!逆に、静的ライブラリなら実行ファイルだけでどこでも動くから、初心者さんには最初は静的ライブラリがおすすめですよ。CMakeなら、STATICとSHAREDの文字を書き換えるだけで切り替えられるので、まずは両方試してファイルのサイズを比較してみるのも面白い勉強になります。」
生徒
「文字を1箇所変えるだけで仕組みが変わるなんて、CMakeって便利ですね!まずは静的ライブラリを作って、自分のツールをまとめてみます!」
先生
「その意気です。ライブラリ化ができるようになると、コードが整理されて、プログラミングがもっと楽しくなりますよ。頑張ってくださいね!」