2025-07-18
ビルドの自動化はもちろん、プロジェクトの全体構成を説明するにもMakefileは欠かせない存在である。識別子の意味などいつも忘れてしまうのでメモ。
以下、自作のC++クラスライブラリlibcppのMakefileです。
(libcpp GitHubはこちら)
| Shell | Makefile | GitHub Source |
CXX = g++
CC_DBG += -g -O2
#STRIP += -s
#CC_OPT += -D_GNU_SOURCE -D_USE_PGSQL -D_USE_MYSQL
CC_OPT += -D_GNU_SOURCE -D_USE_MYSQL
CC_OPT += -DLINUX -D_REENTRANT -D_FORTIFY_SOURCE=2 -fPIC -DPIC -fstack-protector-strong
CC_OPT += -Wformat -Werror=format-security -Wdate-time
CC_INC += -I/usr/local/include
CXXFLAGS += $(CC_DBG) $(CC_OPT) $(CC_INC)
SRCS = LFile.cpp LSocket.cpp LPgSQL.cpp LMySQL.cpp G.cpp LCgi.cpp
OBJS = ${SRCS:.cpp=.o}
DESTLIB = /usr/local/lib
DESTINC = /usr/local/include
all: .deps libcpp.a libcpp.so main.x
.deps:
$(CXX) -M $(CXXFLAGS) $(SRCS) main.cpp > $@
libcpp.a: $(OBJS)
ar rv $@ $?
ranlib $@
libcpp.so: $(OBJS)
$(CXX) -pthread -shared -Wl,--as-needed -Wl,-z -Wl,relro -Wl,-z -Wl,now -Wl,-soname -Wl,$@.1 -o $@.1.0 $^
# env LD_LIBRARY_PATH=`pwd` ./main.x
main.x: main.cpp libcpp.so.1.0
$(CXX) $(CXXFLAGS) -o $@ $^ -pthread -lm -lssl -lcrypto -lpq
clean:
rm -f *.o *.a *.so* *.x .deps
install: all
install libcpp.a $(DESTLIB)
install libcpp.so.1.0 $(DESTLIB)
ldconfig $(DESTLIB)
ln -f -s -r $(DESTLIB)/libcpp.so.1 $(DESTLIB)/libcpp.so
install -m 0644 libcpp.h $(DESTINC)
-include .deps
make
で、
依存関係ファイル.deps
スタティックライブラリlibcpp.a
シェアードライブラリlibcpp.so
テスト実行ファイルmain.x
を一度にビルドします。
それぞれのターゲットだけをビルドしたい場合そのターゲット名を指定。
例)make libcpp.so
ただしlibcpp.soは.depsに依存しているため、.depsのビルドが先に行われます。
make clean
で、すべての生成ファイルを削除。
sudo make install
で、
/usr/local/lib/libcpp.a,libcpp.so、/usr/local/include/libcpp.h
と、システムにインストールされます。
インストール前にローカルでテスト実行ファイルをテストするには
env LD_LIBRARY_PATH=`pwd` ./main.x
とする。スタティックリンクライブラリをテストする場合Makefileを
main.x: main.cpp libcpp.a
と修正する。
makeでビルド後ソースファイル(LCgi.cppなど)やインクルードファイル(.depsで定義)に変更がなければ、もう一度makeとしてもビルドは行われない。ソースを変更した場合そのファイルだけがコンパイルされ、実行ファイルのビルドが行われる。
libparsonやlibnkfのビルドMakefileではスタティックとシェアードでソースのコンパイルオプションを変えていたのでオブジェクトファイルも2通り定義したが、どうもシェアードのオプションでスタティック用のコンパイルをしてもリンク・実行に差し支え無さそうだったので、今回オブジェクトファイルは同じにしている(.oで統一、リコンパイルも不要)
以下、コンパイルオプション・Make識別子の説明
-O2:最適化レベル2オプション。コンパイル速度・オブジェクトサイズは大きくなる。
-fPIC:再配置可能とするオプション。シェアードライブラリビルドには必須。
$@:ターゲット名に変換される。
.deps: $(CXX) -M $(CXXFLAGS) $(SRCS) main.cpp > $@
では、$@ = .depsになる。
$?:依存関係リストのうちターゲットより変更時刻が新しいものだけ展開される。
libcpp.a: $(OBJS) ar rv $@ $?
では、たとえばLSocket.oだけがlibcpp.aより新しいなら、$? = LSocket.oとなる。.depsにより、LSocket.oはLSocket.cppに依存しているわけだから、LSocket.cppが変更されれば上記arが行われる。
$^:依存関係リストに常に変換される。
main.x: main.cpp libcpp.so $(CXX) $(CXXFLAGS) -o $@ $^ -pthread -lssl -lcrypto -lpq
では、$^ = main.cpp libcpp.so になる。
-include .deps:依存関係ファイル.depsを読み込む。読み込まないとヘッダファイルの変更などが行われても再コンパイルされない。-が重要で、これは対象ファイルが無い場合でもエラーとしない識別子。
-g -O2とするならinstallコマンドに-s(stripオプション)はつけてはならない。デバッグシンボルが消えてしまう。
※本記事内容の無断転載を禁じます。
ご連絡は以下アドレスまでお願いします★
マイクで喋った日本語をテキスト変換してOBS Studioにリアルタイムで表示する【2】
マイクで喋った日本語をテキスト変換してOBS Studioにリアルタイムで表示する【1】
Raspberry PI 2 bookworm 32bitでCanon IP4300プリンタ印刷する
【VMware】Apple silicon M2 MacでWindows11を無償で動かす
A4用紙タテ2ページ分をA3用紙ヨコ1ページに印刷するには
【Android】apkのインストールができたのにアプリ一覧に出ない場合
【Node.js】chrono-nodeを使用して自然言語を日付に変換する
CUDA13環境下でGPU使用版のllama.cppを導入しC++ライブラリを使う
CUDA13環境下でGPU使用版のllama-cpp-pythonを導入する
【Windows10】リモートデスクトップ間のコピー&ペーストができなくなった場合の対処法
CUDA13環境下でGPU使用版のPyTorchを導入する
Windows11+WSL2でUbuntuを使う【2】ブリッジ接続+固定IPの設定
【Apache】サーバーに同時接続可能なクライアント数を調整する
LinuxからWindowsの共有フォルダをマウントする
VirtualBoxの仮想マシンをWindows起動時に自動起動し終了時に自動サスペンドする
Googleファミリーリンクで子供の端末の現在地がエラーで取得できない場合
Windows11でMacのキーボードを使うには
【Linux】viエディタが文字化けする場合の対処法