Makefile を 1 つの記事で読む

1.土木工事

        キーボードから 2 つの整数を入力し、それらの合計を計算して出力するような小さなプロジェクトがあります。このプロジェクトには、main.c、input.c、calcu.c の 3 つの C ファイルと、input.h と calcu.h の 2 つのヘッダー ファイルがあります。このうち、main.c は本体、input.c はキーボード入力の受け取り、calcu.c は 2 つの数値の加算を担当します。便宜上、コードは次のように掲載されています。

"main.c"

#include <stdio.h>
#include "input.h"
#include "calca.h"

int main(int argc, char *argv[]) {
    int a, b, num;

    input_int(&a, &b);
    num = calcu(a, b);
    printf("%d + %d = %d\r\n", a, b, num);
}

-------------------------------------------------------------------------------
"input.c"

#include <stdio.h>
#include "input.h"

void input_int(int *a, int *b) {
    printf("input two num:");
    scanf("%d %d", a, b);
    printf("\r\n");
}

-------------------------------------------------------------------------------
"calcu.c"

#include <stdio.h>
#include "calcu.h"

int calcu(int a, int b) {
    return (a + b);
}

-------------------------------------------------------------------------------
"input.h"

#ifndef _INPUT_H
#define _INPUT_H

void input_int(int *a, int *b);
#endif

-------------------------------------------------------------------------------
"calcu.h"

#ifndef _CALCU_H
#define _CALCU_H

int calcu(int a, int b);
#endif

        これをコンパイルして実行します。

二、メイクファイルの構文

2.1 Makefile ルールのフォーマット

        Makefile は一連の規則で構成されており、これらの規則の形式は次のとおりです。 

目标1 ... : 依赖 ...
<TAB>命令1
<TAB>命令2
<TAB>...

目标2 ... : 依赖 ...
<TAB>命令1
<TAB>命令2
<TAB>..

......

指令1:
<TAB>命令1
<TAB>命令2
<TAB>...

指令2:
<TAB>命令1
<TAB>命令2
<TAB>...

......

        上記のルールに従って、このプロジェクトの Makefile は次のように記述されます。

main:main.o input.o calcu.o
	gcc -o main main.o input.o calcu.o 

main.o:main.c
	gcc -c main.c
input.o:input.c
	gcc -c input.c
calcu.o:calcu.c
	gcc -c calcu.c

clean:
	rm *.o
	rm main

        Makefile が書き込まれた後、make コマンドを使用してプロジェクトをコンパイルできます。 

2.2 Makefile 変数

2.2.1 代入文字「=」

        変数を使用して、2.1 で Makefile を書き換えます。

object = main.o input.o calcu.o

main:$(object)
	gcc -o main $(object)

main.o:main.c
	gcc -c main.c
input.o:input.c
	gcc -c input.c
calcu.o:calcu.c
	gcc -c calcu.c

clean:
	rm *.o
	rm main

        「=」を使用する場合、「=」によって割り当てられる変数の実際の値は、それが参照する変数の最後の有効な値に依存することを知る必要があります。 

2.2.2 代入文字「:=」

        「:=」で割り当てられた変数は、定義時の値のみを使用します。

2.2.3 代入文字「?=」

        上記のコードは、変数 curname に以前に値が割り当てられていない場合、この変数は「leafye」であり、以前に値が割り当てられていた場合は、以前の値が使用されることを意味します。

2.2.4 変数への「+=」の追加 

        すでに定義されている変数に文字列を追加する必要がある場合は、「+=」を使用する必要があります。

 2.3 Makefile のパターン規則

        2.1 では、このプロジェクトの Makefile を作成しました。Makefile の 4 ~ 9 行目は、対応する .c ソース ファイルを .o ファイルにコンパイルするためのものですが、プロジェクト内に多数の C ファイルがある場合、ルールを 1 つずつ記述することは明らかにお勧めできません。これを行うには、Makefile のパターン ルールを使用して、すべての .c ファイルを対応する .o ファイルにコンパイルします。
        パターン ルールでは、"%" を使用してファイル名を一致させます。たとえば、「%.c」は、.c で終わるすべてのファイルを意味します。ターゲットに「%」が表示される場合、ターゲットの「%」で表される値によって、依存関係の「%」の値が決定され、使用方法は次のようになります。

%.o:%.c
<TAB>命令

        したがって、2.1 の Makefile は次の形式に変更できます。

object = main.o input.o calcu.o

main:$(object)
	gcc -o main $(object)

%.o:%.c
	#命令

clean:
	rm *.o
	rm main

2.4 Makefile 自動化変数 

        前述のルール モードでは、ターゲットと依存関係は一連のファイルです.パターン ルールが解析されるたびに、異なるターゲットと依存関係のファイルになり、コマンドは 1 行だけです.対応するターゲットを生成しますか? 自動化変数は、この機能を完了するためにここにあります。自動変数は、パターンに一致するすべてのファイルがフェッチされるまで、パターンで定義された一連のファイルを 1 つずつ自動的にフェッチします。自動化変数は、現在のルールのコマンドにのみ含まれます。一般的に使用される自動化変数を以下の表に示します。

        2.3 では自動化変数を使用して Makefile を完成させます。最終的なコードは次のようになります。

object = main.o input.o calcu.o

main:$(object)
	gcc -o main $(object)

%.o:%.c
	gcc -c $<

clean:
	rm *.o
	rm main

2.5 Makefile 疑似ターゲット

        いくつかのコマンドを実行するためのルールを作成する必要がある場合がありますが、このルールはファイルの作成には使用されません.たとえば、次のコードは、前の Makefile でプロジェクトをクリーンアップするために使用されます.

clean:
	rm *.o
	rm main

        「make clean」に入ると、次の「rm *.o」と「rm main」が必ず実行されます。ただし、ディレクトリに「clean」という名前のファイルがある場合、「make clean」を実行した後、ルールに依存ファイルがないため、ターゲットは最新であると見なされ、後続のコマンドは実行されません。予定されていたクリーンアップ プロジェクト機能を完了できません。この問題を回避するために、次の方法で clean を疑似ターゲットとして宣言できます。

.PHONY:clean

        疑似ターゲットを使用して変更された Makefile は次のとおりです。

object = main.o input.o calcu.o

main:$(object)
	gcc -o main $(object)

%.o:%.c
	gcc -c $<

.PHONY:clean

clean:
	rm *.o
	rm main

2.6 Makefileの条件判定

        Makefile の条件判定には、次の 2 つの構文があります。

<条件关键字>
    <条件为真时执行的语句>
endif

        としても

<条件关键字>
    <条件为真时执行的语句>
else
    <条件为假时执行的语句>
endif

        その中には、ifeq、ifneq、ifdef、ifndef の 4 つの条件付きキーワードがあり、これら 4 つのキーワードは、ifeq と ifneq、ifdef と ifndef の 2 つのペアに分けられます。最初に ifeq と ifneq を見てください. ifeq は等しいかどうかを判断するために使用され、 ifneq は等しくないかどうかを判断するために使用されます. ifeq の使用法は次のとおりです。

ifeq(<参数1>,<参数2>)
ifeq'<参数1>','<参数2>'
ifeq"<参数1>","<参数2>"

        上記の用法は、「パラメータ1」と「パラメータ2」が同じかどうかを比較するために使用され、同じであれば真です。ifneq は反対のことを行います。 

        ifdef と ifndef の使用法は次のとおりです。

ifdef<变量名>

        "variable_name" の値が null 以外の場合、式は true になり、それ以外の場合、式は false になります。ifndef は逆です。

2.7 Makefile関数の使用 

        Makefile は関数をサポートしており、それらを直接使用できます。次に、よく使う関数をいくつか紹介しますが、それ以外の関数については、「Makefile を使って書く」というドキュメントを参照してください。

2.7.1 関数 patsubst

        関数 patsubst は、パターン文字列の置換を完了するために使用されます。使用方法は次のとおりです。

$(patsubst<pattern>,<replacement>,<text>)

        この関数は、文字列 <text> 内の単語がパターン <pattern> に一致するかどうかをチェックし、一致する場合は <replacement> に置き換えます. <pattern> では、ワイルドカード文字 "%" を使用して、任意の長さの文字列を表すことができます.関数の戻り値は、置換された文字列です。<replacement> に "%" も含まれている場合、<replacement> の "%" は <pattern> の "%" で表される文字列になります。次に例を示します。

$(patsubst %.c,%.o,a.c b.c c.c)

        文字列「ac bc cc」の「%.c」に一致するすべての文字列を「%.o」に置き換え、置換後の文字列は「ao bo co」です。 

2.7.2 関数のワイルドカード

        ワイルドカード文字 "%" はルールでのみ使用でき、ルールでのみ展開されます. 変数定義と関数を使用するときにワイルドカード文字が自動的に展開されない場合は、この時点で関数のワイルドカードが使用されます.使用方法は次のとおりです。

$(wildcard PATTERN···)

        例えば:

$(wildcard *.c)

        上記のコードは、「%」と同様に、現在のディレクトリ内のすべての .c ファイルを取得するために使用されます。  

おすすめ

転載: blog.csdn.net/weixin_46773333/article/details/129650175
おすすめ