Linux の Makefile とは何ですか? どのように機能しますか?

Linux の Makefile とは何ですか? どのように機能しますか?

この便利なツールでプログラムをより効率的に実行およびコンパイルします
Makefile は自動コンパイルとリンクに使用されます。プロジェクトは多数のファイルで構成されます。ファイルに変更を加えると、プロジェクトが再リンクされます。ただし、すべてのファイルを再コンパイルする必要はありません。Makefile はファイル情報を記録し、リンク時に再コンパイルする必要があるファイルを決定できます。

make ツールは通常、一部のソース ファイルが変更された後にタスクを実行または更新する必要がある場合に使用されます。 make ツールは、実行される一連のタスクを定義する Makefile (または makefile) ファイルを読み取る必要があります。 make を使用してソース コードを実行可能プログラムにコンパイルできます。ほとんどのオープンソース プロジェクトでは、make を使用して最終的なバイナリ ファイルをコンパイルし、make install コマンドを使用してインストールを実行します。
この記事では、いくつかの基本的な例と高度な例を通して、make と Makefile の使用方法を説明します。始める前に、システムに make がインストールされていることを確認してください。

基本的な例は、依然として「Hello World」を印刷することから始まります。まず、myproject という名前のディレクトリを作成し、そのディレクトリ内に次の内容の Makefile ファイルを作成します。

こんにちは:
「こんにちは世界」をエコーし​​ます

myproject ディレクトリで make を実行すると、次の出力が表示されます。

$ 作る
「こんにちは世界」をエコーし​​ます
こんにちは世界

上記の例では、「say_hello」は他のプログラミング言語の関数名に似ています。これをターゲットといいます。ターゲットの後に、前提条件または依存関係が続きます。簡潔にするために、この例では前提条件を定義しませんでした。 echo 'Hello World' コマンドはレシピと呼ばれます。これらのステップは、目標を達成するための前提条件に基づいています。目標、前提条件、および手順が組み合わさってルールが構成されます。

要約すると、典型的なルールの構文は次のようになります。

目的: 前提条件
<TAB> 手順

たとえば、ターゲットは、前提条件 (ソース コード) に基づいたバイナリ ファイルになる場合があります。一方、前提条件は、他の前提条件に依存するターゲットになることもできます。

final_target: サブターゲット final_target.c
最終ターゲットを作成するためのレシピ
サブターゲット: sub_target.c
サブターゲットを作成するレシピ

ターゲットはファイルである必要はなく、この例のようにステップの名前だけにすることもできます。これを「疑似ターゲット」と呼びます

上記の例に戻ると、make が実行されると、コマンド全体 echo "Hello World" が表示され、その後に実際の実行結果が表示されます。コマンド自体を印刷したくない場合は、echo の前に @ を追加する必要があります。

こんにちは:
@echo "こんにちは世界"

make を再度実行すると、次の出力が表示されます。

$ 作る
こんにちは世界

次に、Makefile に次の疑似ターゲットを追加します: generate および clean:

こんにちは:
@echo "こんにちは世界"
生成する:
@echo "空のテキスト ファイルを作成しています..."
タッチファイル-{1..10}.txt
クリーン:
@echo "クリーンアップ中..."
rm *.txt

後で make を実行すると、 say_hello ターゲットのみが実行されます。これは、Makefile の最初のターゲットがデフォルトのターゲットであるためです。通常、デフォルトのターゲットが呼び出されます。これは、ほとんどのプロジェクトの最初のターゲットとして表示されるものです: all。 all はターゲットを呼び出す責任があります。特別な疑似目標.DEFAULT_GOAL を使用して、デフォルトの動作をオーバーライドできます。

Makefile の先頭に .DEFAULT_GOAL を追加します。

.DEFAULT_GOAL := generate

Make は、generate をデフォルトのターゲットとして使用します。

$ 作る
空のテキスト ファイルを作成しています...
タッチファイル-{1..10}.txt

名前が示すように、.DEFAULT_GOAL 疑似ターゲットは 1 つの目標のみを定義できます。このため、多くの Makefile には、複数のターゲットを呼び出すことができるターゲット all が含まれています。
次に、.DEFAULT_GOAL を削除し、all 目標を追加します。

すべて: say_hello 生成
こんにちは:
@echo "こんにちは世界"
生成する:
@echo "空のテキスト ファイルを作成しています..."
タッチファイル-{1..10}.txt
クリーン:
@echo "クリーンアップ中..."
rm *.txt

実行する前に、いくつかの特別な疑似ターゲットを追加しましょう。 .PHONY は、ファイルではないターゲットを定義するために使用されます。デフォルトでは、make はファイル名や最終変更日の存在を確認せずに、これらの疑似ターゲットの下のステップを呼び出します。完全な Makefile は次のとおりです。

.PHONY: すべて say_hello 生成クリーン
すべて: say_hello 生成
こんにちは:
@echo "こんにちは世界"
生成する:
@echo "空のテキスト ファイルを作成しています..."
タッチファイル-{1..10}.txt
クリーン:
@echo "クリーンアップ中..."
rm *.txt

make コマンドは say_hello を呼び出して次を生成します。

$ 作る
こんにちは世界
空のテキスト ファイルを作成しています...
タッチファイル-{1..10}.txt

clean は all や first ターゲットには入れないでください。 cleanは、クリーニングが必要な場合に手動で呼び出す必要があります。呼び出しメソッドはmake cleanです。

$ クリーンにする
掃除中…
rm *.txt

Makefile の基本を理解できたので、次は高度な例を見てみましょう。

高度な例 変数 前の例では、ターゲットと前提条件のほとんどは固定されていましたが、実際のプロジェクトでは通常、それらは変数とパターンに置き換えられます。

変数を定義する最も簡単な方法は、= 演算子を使用することです。たとえば、コマンド gcc を変数 CC に割り当てるには、次のようにします。

CC = gcc

これは再帰変数拡張と呼ばれ、次のようなルールで使用されます。

こんにちは: hello.c
${CC} hello.c -o hello

ご想像のとおり、これらの手順は次のように拡張されます。

gcc hello.c -o hello

${CC} と $(CC) はどちらも gcc を参照できます。しかし、変数が自分自身に代入しようとすると、無限ループが発生します。これを検証してみましょう:

CC = gcc
CC = ${CC}
全て:
@echo ${CC}

この時点で make を実行すると、次の結果になります。

$ 作る
Makefile:8: *** 再帰変数 'CC' は (最終的に) 自分自身を参照します。停止します。

これを回避するには、:= 演算子を使用します (これは単純な変数展開と呼ばれます)。次のコードでは上記の問題は発生しません。

CC := gcc
CC := ${CC}
全て:
@echo ${CC}

モードと関数 次の Makefile は、変数、モード、および関数を使用してすべての C コードをコンパイルします。行ごとに分析してみましょう。

# 使用法:
# make # すべてのバイナリをコンパイル
# make clean # すべてのバイナリとオブジェクトを削除
.PHONY = すべてクリーン
CC = gcc # 使用するコンパイラ
リンカーフラグ = -lm
SRCS := $(ワイルドカード *.c)
ビン:= $(SRCS:%.c=%)
すべて: ${BINS}
%: %.o
@echo "確認中..."
${CC} ${LINKERFLAG} $< -o $@
%.o: %.c
@echo "オブジェクトを作成しています。"
${CC} -c $<
クリーン:
@echo "クリーンアップ中..."
rm -rvf *.o ${BINS}

#で始まる行はコメントです
.PHONY = all clean という行は、 all と clean という 2 つの疑似ターゲットを定義します。
変数 LINKERFLAG は、gcc コマンドがステップで使用する必要があるパラメータを定義します。
SRCS := $(ワイルドカード *.c): $(ワイルドカード パターン) はファイル名に関連する関数です。この例では、「.c」サフィックスを持つすべてのファイルが SRCS 変数に保存されます。
BINS := $(SRCS:%.c=%): これは置換参照と呼ばれます。この例では、SRCS の値が「foo.c bar.c」の場合、BINS の値は「foo bar」になります。
all: ${BINS}: という行は、疑似ターゲット all は ${BINS} 変数内のすべての値をサブターゲットとして呼び出します。
ルール:

%: %.o
@echo "確認中..."
${CC} ${LINKERFLAG} $< -o $@

このルールを理解するために例を見てみましょう。 foo が変数 ${BINS} の値であると仮定します。 % は foo に一致します (% は任意のターゲットに一致します)。拡張後のルールは次のようになります。

foo: foo.o
@echo "確認中..."
gcc -lm foo.o -o foo

上記のように、% は foo に置き換えられます。 $< は foo.o に置き換えられます。 $< は事前設定された条件に一致させるために使用され、 $@ はターゲットに一致します。このルールは、${BINS} 内の各値に対して 1 回呼び出されます。
ルール:

%.o: %.c
@echo "オブジェクトを作成しています。"
${CC} -c $<

前のルールの各前提条件は、このルールではターゲットとして扱われます。展開後の外観は次のようになります。

foo.o: foo.c
@echo "オブジェクトを作成しています。"
gcc -c foo.c

最後に、 clean ターゲットでは、すべてのバイナリとコンパイル済みファイルが削除されます。
以下は書き直された Makefile です。これは foo.c ファイルと同じディレクトリに配置する必要があります。

# 使用法:
# make # すべてのバイナリをコンパイル
# make clean # すべてのバイナリとオブジェクトを削除
.PHONY = すべてクリーン
CC = gcc # 使用するコンパイラ
リンカーフラグ = -lm
SRCS := foo.c
ビン:= foo
全員: foo
foo: foo.o
@echo "確認中..."
gcc -lm foo.o -o foo
foo.o: foo.c
@echo "オブジェクトを作成しています。"
gcc -c foo.c
クリーン:
@echo "クリーンアップ中..."
rm -rvf foo.o foo

これらが一緒になって makefile を形成します。もちろん、これらの関数は少なすぎるため、他の多くのプロジェクトを追加することもできます。しかし、目的は、ファイルをコンパイルするためにどの他のファイルに依存する必要があるかをコンパイラに知らせることです。これらの依存ファイルが変更されると、コンパイラは最終的に生成されたファイルが古くなっていることを自動的に検出し、対応するモジュールを再コンパイルします。

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。これについてもっと知りたい場合は、次のリンクをご覧ください。

以下もご興味があるかもしれません:
  • Linux での makefile コマンド パッケージの定義と使用
  • Linux での makefile の理解
  • Linux での Makefile の書き方と使い方の詳細な説明

<<:  Linux での MySQL 5.7.17 の最新安定バージョンのインストール チュートリアル

>>:  Vue が Ref を使用してレベル間でコンポーネントを取得する手順

推薦する

jsドラッグ効果の原理と実装

ドラッグ機能は主に、ドラッグによる並べ替え、ポップアップ ボックスのドラッグと移動など、ユーザーがカ...

MySQL のあまり知られていないソート方法

序文ORDER BY 字段名升序/降序、このソートステートメントは皆さんご存知だと思いますが、特殊な...

mysql8.0.18 で winx64 をインストールするための詳細なチュートリアル (画像とテキスト付き)

MySQLデータベースをダウンロードするには、https://dev.mysql.com/down...

Docker MQTT のインストールと使用のチュートリアル

MQTT の紹介MQTT (Message Queuing Telemetry Transport)...

html2canvas で破線境界線を実装する例

html2canvas は、HTML 要素からキャンバスを生成するライブラリです。描画されるキャンバ...

Tencent Cloud 上で Hadoop 3.x 疑似クラスターを構築する方法を説明します

1. 環境整備CentOS Linux リリース 7.5.1804 (コア)インストールフォルダを作...

MySQL テーブルにおける非主キー列オーバーフロー監視の詳細な説明

今日もまた罠に落ちてしまいました。 私は以前MySQLの主キーオーバーフローに遭遇したことがあり、そ...

純粋なCSSでデジタルプラスとマイナスボタンを実装するための最適なソリューション

序文:デジタル加算ボタンと減算ボタンの実装には、次のような多くのソリューションがこれまでに使用されて...

ウェブフロントエンドエンジニアにおすすめのヒント

まず、Webフロントエンドエンジニアの価値についてお話ししましょう。現在、Web製品のインタラクショ...

MySQL のテーブル内のレコード数を制限する方法

目次1. トリガーソリューション2. パーティションテーブルソリューション3. 一般的な表領域ソリュ...

jQuery で呼吸カルーセル効果を実現

この記事では、呼吸カルーセル効果を実現するためのjQueryの具体的なコードを参考までに共有します。...

MySQL ステートメントを使用して、さまざまな整数が占めるバイト数とその最大値と最小値を調べる例

直接コード: タイプとして「bigint unsigned」、バイトとして「8」、max_numとし...

React Nativeでaxiosを使用してネットワークリクエストを行う方法

フロントエンド開発では、Ajax、jQuery ajax、axios、fetch など、データ要求を...

Linux でのファイル コンテンツの重複排除と交差と差異の実装

1. データ重複排除日常業務では、Hive や Impala を使用してクエリとエクスポートを行う際...