Linux 組み込み開発 - Makefile の基本文法

Linux 組み込み開発 - Makefile の基本文法

次に、将来 make ツールを使用できるように、基本的な Makefile 構文を詳しく紹介します。

1. Makefile ルールの形式

Makefile は実際には一連のルールで構成されているため、これらのルールの形式を習得することが非常に重要です。これらのルールの形式は次のとおりです。

目标... : 依赖文件集合...
	命令 1
	命令 2
	......

これらのルール形式が何を意味するのかを詳しく見てみましょう。1つ目は目的とも言える目標で、例えば「読書ノートを書く」、これは目標の1つです。

2 つ目は、ファイルのコレクションに依存することです。これは、この目標を達成するために依存する必要があるものに相当します。例えば、「読書ノートを書く」という問題は、「ペン」「本」「机」などに頼る必要があります。

最後のコマンドは、「読書ノートを書く」という目的など、依存するものがすべて存在する場合に実行する必要がある手順に相当します。本と机がある場合は、それに座って開く必要があります。ペンでメモを取り始める、これが順序です。

ただし、依存ファイルのコレクションが更新されると、ターゲットも更新される必要があります。たとえば、読んだ本が変更されれば、読書ノートも当然更新されます。次に、前回の記事の Makefile 内のコードを分析してみましょう。

# 要得到main目标,需要main.o input.o calcu.o,需要执行
# gcc -o main main.o input.o calcu.o命令,后面的都是这样的。
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

# clear需要执行的命令
clean:
	rm *.o
	rm main

これらの Makefile ステートメントを実行するときの make コマンドの実行ステップを具体的に分析してみましょう。

最初に、最初のルールのメインを更新します。通常、最初のルールのターゲットをデフォルトのターゲットと見なします。デフォルトのターゲットが更新される限り、Makefile の作業は完了したとみなされます。最初のコンパイル時には main がまだ存在しないため、最初のルールが実行されます。最初のルールは 3 つの .o ファイルに依存します: main.o、input.o、calcu.o。これら 3 つの .o いずれも存在しません。ファイルは現在利用可能なので、最初に 3 つすべてを更新する必要があります。

次に、make はこれら 3 つの .o ファイルを対象とするルールを検索し、実行します。main.o を例にとると、2 番目のルールが main.o を更新することがわかり、2 番目のルールが実行され、同じことが他の 2 つの .o ファイルにも当てはまります。

最後のルールのターゲットは clean であり、依存ファイルがないため、デフォルトで最新の依存ファイルが設定されるため、対応するコマンドは実行されません。clean を実行したい場合は、「make clean」コマンドを直接使用できます。実行すると、現在のディレクトリにあるすべての .o ファイルと main が削除されるため、clean の機能はプロジェクトのクリーンアップを完了することです。

Make の実行プロセスを要約してみましょう。

  1. make コマンドは、現在のディレクトリで Makefile という名前のファイルを検索します。
  2. Makefile が見つかると、Makefile で定義されたルールに従ってコンパイルされ、最終的なターゲット ファイルが生成されます。
  3. ターゲットファイルが存在しない場合、またはターゲットが依存するファイルがターゲットファイルより新しい場合は、以下のコマンドを実行してターゲットを更新します。

コマンド リスト内の各コマンドは TAB キーで始める必要があり、スペースは使用できません。

2. メイクファイル変数

次に、Makefile 内の変数について説明します。Makefile は C 言語とは異なり、int 型、char 型などさまざまな型があり、Makefile 内の変数はすべて文字列です。それでは、Makefile で変数を使用する方法を見てみましょう。

まず、そのようなコードを見てみましょう。

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

「main.o input.o calcu.o」セクションが繰り返されていることがわかりますが、変数を使用してこの問題を解決するにはどうすればよいでしょうか? そして、次のコードを見てください。

objects = main.o input.o calcu.o
main: $(objects)
	gcc -o main $(objects)

Makefileでの変数の使い方は直接値を代入するもので、参照方法は「$+(変数名)」と比較的簡単で、この2つのコードは同等です。

2.1. 代入記号「=」

まず次のコードを見て、その出力値が何であるかを推測してみましょう。

name = ygr
curname = $(name)
name = yegaorui

print:
	@echo curname: $(curname)

私たちが学んだ C 言語によれば、最終出力は「ygr」でなければならないことがわかりますが、出力が何であるかを見てみましょう。

curname: yegaorui

とてもすごいですね、結果はこうなりました、なぜでしょうか?代入記号「=」の具体的な意味を見てみましょう。 **代入記号「=」によって代入される変数の実際の値は、それが参照する変数の最後の有効な値によって異なります。**ということで、最終結果はこうなりました。

「echo」の前に「@」が付いているのが分かりますが、これはMakeが実行時にコマンドの実行処理を自動的に出力するためで、コマンドの前に「@」を付けるとコマンドの実行処理が行われなくなります。このように結果が直感的にわかるので便利です。

2.2. 代入記号「:=」

代入文字「:=」を見てみましょう。その出力は比較的正常で、C 言語の出力と同じです。

name = ygr
curname := $(name)
name = yegaorui

print:
	@echo curname: $(curname)

出力:

curname: ygr

2.3. 代入記号「?=」

この代入記号は非常に興味深いものです。私はそれを判断代入記号と呼んでいます。その機能は次のとおりです: 変数に以前に値が代入されていない場合、この変数にはこの値が代入されます。以前に値が代入されている場合は、次を使用します前の値、割り当てられた値。具体的なコードは次のとおりです。

name = ygr
curname ?= yegaorui
name = yegaorui

print:
	@echo curname: $(curname)

出力:

curname: yegaorui

2.4、変数追加「+=」

実際、これは文字列接続文字に相当しますが、比較的単純なので詳細は説明しません。

# 两者是相等的
objects = main.o input.o calcu.o

objects = main.o inpiut.o
objects += calcu.o

3. メイクファイルのパターン規則

また、前のコードから、コード内には非常によく似た次のステートメントなど、類似したステートメントが多数あることがわかります。これらのステートメントを簡素化するにはどうすればよいでしょうか? 答えは「はい」ですが、次に紹介する Makefile パターン ルールを導入する必要があります。よし、始めよう!

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

実際、いわゆるパターン ルールは、ターゲットにワイルドカード文字 "%" を導入することです。ターゲットの "%" はファイル名との一致を意味し、"%" は任意の長さの空でない文字列を意味します。たとえば、「%.c」は .c で終わるすべてのファイルです。

ターゲットに「%」が出現する場合、ターゲットの「%」で表される値によって依存関係の「%」の値が決まります。たとえば、次のコードは同等です。

# 等价
main.o: main.c

%.o : %.c

ただし、次の「gcc -c main.c」を「gcc -c %.c」として記述することはできません。gcc の後には特定のファイルが続く必要があるためです。では、この問題をどうやって解決すればいいのでしょうか?すぐにわかります。

4. メイクファイル自動化変数

自動変数: この変数は、パターンに一致するすべてのファイルがフェッチされるまで、パターンで定義された一連のファイルを 1 つずつ自動的に抽出します。自動変数は、ルールのコマンド内にのみ表示されます。

自動化変数を詳しく見てみましょう。

オートメーション変数 説明
$@ ルール内のターゲットのセット。パターン ルールでは、ターゲットが複数ある場合、「$@」は一致するパターンで定義されたターゲットのセットを意味します。
$% ターゲットが関数ライブラリの場合、ルール内のターゲット メンバーの名前を意味します。ターゲットが関数ライブラリ ファイルでない場合、その値は空です。
$< 依存ファイル コレクションの最初のファイル。依存ファイルがパターン (つまり、「%」) で定義されている場合、「$<」はパターンに一致する一連のファイル コレクションです。
$? ターゲットより新しいすべての依存ターゲットをスペースで区切ったコレクション。
$^ スペースで区切られたすべての依存ファイルのコレクション。依存ファイルに複数の重複ファイルがある場合、「$^」は重複した依存ファイルを削除し、1 つのコピーを保持します。
$+ 「$^」と似ていますが、依存ファイルに重複がある場合、重複した依存ファイルは削除されません。
$* ターゲットパターンの「%」とその前の部分を示します。ターゲットがtest/ac、ターゲットモードが%.cの場合、「$*」はtest/aとなります。

学習したばかりの自動化変数に基づいて、次の同等のステートメントを取得できます。

# 等价
main.o: main.c
	gcc -c main.c
	
input.o: input.c
	gcc -c input.c
	
calcu.o: calcu.c
	gcc -c calcu.c
	
# $<就相当与依赖文件的第一个文件
%.o : %.c
	gcc -c $<

次に、コードを次のコードに変更できます。

objects = main.o input.o calcu.o
main: $(objects)
	gcc -o main $(objects)
	
%.o : %.c
	gcc -c $<

clean:
	rm *.o
	rm main

5、Makefile疑似ターゲット

次に疑似コマンドの紹介ですが、実はこれまでにも触れたことがある明確なコマンドです。

「make clean」と入力すると、clear 以下のステートメントを実行できることがわかっていますが、この「clear」ファイルがある場合、クリア ファイルは常に最新であるため、実行されません。したがって、疑似コマンドを定義する必要があります。具体的な構文は次のとおりです。

.PHONY : clean

次。コードを次のコードに変更できます。

objects = main.o input.o calcu.o
main: $(objects)
	gcc -o main $(objects)
	
%.o : %.c
	gcc -c $<

.PHONY : clean
clean:
	rm *.o
	rm main

さて、これが markfile の基本的な構文であり、後ほど詳しく紹介します。

おすすめ

転載: blog.csdn.net/weixin_66578482/article/details/128941220