ソフトウェアまわりの備忘録

研究室で培ったソフトウェアの知識を貯めておく備忘録。

Makefileの改造計画(第一回)

Makefileで苦労した人は多いはず

Linuxにおいてプログラムをコンパイルする際に必要となるMakefile。階層と依存関係を自動的に解決するようなMakefileを作るのは以外に難しいです。何年もこいつを書いてますが未だに苦戦します。ただただコンパイルルールを書くだけなのに以外にクセが強く奥深いです。まわりの人間もMakefileが嫌いとか言ってるやつ結構います。

それでも長い時間(数ヶ月とか)かけて自分の理想に近いMakefileを作りあげることができました。しかしこれを1コマで説明してしまうと複雑だと思われるので、複数回に分けて順に紹介していきます。

今後の掲載予定とソフトウェア環境

現在考えているのは、

  • Makefileの改造計画(今回)
  • 依存関係の自動解決(ヘッダーファイルの依存関係も考慮
  • 多段Makefileの活用(ソースファイルが複数ディレクトリに分かれてる場合)
  • バイナリファイルの整理(odjsディレクトリにまとまる)
  • (番外編)プリコンパイルヘッダによるコンパイルの高速化

です。ただし、多段Makefileやバイナリファイルの整理あたりは説明が多くなりそうなのでさらにページを分割するかもしれません。

Makefileの基本事項を一通り説明する前に私の開発環境(ソフトウェア)を晒しておきます。

  • OS: Ubuntu12.04 LTS
  • GNU Make3.81
  • gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

ハードウェアは仮想環境(VMware)でも動作しているのでそれほど関係ないでしょう。計算速度を図ることが目的でもないためCPUとかメモリ容量等も省きます。

さて、ベースとなるMakefileは以下の通り

main.cppとsample.cppをコンパイルするMakefile

GCC    = g++
CFLAGS = -O2 -Wall -Wextra
SRCS   = main.cpp sample.cpp
TARGET = main
OBJS   = $(SRCS:.cpp=.o)

.cpp.o:
	$(GCC) $(CFLAGS) -c $< -o $@

$(TARGET): $(OBJS)
	$(GCC) $(CFLAGS) -o $@ $+

default: $(OBJS) $(TARGET)

clean:
	$(RM) $(OBJS) $(TARGET)

私が使っている基本点なMakefileの雛形です。コメントいただければ各部の動作の詳細をお答えしますが、多くのサイトで解説されているので割愛します。このMakefile中のSRCSにソースファイルを手動で追加していけば基本的にコンパイルできます。

しかし、ファイル数が10,20,100...となってそんな面倒なことやってられません・・・ってことでwildcardを使ったりするわけです。さらにヘッダーファイルのインクルードや自作ライブラリのリンク、ソースファイルが階層ごとに散らかっていたり、もうとにかく大変です。

それらを次回以降、順次解決していきます。