Linux での Makefile の書き方と使い方の詳細な説明

Linux での Makefile の書き方と使い方の詳細な説明

メイクファイル

プロジェクト ファイルには多数のソース ファイルが存在し、異なる関数やモジュールが異なるディレクトリに配置されている場合があります。従来のコンパイルでは、このような問題を効率的に処理できなくなり、この問題を解決するために Makefile が使用されます。

Makefile が記述されると、Makefile ファイルに記述されたすべての命令を完了するために必要なmakeコマンドは 1 つだけになり、それによってプロジェクト ファイル全体がコンパイルされ、効率が大幅に向上します

make は、Makefile 内のコマンドを解釈するために使用されるコマンド ツールです。

Makefile の命名とルール

ファイル名

makefile または Makefile のいずれかを使用できます。

Makefileのルール

Makefile 内のコマンド ルールは次のとおりです。

xxx (対象ファイル): xxx (依存ファイル)
(タブ)コマンド(シェルコマンド)
このうち、ターゲットファイルは最終的に生成されるファイル(疑似ターゲットを除く)、依存ファイルはターゲットファイルの生成に必要なファイル、コマンドはシェルコマンドです。

コマンドの前にタブインデントが必要であることに注意してください。

例えば:

#メイクファイル
app: ac bc #ターゲット: gcc ac bc -o app に依存 #この行の先頭のインデントに注意してください

上記のMakefileを作成すると、ディレクトリ内のacbc がターゲットファイルappにコンパイルされます。

Makefile の仕組み

Makefile 内のコマンドを実行する前に、必要な依存ファイルが存在するかどうかを確認します。

存在する場合:コマンドを実行する

存在しない場合: 他のルールをチェックして、現在のルールに必要な依存関係を生成する他のルールがあるかどうかを確認します。ある場合は、ルール内のコマンドを実行します。

例えば:

#メイクファイル
アプリ: アオボ
	gcc ao bo -o アプリ
青: ac
	gcc -c ac -o ao
bo: bc
	gcc -c bc -o bo

上記の Makefile では、app ルールを実行すると、必要な依存ファイル ao と bo が現在のディレクトリに存在しないことが分かるので、このファイルを生成する他のルールがないか下の方を調べます。ao ルールが見つかると、それが必要なファイルであることが分かるので、gcc -c ac -o ao が実行され、bo についても同様になります。

ルール内のコマンドを実行すると、Makefile はターゲット ファイルと依存ファイルの変更時刻を比較します。<br /> 依存ファイルがターゲット ファイルよりも新しい場合、つまり依存ファイルが最後のターゲット生成後に変更されている場合、ターゲット ファイルは再生成されます。
依存ファイルがターゲット ファイルの変更時刻よりも前の場合、つまり依存ファイルが最後のターゲット生成以降に変更されていない場合、対応するコマンドは実行されません。
たとえば、Makefile に対して make を 2 回使用すると、2 回目にはmake: "app" is already up to date というプロンプトが表示されます。

この機能を利用すると、依存関係とターゲットを段階的に生成できます。つまり、上記の 2 番目の Makefile です。このように、ac ファイルのみを変更すると、make は ao ルールと app ルールのみを再度実行します。bc は変更されていないため、bo ルールは実行されません。これにより、リソースの無駄を大幅に削減できます。

Makefile変数

上記によりコンパイルされたコードの重複を減らすことができますが、プロジェクト内に .c .h ファイルが 1,000 個ある場合、Makefile の作成に多くの時間がかかります。したがって、効率を向上させるためにいくつかの変数を採用する必要があります。

変数の取得<br /> 変数を使用するには、$(変数名)を使用します。

カスタム変数<br /> 必要な変数をカスタマイズするには、var = helloなどの変数名 = 変数値を使用します。
たとえば、上記の最初の Makefile は次のように書き直すことができます。

#メイクファイル
rsc = ac bc
app: $(rsc) #ターゲット: gcc に依存 $(rsc) -o app #この行の先頭のインデントに注意してください

定義済み変数<br /> 一部の変数はシステムによって定義されており、直接使用できます。
AR: アーカイブメンテナンスプログラムの名前。デフォルト値はarです。
CC: Cコンパイラの名前。デフォルト値はccです。
CXX: C++コンパイラの名前。デフォルト値はg++です。
$@: ターゲットのフルネーム
$<: 最初の依存ファイルの名前
$^: すべての依存ファイルの名前
<br /> 以下の例を理解しやすくするために、Makefile でのパターン マッチングについて簡単に説明します。
%.o:%.cでは、 % は文字列に一致するワイルドカード文字ですが、 2 つの % は同じ文字列に一致します。
たとえば、上記の 2 番目の Makefile は次のように書き直すことができます。

#メイクファイル
rcs = アオボ
アプリ: $(rcs)
	$(CC) $(rcs) -o $@
%.o: %.c #上記のルールはこのルールを2回実行します $(CC) -c $< -o $@

Makefile関数

上記の Makefile は比較的シンプルですが、プロジェクト内のファイル数が多いという問題は解決されていません。rcs を取得するには、コンパイルする必要がある各ファイルを入力する必要があります。次に、関数を使用してこれらの依存ファイルを書き込む必要があります。

$(ワイルドカードパターン. . .)
この関数の機能は、指定されたディレクトリ内の指定されたタイプのファイルを取得することです。
パラメータ PATTERN は、特定のディレクトリ内の特定のタイプのファイルです。複数のディレクトリと複数のタイプはスペースで区切ることができます。
戻り値は、ファイル名がスペースで区切られた複数のファイルのファイル リストです。

例えば:

$(ワイルドカード ./*.c) は、現在のディレクトリ内の接尾辞 c を持つすべてのファイルを返します。

$(patsubst パターン、置換、テキスト)
この関数の機能は、テキスト内の単語がパターンに一致するかどうかを調べることです。一致する場合は、replacement で置き換えられます。
パターンにはワイルドカード文字 % を含めることができます。置換にも % が含まれている場合、置換内の % はパターン内の % と一致します。
戻り値は置換された文字列です。

例えば:

$(patsubst %.c, %.o, ac, bc) は ao、bo を返します。

このようにして、上記の例は次のように書き直すことができます。

#メイクファイル
rcs = $(ワイルドカード ./*.c)
objs = (patsubst %.c、%.o、$(src))
アプリ: $(objs)
	$(CC) $(オブジェクト) -o $@
%.o: %.c #上記のルールはこのルールを2回実行します $(CC) -c $< -o $@

Makefile クリーンルール

make コマンドを実行すると、現在のディレクトリに o という接尾辞を持つファイルが多数あることがわかりますが、必要なのは最終的なターゲット ファイル app のみで、その他は冗長です。どのように対処すればよいでしょうか。クリーンルールは、それらに対処するのに役立ちます。

クリーン

Makefile の最後に clean ルールを追加するだけで、各コンパイルが完了した後に clean ルール内のコマンドを実行できます。のように:

#メイクファイル
rcs = $(ワイルドカード ./*.c)
objs = (patsubst %.c、%.o、$(src))
アプリ: $(objs)
	$(CC) $(オブジェクト) -o $@
%.o: %.c #上記のルールはこのルールを2回実行します $(CC) -c $< -o $@
クリーン:
	rm $(objs) -f #rm コマンド delete -f 反復削除

ただし、現在のディレクトリには余分な clean ターゲット ファイルがあることがわかります。Makefile 戦略は引き続き使用されます。変更時間を比較すると、多くの場合、時間内に clean を実行してもファイルをクリアできません。その場合は、次の操作が必要です。

clean を疑似ターゲットとして定義します (つまり、.PHONY:clean)。そうすると、ターゲット ファイルは生成されず、比較も行われず、毎回実行されます。

例えば:

#メイクファイル
rcs = $(ワイルドカード ./*.c)
objs = (patsubst %.c、%.o、$(src))
アプリ: $(objs)
	$(CC) $(オブジェクト) -o $@
%.o: %.c #上記のルールはこのルールを2回実行します $(CC) -c $< -o $@
.PHONY: clean #疑似ターゲット clean:
	rm $(objs) -f #rm コマンド delete -f 反復削除

Linux での Makefile の記述と使用に関するこの記事はこれで終わりです。Linux Makefile の記述と使用に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Linux の Makefile とは何ですか? どのように機能しますか?
  • Linux での makefile コマンド パッケージの定義と使用
  • Linux での makefile の理解

<<:  Bootstrap 3.0 学習ノートボタンスタイル

>>:  Vue + Axios リクエストインターフェース方式とパラメータ渡し方式の詳しい説明

推薦する

UbuntuにMySQLデータベースをインストールする方法

Ubuntu は、Linux をベースにした無料のオープンソース デスクトップ PC オペレーティン...

CSS3 でテキストマーキーを実装するためのサンプルコード

背景何が起こったかというと、Luzhu は偶然、宇宙で最高の外部スピーカーを備えた携帯電話について知...

Linux でファイルを削除するときに「操作は許可されていません」というプロンプトが表示される場合の対処方法

同僚からよく聞かれるのですが、ファイル/ディレクトリを削除すると「操作は許可されていません」というエ...

CSS ブラウザ互換性の問題に対する 4 つの解決策

フロントエンドは、技術が急速に進化するだけでなく、知っておくべき事柄が多すぎるという理由で大変な仕事...

ウェブサイトのパフォーマンスを向上させるためのウェブサーバーの改善

<br />このシリーズの最初のセクションでは、Web サイトのパフォーマンスを向上させ...

CocosCreator 入門チュートリアル: TS で初めてのゲームを作る

目次前提TypeScript と JavaScriptコードエディタの選択TypeScriptを学ぶ...

動的画像読み込み技術の応用とjquery.lazyloadプラグインの使用例

アプリケーション例ウェブサイト http://www.uhuigou.net画像の動的読み込みは目新...

CocosCreator MVCアーキテクチャの詳細な説明

概要この記事では、ゲームクライアントでよく使用される MVC アーキテクチャについて紹介します。ゲー...

MySQLからMariaDBへのスムーズな移行のための詳細な手順

1. MariaDB と MySQL の紹介1. MariaDB の紹介MariaDB は、MySQ...

MySQL の日付フォーマットと複雑な日付範囲クエリ

目次序文クエリの使用シナリオ例時間間隔クエリクエリ日付と今日の時間の比較データ一般的なサイクルタイム...

ウェブデザイナーは適した人材

<br />この世に道はない。より多くの人が歩くようになると、それは道になります。最初は...

MySQL ルートパスワードを変更する複数の方法 (推奨)

方法1: SET PASSWORDコマンドを使用する MySQL -u ルート mysql> ...

クールなIoT大画面機能を実現するHTML+VUEページング

効果デモ.html <html> <ヘッド> <メタ文字セット=&qu...

JavaScript にはすでに Object があるのに、なぜ Map が必要なのでしょうか?

目次1. オブジェクトをマップとして扱わない1. 未定義のプロパティはプロトタイプチェーンを通じてア...

CSS の :focus-within の楽しさについて簡単に説明します

Bステーションでパスワードを入力するときに目を覆っているこの画像を見たことがある人もいると思いますこ...