プログラミングユーティリティ

入れ子にした make コマンド

以上の問題を解決するには、ライブラリがあるディレクトリで make コマンドを入れ子にして実行し、(そのディレクトリにあるメークファイル中のターゲットエントリに従って) ライブラリを構築します。


注 -

デフォルトでは "make" という値に設定されている MAKE マクロは、make コマンドの -n オプションを無効にします。つまり MAKE マクロを参照しているコマンドは、-n オプションが指定されている場合でも実行されます。ただし MAKE マクロは make コマンドを呼び出すためにのみ使用され、このマクロによって呼び出された make は、特殊マクロ MAKEFLAGS から -n オプションを継承します。入れ子 (階層構造) になった make はそれぞれ MAKEFLAGS マクロによって -n オプションが指定されていることを認識していきます。このため、-n オプションを使用することで、入れ子になった make の動作を実際に実行せずに確認することができます。


# 他のディレクトリに生成されるターゲット用の最初のエントリ

../lib/libpkg.a:
        	cd ../lib ; $(MAKE) libpkg.a

ライブラリは、現在のディレクトリからの相対パス名で指定します。プロジェクトが新しいルートディレクトリまたはマシンに移動された場合に、新しいルートディレクトリに対するディレクトリ構造がそのまま同じであれば、すべてのターゲットエントリが正しいファイルを示します。

入れ子にした make のコマンド行では、定義済みマクロ MAKE の場合と同様に、動的マクロの修飾子の F および D が便利です。処理されるターゲットがパス名で指定されている場合は、$(@F) はファイル名部分、$(@D) はディレクトリ部分をそれぞれ示します。ターゲット名に / という文字が含まれていない場合は、$(@D) の値としてドット (.) が値として割り当てられます。

ターゲットエントリは、次のように書き換えることができます。

# 2 番目のエントリ

../lib/libpkg.a:
        	cd $(@D); $(MAKE) $(@F)

入れ子にした make コマンドを強制的に実行する

このターゲットには依存関係がないため、../lib/libpkg.a という名前のファイルがないときにだけこのターゲットが実行されます。ファイルが .PRECIOUS により保護されたライブラリアーカイブである場合は、../lib/libpkg.a ファイルがないということはほとんどありません。make はそのファイルの依存関係を認識する必要はないため、認識しません。ファイルを構築するかどうか、およびその構築方法は、入れ子にした呼び出しによって決定されます。

つまり、ファイルシステム内にファイルがあっても、そのファイルが最新でない場合もあります。したがって、ファイルがあるかどうかに関わらず、そのファイルを規則が空白の (および既存のファイルがない) 他のターゲットに依存させることによって、入れ子にした make コマンドを強制的に実行する必要があります。

表 4-15 入れ子にした make コマンド用のターゲットエントリ
# 入れ子にした make コマンド用
# ターゲットエントリ

../lib/libpkg.a:  FORCE
        	cd $(@D); $(MAKE) $(@F) 
FORCE:

この方法により、make は、正しいディレクトリ ../lib に変更し、そのディレクトリにあるメークファイルに記述された命令に従って、必要であれば libpkg.a を構築します。入れ子にした make の実行結果は次のようになります。

$ make ../lib/libpkg.a 
cd ../lib; make libpkg.a 
make libpkg.a 
`libpkg.a' is up to date.

以下のメークファイルは、入れ子にした make コマンドを使用して、プログラムが依存するユーザー定義のライブラリを処理します。

表 4-16 ユーザー定義のライブラリを使用した C プログラム用のメークファイル
# ユーザー定義の C ライブラリと
# 入れ子になった make コマンド用の Makefile

CFLAGS= -O 

.KEEP_STATE:

functions: main.o data.o ../lib/libpkg.a 
        	$(LINK.c) -o $@ main.o data.o
         ../lib/libpkg.a -lcurses -ltermlib 
         ../lib/libpkg.a:  FORCE
        	cd $(@D); $(MAKE) $(@F) 
FORCE: 

lint: main.ln data.ln 
        	$(LINT.c) main.ln data.ln 
clean: 
        	rm -f functions main.o data.o main.ln data.ln

../lib/libpkg.a が最新である場合は、このメークファイルを使用する make の実行結果は以下のようになります。

$ make 
cc -O -c main.c 
cc -O -c data.c 
cd ../lib; make libpkg.a 
`libpkg.a' is up to date.  
cc -O -o functions main.o data.o ../lib/libpkg.a -lcurses -l   termlib

MAKEFLAGS マクロ

MAKE マクロと同様に、MAKEFLAGS も特殊マクロです。


注 -

MAKEFLAGSメークファイル中に定義しないでください。


MAKEFLAGS には、make コマンド用のフラグ (1 文字のオプション) が含まれています。他の FLAGS マクロとは異なり、MAKEFLAGS の値は、フラグの冒頭に付いている - (ハイフン) を除いて連結したものになります。たとえば、eiknp という文字列は、MAKEFLAGS の値として認識されますが、-f x.mkmacro=value は値として認識されません。

MAKEFLAGS という環境変数が設定されている場合は、make は、コマンド行で指定されたフラグと、MAKEFLAGS に含まれるフラグを組み合わせて実行されます。

MAKEFLAGS の値は、環境変数で設定されているかどうかに関係なく常にエクスポートされ、MAKEFLAGS に含まれるオプションは、($(MAKE)make/usr/bin/make のうちどれによって呼び出されたかに関係なく) 入れ子にした make コマンドに渡されます。これにより、親の make が呼び出された際のオプションが、入れ子にした make コマンドに渡されます。