* 6 大きなプロジェクトの管理
- まず、大きなソフトウエアは、それを書くことにお
いてもコンポーネントへの分割が重要となる。
- makeによる構築もそれに従う。コンポーネント毎の構
築を行うmakefileを作ることになる。そしてトップ
レベルにそれらmakefilesを管理するmakefileを置く。
- この手法を再帰的makeと呼ぶ。
- 再帰的makeはいくつか課題をもつ。
- それを回避するために、トップレベルのmakefileが
各コンポーネントディレクトリを調べることによっ
て、すべての構築処理を管理するという非再帰的
makeという手法もある。
- コンポーネント分割の他に、次のようなトピックが
ある。
- 複数バージョンの取扱い
- マルチプラットフォームの取扱い
- ディレクトリ構成の工夫
** 6.1 再帰的make
- 再帰はシェルスクリプトではなく、makeで書いたほ
うがよい。
- makeで書いた例
------
components := lib/a lib/c hoge piyo
all: $(components)
$(components):
$(MAKE) --directory=$@
------
- シェルスクリプトで書いた例
------
components := lib/a lib/c hoge piyo
all:
for d in $(components); \
do \
$(MAKE) --directory=$$d; \
done
------
- なぜか?
- 呼び出し元のmakeにエラーが返らない。
- 並列化ができない。
- 前提条件について、GNU makeは左から右へ実行して
いく。また、あるターゲットの前提条件が複数行に
かかれていたときどうなるかは実装依存である。前
提条件の実施順について構築上必須の部分があるな
ら、それにケアして前提条件を並べるべきである。
*** 6.1.1 コマンドラインオプション
- makeはMAKEFLAGS変数を通じて、下位のmakeにコマン
ドラインオプションを引き継ぐ。
- 一部のコマンドラインオプションは特別扱いとなる。
例えば、--touch、--just-print、--question。
- makeを呼ぶルール自体はPHONYなので、これらオプショ
ンでは実行されないのが基本。これを実行させるよ
うにmakeが振る舞う。
*** 6.1.2 値を渡す
- makeの間で値を渡すには環境変数を使う。
- makeのexport/unexport命令で制御する。
- --environment-overridesを使うと、下位のmakefile
で環境変数由来の変数に代入していても、それを無
視して環境変数の値を使う。
- overrideを使うと、--environment-overridesがあっ
たとしても、変数の代入を実行する。例。
------
override TMPDIR = ~/tmp
------
*** 6.1.3 エラー処理
- 下位のmakeのエラーは、上位へ伝搬し、トップの
makeの処理が止まる。
- --keep-goingをトップで指定しているなら、それは
全てのmakeに渡される。
*** 6.1.4 その他のターゲットの構築
- cleanとかinstallとかのPHONYなターゲットを再帰的
にするにはどう書くか。こう書く。
------
$(components):
$(MAKE) --directory=$@ $(TARGET)
$(if $(TARGET), $(MAKE) $(TARGET))
------
- これによって、任意のターゲットを再帰的に渡すこ
とができる。
*** 6.1.5 makefileの相互依存
- ヘッダファイルなどについてコンポーネント間で依
存関係が発生することがある。
- 特にコードジェネレータを使っている場合、先に一方
のコンポーネントを構築しないと、適切なハッダファ
イルが存在しないことになる。
- これはトップレベルで地道に依存関係を作り込むし
かない。
*** 6.1.6 コードの重複を回避する
- makefile間でのコードの重複を避けるには、共用ファ
イルをつくりincludeする。
- ちなみに、こういうファイルの拡張子は.mk。
** 6.2 非再帰的make
- 各componentのディレクトリには、component.mkを置
く。そこには、そのcomponentに関する変数定義とルー
ル定義をおこなう。
- トップレベルのmakefileはそれらをincludeする。ま
た、このmakefileには各componentからの情報を集積
する変数を定義しておく
- component.mkには、集積する変数に自分が定義した
ものを投入していく。
** 6.3 巨大システムのコンポーネント
- ビルドシステムの構成に関する一般則
- ソースとバイナリの置き場所は分けるべき。
- それぞれのディレクトリ構造をソースツリー・バ
イナリツリーと呼ぶ。
- リファレンスを運用すべき。
- リポジトリからチェックアウトした状態のソース
と、それをそのままビルドしたバイナリを、あわ
せてリファレンスという。
- それぞれツリーを成している場合、それぞれリファ
レンスソースツリー・リファレンスバイナリツリー
と呼ぶ。
- リファレンスソースツリーは読み出し専用にす
べき。
** 6.4 ファイルシステムの配置
- バイナリツリーの配置に注意すべし。
- 名前の付け方の工夫が有効。
- 構築パラメータをパスに含める。
例。
------
vendor-architecture-os-memo
dell-386-linux-debug
------
** 6.5 構築とテストの自動化
- 構築の自動化は大事。
- テストの自動化も大事。
- テストの自動化はグラフィカルかそうじゃないかで
大別。
- グラフィカル(X): Xvfb
- 非グラフィカル: devaGnu, JUnit
こつこつ。
0 件のコメント:
コメントを投稿