メイクファイルシンボル$ @と$ <はどういう意味ですか?


416
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
    $(CC) $(CFLAGS) $< -o $@

何を$@して$<正確ですか?


5
上記のリンクは壊れています、これは別のものです:gnu.org/software/make/manual/html_node/Automatic-Variables.html
asciz

1
こんにちは、この ".cpp.o:"はターゲットとして何を意味しますか?(前の最後の行?)。
pseudonym_127

3
".cpp.o:"は、 "。cpp"(ソースファイル)から ".o"(オブジェクトファイル)をビルドすることを意味します
jaguzu

1
Mohitが彼の投稿でmakefileを取得したと私が信じている次のリンクにmakeチュートリアルがあることに注意すべきです。mrbook.org/blog/tutorials/make
DeepDeadpool

Microsoftはそれをファイル名マクロ(NMAKEの場合)と呼び、自動変数(MAKEの場合)よりも明確です。教育目的で両側を確認すると便利です。
Ivanzinho

回答:


502

$@生成されるファイルの名前であり$<、最初の前提条件(通常はソースファイル)です。これらすべての特殊変数のリストは、GNU Makeマニュアルにあります

たとえば、次の宣言について考えてみます。

all: library.cpp main.cpp

この場合:

  • $@ 評価する all
  • $< 評価する library.cpp
  • $^ 評価する library.cpp main.cpp

16
$@必ずしもファイルである必要はないことに注意してください.PHONY。ターゲットの名前でもかまいません。
Ephemera

$@sname.osなどのアセンブリ出力を生成するために、これをコマンドラインオプションに追加できますか?
フセイントゥグルルブキシク2017

4
最初の依存関係がリストを表す変数である場合は、$ <が展開された後に評価されます。したがって、LIST = lib1.cpp lib2.cpp、およびすべて:$ {LIST} main.cppの場合、$ <はlib1.cppのみと評価されます。数年前、私はこの行動によって引き起こされた結果で何が起こっているのかを理解するのにしばらく時間を費やしていました。
チャン・キム

:一般$に@の左側にあるターゲット名を参照する
ディーパックキラン

78

呼ばれている自動変数。変数は、作成されたファイル(ターゲット)の名前を表し、出力ファイルの作成に必要な最初の前提条件を表します。 例えば:$@$<$@$<

hello.o: hello.c hello.h
         gcc -c $< -o $@

これhello.oが出力ファイルです。これは$@拡大するものです。最初の依存関係はhello.cです。それが$<拡大するものです。

-cフラグは生成.oファイル。man gcc詳細な説明については、を参照してください。-o作成する出力ファイルを指定します。

詳細については、Linux Makefileに関するこの記事を参照してください。

また、GNU makeマニュアルも確認できます。Makefileの作成とデバッグが容易になります。

このコマンドを実行すると、makefileデータベースが出力されます。

make -p 

1
あなたの答えは(両方)に$<拡張されるように聞こえhello.c hello.hます。どうか明らかにしてください。
Beco博士、2015

はい、hello.cとhello.hの両方が含まれます
器用な

19
$<最初のアイテムです。すべてを含めるには、を使用します$^
Beco博士、2015

1
ベコ博士は正しいです。著者は彼の答えを修正する必要があります。
PT Huynh、2015年

67

GNUのメイク、第3版、Pでプロジェクトを管理します。16(これはGNU Free Documentation Licenseに基づいています):

自動変数make、ルールが一致した後にによって設定されます。これらは、ターゲットおよび前提条件リストの要素へのアクセスを提供するため、ファイル名を明示的に指定する必要はありません。これらはコードの重複を回避するのに非常に役立ちますが、より一般的なパターンルールを定義する場合には重要です。

7つの「コア」自動変数があります。

  • $@:ターゲットを表すファイル名。

  • $%:アーカイブメンバー指定のファイル名要素。

  • $<:最初の前提条件のファイル名。

  • $?:スペースで区切られた、ターゲットより新しいすべての前提条件の名前。

  • $^:スペースで区切られたすべての前提条件のファイル名。コンパイル、コピーなどのほとんどの用途では重複が不要であるため、このリストでは重複するファイル名が削除されています。

  • $+:と同様に$^$+重複を含む場合を除いて、スペースで区切られたすべての前提条件の名前です。この変数は、重複する値が意味を持つリンカーへの引数などの特定の状況のた​​めに作成されました。

  • $*:ターゲットファイル名の語幹。語幹は通常、サフィックスのないファイル名です。パターンルール外での使用はお勧めしません。

さらに、上記の各変数には、他のメーカーとの互換性のために2つのバリアントがあります。1つのバリアントは、値のディレクトリ部分のみを返します。これは、シンボルに「D」を追加することによって示されている$(@D)$(<D)などの他のバリアント戻り値の唯一のファイル部分。これは、シンボルに「F」を追加することによって示され$(@F)$(<F)これらのバリアント名は括弧で囲む必要があり、複数の文字長いので、あること、などの注意を。GNU makeは、dirおよびnotdir関数を使用して、より読みやすい代替手段を提供します。


37

$@そして$<特殊なマクロです。

どこ:

$@ ターゲットのファイル名です。

$< 最初の依存関係の名前です。


19

Makefileは構築するhelloのいずれかの場合には実行可能ファイルをmain.cpphello.cppfactorial.cpp変更しました。その仕様を達成するための最小のMakefileは次のようになります。

hello: main.cpp hello.cpp factorial.cpp
    g++ -o hello main.cpp hello.cpp factorial.cpp
  • プロ:非常に読みやすい
  • con:メンテナンスの悪夢、C ++依存関係の重複
  • con:効率の問題、1つだけが変更された場合でも、すべてのC ++を再コンパイルします

上記を改善するために、編集されたC ++ファイルのみをコンパイルします。次に、結果のオブジェクトファイルをリンクするだけです。

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

main.o: main.cpp
    g++ -c main.cpp

hello.o: hello.cpp
    g++ -c hello.cpp

factorial.o: factorial.cpp
    g++ -c factorial.cpp
  • pro:効率の問題を修正
  • 短所:新しいメンテナンスの悪夢、オブジェクトファイルの誤植の可能性

これを改善するために、すべてのオブジェクトファイルルールを単一の.cpp.oルールに置き換えることができます。

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

.cpp.o:
    g++ -c $< -o $@
  • pro:やや読みやすい短いmakefileに戻る

ここでは.cpp.oルールが構築する方法を定義しますanyfile.oからanyfile.cpp

  • $< この場合、最初の依存関係に一致します。 anyfile.cpp
  • $@ターゲット、この場合はと一致しanyfile.oます。

Makefileに存在するその他の変更は次のとおりです。

  • コンパイラをg ++から任意のC ++コンパイラに簡単に変更できます。
  • コンパイラー・オプションを簡単に変更できるようにします。
  • リンカオプションの変更を容易にします。
  • C ++ソースファイルと出力の変更を容易にします。
  • アプリケーションをビルドする前に、すべてのソースファイルが存在することを確認するクイックチェックとして機能するデフォルトルール「all」を追加しました。

1

ソースをコンパイルしたいが別のディレクトリにオブジェクトがある場合は、次のようにします。

あなたがする必要があります:

gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...

しかし、ほとんどのマクロでは、結果は次のようにすべてのオブジェクトの後にすべてのソースが続きます。

gcc -c -o <all OBJ path> <all SRC path>

したがって、これは何もコンパイルしません^^で、オブジェクトファイルを別のディレクトリに置くことはできません:(

解決策は、これらの特別なマクロを使用することです

$@ $<

これにより、SRC(src / file.c)の各.cファイルに対して.oファイル(obj / file.o)が生成されます

$(OBJ):$(SRC)
   gcc -c -o $@ $< $(HEADERS) $(FLAGS)

その意味は :

    $@ = $(OBJ)
    $< = $(SRC)

しかし、OBJのすべての行のINSTEAD行と、それに続くSRCのすべての行


「you」の代わりに「u」と入力することで節約した時間をどのように処理するのでしょうか。
Ivanzinho
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.