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 リクエストインターフェース方式とパラメータ渡し方式の詳しい説明

推薦する

iPhone デバイスの WAP ページでフォントサイズが大きい問題の解決策

JavaScriptコントロールを使用したくない場合は、次の方法を試してください。 Safariブラ...

Win10にMySQL8圧縮パッケージ版をインストールするチュートリアル

1 公式サイトからMySQL8をダウンロードしてインストールするMySQL8 ダウンロードアドレスこ...

JavaScript を使用してタイムラインとアニメーション効果を実装するためのサンプル コード (フロントエンドのコンポーネント化)

目次コードのクリーニングJavaScript の「フレーム」 「フレーム」の実装方法1. 間隔を設定...

1 つの記事で Vue ミドルウェア パイプラインを学ぶ

SPA を構築する場合、多くの場合、特定のルートを保護する必要があります。たとえば、認証されたユーザ...

Windows で削除された MySQL 8.0.17 のルート アカウントとパスワードを回復する方法

少し前にSQLの独学を終え、MySQL 8.0.17をダウンロードしました。インストールして設定した...

複雑なSQLクエリを含むMySQLの一般的なSQL文の概要

1. 複雑なSQLクエリ1.1. 単一テーブルクエリ(1)指定の列を選択する[例] 全生徒の生徒ID...

Linux環境でglogログライブラリを使用する方法

Linuxライブラリを生成するLinux版はcentos7.3を使用し、コンパイルしてライブラリを生...

Vueは買い物数量を変更できるショッピングカートを実装します

この記事では、Vueを使用してショッピングカートの数量を変更する方法を紹介します。具体的な内容は次の...

DIV と画像の水平および垂直の中央揃えは複数のブラウザと互換性があります

最初のタイプ: 完全な CSS コントロール、レイヤーフローティング (ログインページに適しています...

Flash が HTML div 要素を覆わないようにする方法

今日、フラッシュ広告のコードを書いていたとき、フラッシュに付属するリンクはポップアップ広告と間違われ...

Maven プロジェクトのリモート デプロイメント && Tomcat を使用してデータベース接続を構成する方法

1つ。 tomcat を使用したリモート展開1.1 発生した問題:プロジェクトでは、サードパーティの...

MySQL サブクエリとグループ化されたクエリ

目次概要サブクエリサブクエリの分類クエリの結果によるとサブクエリの位置で区別する選択後のサブクエリサ...

nginx 設定ファイルパスとリソースファイルパスを表示する方法

nginx 設定ファイルのパスを表示する nginx -t 経由nginx -t コマンドの本来の機...

React における useEffect と useLayoutEffect の違い

目次前提条件使用効果コミット前ミューテーション効果コミットミューテーション効果コミットレイアウト効果...

Vue のリスナーの基本的な使用例

目次序文1. リスナーの基本的な使い方2. リスナー形式3. ページに入るとすぐに監視とディープモニ...