特定のファイルが更新されたときにタスクを実行または更新する場合は、make
ユーティリティが重宝します。 make
ユーティリティにはファイルMakefile
が必要です (またはmakefile
)、実行するタスクのセットを定義します。 make
を使用した可能性があります ソースコードからプログラムをコンパイルします。ほとんどのオープンソースプロジェクトはmake
を使用します 最終的な実行可能バイナリをコンパイルします。これは、make install
を使用してインストールできます。 。
この記事では、make
について説明します。 およびMakefile
基本的な例と高度な例を使用します。開始する前に、make
を確認してください システムにインストールされています。
基本的な例
まず、端末にクラシックな「HelloWorld」を印刷してみましょう。空のディレクトリmyproject
を作成します ファイルを含むMakefile
このコンテンツで:
say_hello:
echo "Hello World"
次に、make
と入力してファイルを実行します ディレクトリmyproject
内 。出力は次のようになります:
$ make
echo "Hello World"
Hello World
上記の例では、say_hello
他のプログラミング言語と同様に、関数名のように動作します。これはターゲットと呼ばれます 。 前提条件 または依存関係 ターゲットに従ってください。簡単にするために、この例では前提条件を定義していません。コマンドecho "Hello World"
レシピと呼ばれます 。 レシピ 前提条件を使用します ターゲットを作成する 。ターゲット、前提条件、レシピが一緒になってルールを作成します 。
要約すると、以下は典型的なルールの構文です:
target: prerequisites
<TAB> recipe
例として、ターゲットは前提条件(ソースファイル)に依存するバイナリファイルである可能性があります。一方、前提条件は、他の依存関係に依存するターゲットになることもあります。
final_target: sub_target final_target.c
Recipe_to_create_final_target
sub_target: sub_target.c
Recipe_to_create_sub_target
ターゲットがファイルである必要はありません。この例のように、レシピの単なる名前である可能性があります。これらを「偽のターゲット」と呼びます。
上記の例に戻ると、make
コマンド全体が実行され、echo "Hello World"
が表示され、続いて実際のコマンド出力が表示されました。私たちはしばしばそれを望んでいません。実際のコマンドのエコーを抑制するには、echo
を開始する必要があります @
で :
say_hello:
@echo "Hello World"
次に、make
を実行してみます また。出力にはこれだけが表示されます:
$ make
Hello World
さらにいくつかの偽のターゲットを追加しましょう:generate
およびclean
Makefile
に :
say_hello:
@echo "Hello World"
generate:
@echo "Creating empty text files..."
touch file-{1..10}.txt
clean:
@echo "Cleaning up..."
rm *.txt
make
を実行しようとすると 変更後は、ターゲットのsay_hello
のみ 実行されます。これは、makefileの最初のターゲットのみがデフォルトのターゲットであるためです。多くの場合、デフォルトの目標と呼ばれます 、これがall
が表示される理由です ほとんどのプロジェクトの最初のターゲットとして。 all
の責任です 他のターゲットを呼び出すため。 .DEFAULT_GOAL
と呼ばれる特別な偽のターゲットを使用して、この動作をオーバーライドできます。 。
makefileの先頭にそれを含めましょう:
.DEFAULT_GOAL := generate
これにより、ターゲットのgenerate
が実行されます デフォルトとして:
$ make
Creating empty text files...
touch file-{1..10}.txt
名前が示すように、偽のターゲット.DEFAULT_GOAL
一度に実行できるターゲットは1つだけです。これが、ほとんどのmakefileにall
が含まれている理由です。 必要な数のターゲットを呼び出すことができるターゲットとして。
偽のターゲットall
を含めましょう .DEFAULT_GOAL
を削除します :
all: say_hello generate
say_hello:
@echo "Hello World"
generate:
@echo "Creating empty text files..."
touch file-{1..10}.txt
clean:
@echo "Cleaning up..."
rm *.txt
make
を実行する前に 、別の特別な偽のターゲット、.PHONY
を含めましょう 、ファイルではないすべてのターゲットを定義します。 make
その名前のファイルが存在するかどうか、またはその最終変更時刻が何であるかに関係なく、レシピを実行します。完全なmakefileは次のとおりです:
.PHONY: all say_hello generate clean
all: say_hello generate
say_hello:
@echo "Hello World"
generate:
@echo "Creating empty text files..."
touch file-{1..10}.txt
clean:
@echo "Cleaning up..."
rm *.txt
make
say_hello
を呼び出す必要があります およびgenerate
:
$ make
Hello World
Creating empty text files...
touch file-{1..10}.txt
clean
を呼び出さないことをお勧めします all
またはそれを最初のターゲットとして置きます。 clean
make
の最初の引数としてクリーニングが必要な場合は、手動で呼び出す必要があります :
$ make clean
Cleaning up...
rm *.txt
基本的なmakefileがどのように機能し、簡単なmakefileを作成するかがわかったところで、さらに高度な例を見てみましょう。
高度な例
変数
その他のLinuxリソース
- Linuxコマンドのチートシート
- 高度なLinuxコマンドのチートシート
- 無料のオンラインコース:RHELの技術概要
- Linuxネットワーキングのチートシート
- SELinuxチートシート
- Linuxの一般的なコマンドのチートシート
- Linuxコンテナとは何ですか?
- 最新のLinux記事
上記の例では、ほとんどのターゲット値と前提条件値がハードコーディングされていますが、実際のプロジェクトでは、これらは変数とパターンに置き換えられています。
makefileで変数を定義する最も簡単な方法は、=
を使用することです。 オペレーター。たとえば、コマンドgcc
を割り当てるには 変数CC
に :
CC = gcc
これは、再帰展開変数とも呼ばれます。 、および以下に示すようなルールで使用されます:
hello: hello.c
${CC} hello.c -o hello
ご想像のとおり、レシピはターミナルに渡されると次のように拡張されます。
gcc hello.c -o hello
両方の${CC}
および$(CC)
gcc
を呼び出すための有効な参照です 。しかし、変数をそれ自体に再割り当てしようとすると、無限ループが発生します。これを確認しましょう:
CC = gcc
CC = ${CC}
all:
@echo ${CC}
make
を実行しています 結果は次のようになります:
$ make
Makefile:8: *** Recursive variable 'CC' references itself (eventually). Stop.
このシナリオを回避するために、:=
を使用できます 演算子(これは単に展開された変数とも呼ばれます )。以下のmakefileの実行に問題はありません:
CC := gcc
CC := ${CC}
all:
@echo ${CC}
パターンと機能
次のmakefileは、変数、パターン、および関数を使用して、すべてのCプログラムをコンパイルできます。行ごとに調べてみましょう:
# Usage:
# make # compile all binary
# make clean # remove ALL binaries and objects
.PHONY = all clean
CC = gcc # compiler to use
LINKERFLAG = -lm
SRCS := $(wildcard *.c)
BINS := $(SRCS:%.c=%)
all: ${BINS}
%: %.o
@echo "Checking.."
${CC} ${LINKERFLAG} $< -o $@
%.o: %.c
@echo "Creating object.."
${CC} -c $<
clean:
@echo "Cleaning up..."
rm -rvf *.o ${BINS}
-
#
で始まる行 コメントです。 -
行
.PHONY = all clean
偽のターゲットを定義するall
およびclean
。 -
変数
LINKERFLAG
gcc
で使用されるフラグを定義します レシピで。 -
SRCS := $(wildcard *.c)
:$(wildcard pattern)
ファイル名の関数の1つです 。この場合、.c
を持つすべてのファイル 拡張子は変数SRCS
に保存されます 。 -
BINS := $(SRCS:%.c=%)
:これは置換参照と呼ばれます 。この場合、SRCS
値は'foo.c bar.c'
、BINS
'foo bar'
があります 。 -
行
all: ${BINS}
:偽のターゲットall
${BINS}
の値を呼び出します 個別のターゲットとして。 -
ルール:
%: %.o
@echo "Checking.."
${CC} ${LINKERFLAG} $< -o $@このルールを理解するために例を見てみましょう。
foo
と仮定します${BINS}
の値の1つです 。次に%
foo
と一致します (%
任意のターゲット名に一致できます)。以下は、拡張された形式のルールです。foo: foo.o
@echo "Checking.."
gcc -lm foo.o -o foo示されているように、
%
foo
に置き換えられます 。$<
foo.o
に置き換えられます 。$<
前提条件と$@
に一致するようにパターン化されています ターゲットに一致します。このルールは、${BINS}
のすべての値に対して呼び出されます -
ルール:
%.o: %.c
@echo "Creating object.."
${CC} -c $<前のルールのすべての前提条件は、このルールのターゲットと見なされます。以下は、拡張された形式のルールです。
foo.o: foo.c
@echo "Creating object.."
gcc -c foo.c -
最後に、ターゲットの
clean
内のすべてのバイナリとオブジェクトファイルを削除します 。
以下は、単一のファイルfoo.c:
を持つディレクトリに配置されていると仮定して、上記のmakefileを書き直したものです。
# Usage:
# make # compile all binary
# make clean # remove ALL binaries and objects
.PHONY = all clean
CC = gcc # compiler to use
LINKERFLAG = -lm
SRCS := foo.c
BINS := foo
all: foo
foo: foo.o
@echo "Checking.."
gcc -lm foo.o -o foo
foo.o: foo.c
@echo "Creating object.."
gcc -c foo.c
clean:
@echo "Cleaning up..."
rm -rvf foo.o foo
makefileの詳細については、完全なリファレンスと例を提供するGNUMakeマニュアルを参照してください。
また、GNU Autotoolsの概要を読んで、コーディングプロジェクトのmakefileの生成を自動化する方法を学ぶこともできます。