Makefile ルールの詳細な説明

Makefile ルールの詳細な説明

1 はじめに

GCC (GUN C Compiler) は最も初期に開発された C コンパイラであり、現在でも広く使用されており、C++、Objective-C、Fortran、Ada、Go などの言語のコンパイル サポートも追加されています。

GCC は CLI インタラクションを使用するコンパイル ツールであり、グラフィカル インターフェイスをサポートしていないため、すべての操作はターミナルのコマンドを通じて完了する必要があります。ただし、完全なソース コードは常に複数のファイルに分割されており、コンパイル中にさまざまな制御とコンパイル オプションが必要です。ターミナルに長いコンパイル コマンドを入力する必要があり、一度に入力できるコマンドは 1 行だけです。このプロセスはファイルがコンパイルされるたびに繰り返す必要があり、非常に手間がかかります。

コンパイル プロセスを簡単かつ迅速にし、GCC を使用してコマンドを入力して段階的にコンパイルする手間を省くために、Makefile が登場しました。長いコマンドを恐れることはなくなり、GCC のさまざまな制御およびコンパイル オプションを Makefile に書き込むだけです。 , Make に Makefile を解析させてから GCC を呼び出してコンパイルを実行するだけで、コンパイル (ビルド) の自動化が完全に実現されます。

2.作る

Makefile について詳しく説明する前に、まず Make ツールについて理解しましょう。Makefile は Make によって使用されるように書かれていることを知っています。では、メイクとは何でしょうか?当面、Make は Python プログラムを解釈する Python インタープリターと同様のインタープリターとして理解できますが、Make によって解釈されるプログラムは Makefile ファイルです。

では、Make の役割は何でしょうか? 「作成」または「製造」を意味する Make の中国語の意味を翻訳しましょう。はい、Make の機能は、特定の形式でファイルを作成できることです。

Make を使用してプレーン テキスト ファイル hello.txt を作成する必要がある場合は、次のコマンドを実行できます。

make hello.txt

ただし、Make はユーザーの希望に合った hello.txt ファイルの作成方法を知らず、hello.txt にどのような内容を記述すべきかも知らないため、「hello.txt を作成するためのルールはありません」というエラーが表示されます。

make: *** No rule to make target 'hello.txt'.  Stop.

hello.txt のファイル内容が temp.txt の内容と同じである場合、つまり hello.txt が temp.txt のコピーである場合 (または hello.txt は temp.txt に依存する場合)、Make に次のように指示できます。 temp.txt をコピーして hello.txt という名前を付けるだけで、ニーズに合った hello.txt を取得できるので、次のルールを作成するように指示する必要があります。

hello.txt: temp.txt
    cp temp.txt hello.txt

make hello.txtコマンドを実行すると、temp.txtが存在するか確認し、存在する場合はcpコマンドでtemp.txtファイルをコピーし、新しいファイルhello.txtとして出力します。

このようなルールは前述の Makefile に記述されており、Make はこのファイルを利用して構築します。

実験:

必要な内容を含む temp.txt ファイルを準備します。新しいファイルを作成し、その中に上記のルールをコピーし、ファイル名を Makefile として保存します。次に、make hello.txt コマンドを実行すると、次の出力が得られます。ローカル ファイルを確認すると、hello.txt ファイルが実際に取得されます。内容は、準備した temp.txt と同じです。

make hello.txt
cp temp.txt hello.txt

ショックを受けましたか? 上記は疑似コードだと思いますか? 実際に問題なく実行できますし、Make は C プログラムの処理に限定されるものではなく、ルールさえ与えれば、それを処理することができます。

要約:

Make は特定の形式でファイルを生成できますが、Make 自体は特定の形式でファイルを生成する方法を知りません。したがって、Makefile の役割は、Make に特定の形式でファイルを作成する方法を指示することであり、Makefile を記述することは、Make に特定の形式でファイルを作成する方法を指示することと同じです。

Make は特定の形式でファイルを作成できますが、Make 自体にはファイルを作成 (または編集) する機能がないため、Make はファイルを作成するために、GCC やテキスト編集。呼び出し方法は、これらのツールが提供するコマンドを実行することです。特定のコマンドについてはここでは詳しく説明しません。Make がファイルを作成できることだけ知っておいてください。

3. ルールの詳しい説明

前のセクションで説明したように、ビルド ルールはすべて Makefile に記述されており、Makefile に Makefile または makefile という名前を付ける場合、拡張子は必要ありません。ターミナルでコマンドを実行すると、Make は Makefile または makefile という名前のファイルを検索しますmake。現在のディレクトリ。

もちろん、config.txt などの別の名前を付けることもできますが、-f名前は make コマンド オプションを使用して指定する必要があります。

make -f config.txt
make --file=config.txt

Make を使用してプログラムを構築する方法を学ぶには、Makefile ファイルの書き方を学ぶ必要があります。Makefile の書き方のルールを詳しく見てみましょう。

3.1 全体的なルール

Linux ソース コード Makefile などの Makefile を開きます。全体的には、さまざまな種類の奇妙な記号があり、非常に複雑に見えます。実際、記号の意味は別として、複雑な Makefile は単純なルールで構成されています。Makefile のルールフォームは以下の通りです。

<target> : <prerequisites>
[tab] <commands>

1行目のコロンより前の部分を「ターゲット」、コロンより後の部分を「前提条件」と呼びます。2行目はタブキーで始まり、その後に「コマンド」が続きます。

「対象」は必須であり、省略することはできません。「precondition」と「command」は省略可能ですが、少なくともどちらか一方が存在する必要があります(両方を同時に省略することはできません)。

各ルールは、目標を構築するための前提条件と、目標を構築する方法という 2 つのことを明確にします。

3.2 対象

ターゲットはルールを構成します (各ルールは「ターゲット」で始まります)。ターゲットは通常、Make コマンドによって構築されるオブジェクトを示すファイル名です (前の例の hello.txt など)。ターゲットは 1 つ以上のファイル名にすることができ、複数のファイル名はスペースで区切られます。

ターゲットにはファイル名以外に操作名を指定することもでき、このようなターゲットを「偽のターゲット」と呼びます。

たとえば、ターゲットが clean (クリーニング操作) の場合、clean は一部の中間ファイルをクリアするために使用される「疑似ターゲット」であり、ターミナルで実行すると、中間ファイルをクリアできますmake clean

clean:
    rm -rf *.o

ご存知のとおり、Makefile は「ターゲット」構築原則に基づいて「疑似ターゲット」を巧みに利用して、操作コマンドをカスタマイズできる機能を実装しています。ただし、ソース コードに clean という名前のファイルが含まれている場合、疑似ターゲット clean に対応するコマンドは実行されません。Make はクリーンなファイルがすでに存在していることを発見したため、それを再構築する必要はないと判断し、当然rm -rf *.oコマンドの実行を停止しました。

この状況を回避するには、.PHONYclean を「疑似ターゲット」として明示的に宣言します。clean を「疑似ターゲット」として宣言した後は、Make は clean という名前のファイルがあるかどうかをチェックしなくなり、ファイルが存在するたびに対応するコマンドを実行します。宣言 方法は次のとおりです。

.PHONY: clean
clean:
    rm -rf *.o

したがって、make の「真の目標」は特定のターゲット オブジェクトをビルドすることであり、make の「疑似目標」は特定の操作を実行することです。

3.3 前提条件

前提条件は、「ターゲット」の依存ファイルを参照します。ターゲットは生成される前提条件に依存する必要があります。通常は 1 つ以上のファイル名です。複数のファイル名はスペースで区切られます。「ターゲット」が他のファイルに関連していない場合、前提条件にファイル名をリストする必要はありません。

前提条件によって、「ターゲット」を再構築する必要があるかどうかが決まります。前提条件にリストされているファイルのいずれかが更新されている (つまり、前提条件にリストされているファイルの最終変更時刻がターゲットの最終変更時刻より新しい)、または「ターゲット」が存在しない限り、"ターゲット」を再構築する必要があります。

前提条件にリストされているファイルのいずれかが存在しない場合、Make は Makefile 内でファイルを生成できるルールを見つけて実行する必要があります。つまり、不足しているファイル自体も「ターゲット」であり、最初に実行する必要があります。この「目標」は、現在の「目標」を構築するために使用する前に構築する必要があります (A を構築するときに、A が B に依存する必要があることが判明したため、A の構築を続行する前に最初に B を構築する必要があります。これは参照されています)再帰的な依存関係の生成として)。

hello.txt: temp.txt
    cp temp.txt hello.txt

前の例に戻って、hello.txt がターゲットであり、ターゲットを構築するための前提条件は temp.txt です。temp.txt が現在のディレクトリに既に存在する場合は、make hello.txt正常に実行できますが、それ以外の場合は、temp.txt を最初に生成し、次に hello.txt を生成する必要があります。

3.4 コマンド

コマンドは、ターゲット ファイルの更新方法を示します。コマンドは、1 行以上のシェル スクリプト コマンドで構成されます。「ターゲット」を構築するための具体的な指示です。通常、コマンドを実行すると、ターゲット ファイルが生成されます。

コマンドはタブ キーで始める必要があることに注意してください。もちろん、柔軟な Makefile を使用すると、タブ キーを他のシンボルに置き換えることができます。置き換え方法は、Makefile の組み込み変数を使用して新しいシンボルを宣言することです.RECIPEPREFIX>>Tabキーを置き換えます。

.RECIPEPREFIX=>>

clean:
>>rm -rf *.o

ターゲットの構築には複数のコマンドの使用が必要になる場合があります。複数のコマンドは通常、読みやすくするために複数行で記述する必要があります。ただし、注意すべき点が 1 つあります。それは、Makefile は、別の行に書かれたコマンドを別のシェル プロセスに割り当てて実行することです。これらのシェル間には継承関係はありません (つまり、コンテキスト接続がなく、シェル プロセスは実行後すぐに終了します)。 )、これは、したがって、2 つの隣接するコマンド間ではデータ相互作用を実現できないことを意味します。

したがって、次の Makefile ルールの echo コマンドは変数 var の値を取得できません。これは、これら 2 行のコマンドが異なるシェル プロセスで実行するように割り当てられているためです。

variable_test:
    export var="Hello, World!"
    echo var=$${var}

したがって、コマンド間でのデータ共有を実現するには、次のように、関連する複数のコマンドを 1 行に記述し、各コマンドをセミコロンで区切ることが解決策となります。

variable_test:
    export var="Hello, World!"; echo var=$${var}

複数のコマンドを 1 行で書くと結局読みにくいので、やはり複数行に分けて書く必要がありますが、複数行のコマンドで 1 行の効果を実現するには、バックスラッシュ エスケープを使用できます。エスケープすると、Make はこれらのコマンドが同じ行にあると認識するため\、同じシェル プロセスで実行する必要があります。

variable_test:
    export var="Hello, World!"; \
    echo var=$${var}

各コマンドの後にバックスラッシュを置くのが不適切だと思われる場合、最後のオプションは、バックスラッシュのエスケープ効果と同様に、\Makefile の組み込みコマンドを使用してルールを宣言することです。.ONESHELL:

.ONESHELL:
variable_test:
    export var="Hello, World!";
    echo var=$${var}

3.5 概要

Makefile は通常、いくつかの「実際のターゲット」といくつかの「疑似ターゲット」など、複数の「ターゲット」を定義します。デフォルトでは、makeMake コマンドを実行すると、Makefile の最初の「ターゲット」がビルドされ、その後、最初のターゲットの依存関係が徐々にビルドされます。

Make に指定した「ターゲット」をビルドさせたい場合は、makeコマンドの後にビルドする「ターゲット」の名前を指定します (例: 、make hello.txtまたは ) make clean。ターゲットが「実際のターゲット」の場合、Nubio オブジェクトがビルドされます。 , ターゲットが「疑似ターゲット」の場合は、何らかのアクションを実行します。

4. コマンドの詳細説明

前のセクションを終えて、Makefile の規則についてはすでに理解されているので、Makefile の基本的な構文を説明し、Makefile のいくつかの基本要素について理解しましょう。

4.1 注意事項

Makefile のコメントは、プログラミング言語Pythonやスクリプトと同じようにshell文字を#コメント識別子として使用します。つまり#、記号に続く内容は Make によってコメントとして認識され、無視されます。

# 这是注释语句
hello.txt: temp.txt # 这是注释语句
    cp temp.txt hello.txt # 这是注释语句

4.2 エコー

Make は各コマンドを実行する前に、実行するコマンドをターミナルに出力してから実行する、これがエコー機構です。

echoing:
    echo "Hello, World!"

make echoingターミナルでコマンドを実行すると、以下のような出力がターミナルに表示され、実行されたすべてのコマンドが Make によってターミナルに出力されていることがわかります。

make echoing
----------------------------------
echo "Hello, World!"
Hello, World!

コマンドの前に追加すると、現在のコマンドのエコーをオフにすることができます。もちろん、通常は、ターミナルへの出力自体を避けるために、@コメントと純粋な表示エコー コマンドの前にのみ追加されます。@echo

echoing:
    @echo "Hello, World!

echoコマンドの前に追加すると、@echoコマンド自体はターミナルに出力されなくなり、出力する必要のある内容のみが出力されるようになります。

make echoing
----------------------------------
Hello, World!

4.3 ワイルドカード

ワイルドカード文字 (Wildcard) は、修飾されたファイル名のセットを指定するために使用されます。Makefile のワイルドカード文字は Bash と一致しており、主にアスタリスク*、疑問符?、および が含まれます...たとえば、接尾辞名を持つ*.oすべての.oファイルを表します。たとえば、前の例ではワイルドカード文字が使用されています。

.PHONY: clean
clean:
    rm -rf *.o

4.4 パターンマッチング

Make コマンドを使用すると、正規表現と同様の方法でファイル名を一致させることができます。使用される主な一致文字はパーセント記号です%たとえば、現在のディレクトリに 2 つのソース コード ファイル ac と bc があると仮定すると、それらを対応するオブジェクト ファイル ao と bo にコンパイルする必要があり、2 つのルールを記述する必要があります。

a.o: a.c
    gcc -c a.c -o a.o

b.o: b.c
    gcc -c b.c -o b.o

プロジェクトに多数の C ファイルが含まれている場合、これを行うのは明らかに非常に面倒なので、簡単にするために%.o: %.cパターン マッチングを使用できます。その効果は次の記述と同等です。したがって、一致する文字を使用すると%、1 つの Makefile ルールだけを使用して同じタイプの多数のファイルを構築できます (パターン マッチングを通じて、すべてのファイルを対応するファイルにコンパイルするために実装できるルールは 1 つだけです.c) .o

%ターゲットに が含まれる場合、%ターゲットで表現される値が%依存関係の値を決定します。使用
方法は次のとおりです。

a.o: a.c
b.o: b.c

パターン ルールでは、少なくともルールのターゲット定義に含める必要があります%。それ以外の場合は一般ルールです。ターゲットでは、%ファイル名と一致することを意味するため、%任意の長さの空でない文字列を意味します。

4.5 変数

Makefile は、他のプログラミング言語と同様に、変数の定義をサポートしています。変数を定義する利点は、広範囲で使用されるコンテンツに対して、変数に置き換えることができることです。変数が変更されていない場合は、変数の内容を変更できることです。広範囲で利用されるコンテンツを一律に修正する。

Makefile で変数を定義する方法は以下の通りです Makefile はスクリプトであるため、他のプログラミング言語とは異なり、Makefile で変数を定義する際に変数の型を宣言する必要はありません (実際、Makefile 変数に保存される値はすべて文字列です) )。

一方、Makefile 変数は本当の意味での変数ではなく、C/C++ のマクロ定義に近く、実行すると変数の内容がそのまま使用箇所に展開されます。

hello = Hello, World!

hello:
    @echo $(hello)

変数を参照する場合、変数を変数に配置する$( )か、${}変数の値を取得する必要があります。

4.6 代入演算子

変数は以前に定義されており、関数に値を割り当てる必要があります。Makefile では、さまざまなシナリオに合わせて 4 つの代入演算子、すなわち 、 、 を定義しています。これらの代入演算子は異なる意味を持っ=:=?=ます+=

(1) =変数が実行されるときに展開され、再帰的展開が可能になります。Make は Makefile 全体を展開し、変数の値を決定します。つまり、変数の値は、Makefile 全体で指定された最後の値になります。

x = Hi
y = $(x) World
x = Hello
---
echo $(y)
Hello World

(2):=変数が定義されている場合は展開します。変数の値が、Makefile 全体が展開された後の最終値ではなく、Makefile 内の位置によって決定されることを示します。

x := Hi
y := $(x) World
x := Hello
---
echo $(y)
Hi World

(3)?=値は変数が空の場合にのみ設定されます。

(4)+=値を変数の末尾に追加します。

4.7 組み込み変数

Make コマンドは、クロスプラットフォーム互換性のための一連の組み込み変数を提供します。たとえば、$(CC)現在使用されているコンパイラー (gcc など) を指すもの、$(MAKE)現在使用されている Make ツールを指すもの、その他の組み込み変数などです。 Make の公式マニュアルを確認してください。

hello:
    $(CC) hello.c -o hello.exe

4.8 自動変数

先ほどパターン マッチングについて話したときに、ターゲットと依存関係は一連のファイルであると述べました。パターン マッチングが解析されるたびに、%異なるターゲット ファイルと依存関係ファイルが表され、コマンドは 1 行だけです。さまざまなターゲットと依存関係を取得するためのコマンドは何ですか? 依存関係に対応するターゲットは依存関係ファイル内に生成されますか? これには、Makefile 自動変数を使用する必要があります。

$@Makefile では、のような記号がよく見られますが$^$<この記号を自動変数と呼びます。自動変数は、現在のルール内で有効範囲を持つローカル変数です (つまり、自動化変数は Makefile ターゲット ルールにのみ表示される必要があります)。自動変数を使用すると、ルール ステートメントを簡素化できます。

いわゆる自動変数は、パターンに一致するすべてのファイルが取得されるまで、パターンで定義された一連のファイルを 1 つずつ自動的に取得する変数です。

(1)$@は現在のターゲットを指します。これは、Make コマンドによって現在構築されているターゲットです。たとえば、$@これは target を表しますhello

hello: hello.o
    gcc hello.o -o hello

したがって、以下の書き込み効果は上記と同じです。

hello: hello.o
    gcc hello.o -o $@

(2)$<は最初の前提条件を指します。たとえば、ルールが hello: ab の場合、$<a を参照します。

hello: a.o b.o
    gcc a.o b.o -o hello

したがって、以下の書き込み効果は上記と同じです。

hello: a.o b.o
    gcc $< b.o -o hello

(3) は、$?スペースで区切られた、ターゲットよりも新しいすべての前提条件を指します。たとえば、ルールが hello: ab で、b のタイムスタンプがターゲットの hello より新しい場合、$?b を参照します。

(4)$^は、スペースで区切られたすべての前提条件を指します。たとえば、ルールが hello: ab の場合、$^a と b を参照します。

hello: a.o b.o
    gcc a.o b.o -o hello

したがって、以下の書き込み効果は上記と同じです。

hello: a.o b.o
    gcc $^ -o hello

(5)$*一致文字%の一致部分を指します。たとえば%、a.txt の a と一致する場合、$*a を意味します。


ここにはリストされていない自動変数もありますので、詳細については Make の公式マニュアルを参照してください。

5. 高度なコマンド

Make コマンド自体に加えて、Makefile は Bash 構文 (つまり、シェル スクリプト構文) も使用できます。たとえば、シェル構文を使用して判定やループ、環境変数参照などを完了することができます。

2 つの構文の相互使用もエレガントではありません。たとえば、Makefile では代入演算子の=両側にスペースを含めることができますが、シェルではそれが許可されません。それ以外の場合、シェルでは値としてスペースも含めることになります。

5.1 判断

条件ステートメントは、適切な条件に基づいて特定の操作を実行または無視するように Make を制御できます。他のプログラミング言語とは異なり、Makefile には比較演算子がなく、別の比較コマンドに置き換えられます。そのため、条件付き比較を行うには、次の 4 つの比較コマンドが必要です。

注文 説明する
イフェク パラメータが等しくないかどうかを確認します。等しい場合は true、等しくない場合は false。
イフネク パラメータが等しくないかどうかを確認します。等しくない場合は true、等しい場合は false です。
ifdef 値があるかどうかを判定し、値がある場合は true、値がない場合は false とします。
ifndef 値があるかどうかを判定し、値がない場合は true、値がある場合は false とします。

コマンドの使用法ifeqは次のとおりで、残りの 3 つの使用法も同様です。

all:
ifeq ($(CC), gcc)
    @echo GCC Compiler
else
    @echo Other Compiler
endif

5.2 ループ

Makefile の for ループ構文は次のとおりです。 ここで、 は@コマンド エコーをオフにするためにのみ使用され、$$実際に$はシェル プロセスでシェル変数を参照するために使用されることを意味します (シェルでは$エスケープ記号として使用されるため)。$aまたは$(a)Makefile 変数を参照することを意味します。

a := 123 123 123

testfor:
    @for var in $(a); do \
        echo $${var}; \
    done

for ループに加えて、Makefile は、Makefile の組み込み関数である foreach ステートメントもサポートしています (理解していなくても問題ありません。次のセクションで説明します)。構文は次のとおりです。

a := 123 123 123

testfor:
    @$(foreach var, $(a),\
        echo $(var); \
    )

5.3 機能

Makefile では関数も使用できます。Makefile の場合、関数は特別な命令です。関数はパラメータを受け取り、次の形式で値を返すことができます。

$(function arguments) 或 ${function arguments}

pwdMakefile 内の関数は Make によって定義されており、カスタム関数はサポートされていません。これらを直接使用できます。たとえば、この関数は Makefile 内のシェル コマンドを実行するために使用できます。ここでは、関数はコマンドを実行するために使用されますターミナルの作業ディレクトリを出力できます

PATH := $(shell pwd)

Make が提供する関数はそれほど多くはありませんが、十分に活用できるので、次のセクションでは Make が提供する関数 (組み込み関数) の使い方を概説します。

6. 内蔵機能

Makefile は、さまざまな種類のファイルの処理に適した一連の組み込み関数を公式に提供しており、この関数自体は操作プロセスの一種のカプセル化であり、これらの関数を使用することで、一部の複雑な操作を簡素化できます。

6.1 シェル関数

シェル関数はシェルコマンドを実行するために使用されます。

srcfiles := $(shell echo src/{00..99}.txt)

6.2 ワイルドカード機能

ワイルドカードは%ターゲット ルールでのみ使用でき、ターゲット ルールでのみ展開されます。変数を定義して関数を使用するときにワイルドカードが自動的に展開されない場合は、この時点で関数ワイルドカードを使用する必要があります。

これを使用すると、Makefile 内の Bash のワイルドカード文字*やワイルドカード文字を置換し%、パターンに一致するファイル名のリストを返すことができます。

$(wildcard pattern...)

たとえば、src ディレクトリ内のすべての .txt ファイルと一致します。

srcfiles := $(wildcard src/*.txt)

6.3 サブ関数

subst関数は、本文中のfromをtoに置き換えて文字列の置換(文字列置換)を完了する関数であり、書式は以下の通りです。

$(subst from,to,text)

たとえば、文字列「feet on the street」に含まれるすべての「ee」を「EE」に置き換えます。

$(subst ee,EE,feet on the street)

以下の例を参照してください。

comma:= ,
empty:=
# space变量用两个空变量作为标识符,当中是一个空格
space:= $(empty) $(empty)
foo:= a b c
bar:= $(subst $(space),$(comma),$(foo))
# bar is now `a,b,c'.

6.4 Patsubst関数

patsubst関数はパターン一致置換に使用する関数で、文字列のパターンに一致した部分を置換で置換します。

$(patsubst pattern,replacement,text)

パターンではワイルドカードを使用して%任意の長さの文字列を表すことができ、関数の戻り値は置換された
文字列になります。置換も含まれる場合%、置換は%パターン内の文字列%で表される文字列になります。

たとえば、文字列「ac bc cc」の「%.c」に一致する文字列をすべて「%.o」に置換すると、置換後の文字列は「ao bo co」になります。

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

6.5 Foreach関数

foreach 関数はループを完了するために使用されます。この関数の意味は、パラメータリスト内の単語を 1 つずつ取り出してパラメータ var に代入し、テキストに含まれる式を実行することです。毎回 文字列が返されます。ループ中、テキストに含まれる各文字列はスペースで区切られます。最後にループ全体が終了すると、テキストによって返された各文字列で構成される文字列全体が、関数 foreach 関数の戻り値になります。

$(foreach var, list,text)

6.6 Dir/Notdir 関数

ディレクトリの取得には関数 dir を使用します。この関数はファイル名列名からディレクトリ部分を抽出するために使用されます。戻り値はファイル名列名のディレクトリ部分です。

$(dir names...)

たとえば、ファイル「/src/hello.c」のディレクトリ部分、つまり「/src」を抽出します。

$(dir </src/hello.c>)

関数 notdir は名前を見て、ファイルのディレクトリ部分を削除することを認識しますが、これは逆の効果があります。

$(notdir names...)

たとえば、ファイル「/src/hello.c」のファイル名部分「hello.c」を抽出します。

$(notdir </src/hello.c>)

7. まとめ

要約すると、Makefile を作成するには、コンパイル プロセスの段階と GCC コマンドの使用に精通している必要があります。それでも理解できない場合は、私のこの記事を読んでください。

GCCコマンドの詳しい説明

おすすめ

転載: blog.csdn.net/jf_52001760/article/details/131277015