makefileルール


makefileのルール
概要
ルールの一般的な形式:
target:  |  
    

makefileの構成主体は様々なルールである.どのような形式のルールでも、ターゲット、必要条件、コマンドの3つの要素グループが記述されます.1つのルールでは、1つまたは複数の作業ターゲット(実際には無数のルールで構成されたモード)を同時に記述できます.複数のターゲットのルールは、複数のルールのオーバーラップ記述とみなされ、単一の作業ターゲットのルールに分割できます.作業ターゲットはファイル名、またはアクションです.を選択します.必要条件は、具体的なファイルまたは「アクション」であってもよく、空であってもよい.コマンドは、更新が発生したときにサブshellに渡されるコマンドであり、複数のコマンドを1つのshellに渡すことができ、すべてのコマンドを1つのshellに実行する場合は、1行にまとめるか、または連行記号\を使用します.
ターゲットと必要な条件の変数はすぐに拡張され、コマンドは拡張されません.(makeは、すべての変数とコマンドがデータベースにロードされた後、コマンドを実行する前にコマンドの変数を拡張します.).SECONDEXPANSIONというターゲットが定義されている場合、その後のルールの必要条件は2回拡張されます.2回目の拡張は、makeがすべての変数とルールを読み込んだ後、ルールを実行する前に発生します.
makeがmakefileを読み込むと、必要な条件のタイプとタイムスタンプとターゲットのタイムスタンプに基づいて、更新アクションを実行するかどうかを決定します(コマンドをサブshellに渡して実行します).必要条件は、通常必要条件の2つに分けられます.ターゲットを更新する前に、通常必要条件を更新します.この必要条件のタイムスタンプがターゲットのタイムスタンプ以上であれば(まだ存在しないファイルタイムスタンプは負の無限またはある古い時点と考えられる)は、更新動作を引き起こす.「order-only」必要条件、(一度だけ実行する必要条件、|以降の必要条件).Makeはこの必要条件を更新する際にそのファイルが存在するかどうかをチェックし、存在する場合は、この必要条件を更新し続けない(タイムスタンプにかかわらず)そのためにターゲットを更新することはありません.存在しない場合は、makeの実行中にその必要条件をターゲットとするルールが実行されたかどうかを確認し、なければ1回実行し、そうでなければこの必要条件の更新を終了します.
次の例では、新しいターゲットファイルとの間にターゲットフォルダが存在することを要求しますが、新しいターゲットファイルとのルールごとにmkdir-pを実行することはできません.これでも仕事ができますが、見ているとつらいです.より良い方法は、ターゲットファイルorder-onlyをフォルダに依存させ、フォルダに対する更新動作をmkdir-pにすることです.これにより、mkdirは1回しか実行されません.
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)

$(OBJS): | $(OBJDIR)
$(OBJDIR):
    mkdir $(OBJDIR)

具体的なルールは、具体的な作業目標を指定し、必要な条件にタイムスタンプが後ろにあるファイルがある場合はコマンドを実行します.これは最も一般的なルールです.モードルールでは、ターゲットは特定のファイル名ではなくワイルドカードを使用します.これにより、makeはモードに一致する作業ターゲットにルールを適用します.暗黙規則は、モード規則であってもよいし、makeに組み込まれた接尾辞規則であってもよい.
具体的なルール
具体的なルールは、特定のファイルを作業目標と必要条件とします.各ルールは、複数の作業ターゲットで実行できます.各作業目標が後の必要条件に依存していることを意味します.ルールは完全に一度に定義する必要はありません.makeが作業目標を見るたびに,その作業目標と必要条件を依存図に加える.作業ターゲットがすでに存在する場合、依存マップに追加する必要条件が追加されます.1つの作業目標に複数回コマンドが設定されている場合(1回のコマンドが複数のコマンドで構成されているわけではない)、最後のコマンドを更新動作として取り、前のコマンドを無視するとmakeは警告します.
仮想作業目標:作業目標は実際のファイルではなく、動作を表し、仮想作業目標になります.常に更新されておらず、「古い」ので、ルールのコマンドは毎回実行されます.このアクションがファイルと重複する可能性を防止するために、.PHONY:で宣言できます.
パターン規則
背景:
  • 多くのファイルを含む大規模なプログラムでは、各ルールを手動で指定することは現実的ではありません.また、これらのコマンドは重複するコードである可能性が高く、どこかを修正すると複数の修正が起こり、メンテナンスが困難になるという問題が発生する可能性があります.
  • 多くのプログラムは、入力ファイルを読み取り、出力ファイルを生成する際に慣例に従う.

  • を選択します.
    モード規則のパーセント文字%は、unixのアスタリスク*とほぼ同等であり、任意の複数の文字を表すことができる.パーセンテージ文字はモードのどこにでも配置できますが、一度しか表示されません.makeが使用するモードルールを検索すると、まず一致するモードルールの作業目標を検索し、パーセンテージで表される部分を必要条件に置き換えてモードルールの必要条件をチェックします.
    例:
    %: %.mod
        $(COMPILE.mod) -o $@ -e $@ $^
    
    %: %.cpp
        $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@
    
    %: %.sh
        cat $< >$@
        chmod a+x $@

    静的モード規則
    静的モード・ルールと一般的なモード・ルールの唯一の違いは、作業目標の一致セットを指定することです.
    $(OBJECTS): %.o: %.c
        $(CC) -c $(CFLAGS) $< -o $@

    接尾辞規則
    接尾辞規則は,従来モード規則がなかった場合の代替品であり,廃棄された.
    暗黙のルール
    暗黙ルールはmakeに組み込まれたモードルールです.makeに組み込まれているルールを表示するには、-p, --print-data-baseコマンドを使用して表示します.このコマンドには、組み込まれた変数定義も表示されます.
    makeが作業ターゲットをチェックすると、特定のルールが見つからない場合は、隠しルールが使用されます.コマンドなしのモード規則を使用すると、対応する暗黙規則を遮断できます.
    例:
    hello:
    hello: hello.c

    適切なコンパイルプロセスが自動的に実行されます.
    %: %.o

    シールド可能oファイルリンク実行可能プログラムのルール.
    その他
    ルールではshellのモードマッチングを使用できますが、他の場所ではwildcard関数を使用します.
    ルールに必要な条件は、一度に完全に記述する必要はなく、複数回に分けることができますが、同じルールのコマンドについては、最後の記述のコマンドのみを取ります.例:
    hello : hello.c
        echo hello
        
    hello : include.h
        gcc -o hello hello.c

    helloをターゲットとするルールには、hello.cinclude.hの2つの必要条件があり、このルールのコマンドはgcc -o hello hello.cのみです.