CFLAGSとCPPFLAGS


103

CFLAGS(またはC ++の場合はCXXFLAGS)はコンパイラー用であり、CPPFLAGSはプリプロセッサーによって使用されることを理解しています。

しかし、私はまだ違いを理解していません。

#includeでインクルードされるヘッダーファイルのインクルードパスを指定する必要があります-#includeはプリプロセッサディレクティブなので、プリプロセッサ(CPPFLAGS)だけが重要ですか?

コンパイラーに追加のインクルードパスを与える必要があるのはどのような場合ですか?

一般に、プリプロセッサが必要なヘッダーファイルを見つけてインクルードする場合、なぜ追加のインクルードディレクトリについて通知する必要があるのですか?CFLAGSの用途は何ですか?

(私の場合、実際にはこれらの両方でプログラムをコンパイルできるため、混乱を招きます... CFLAGS または CPPFLAGSを使用して(少なくともautoconfコンテキストで)目標を達成できます。何が得られますか?)


回答:


153

Cプログラムをコンパイルするための暗黙のmakeルールは次のとおりです。

%.o:%.c
    $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

ここで、$()構文は変数を展開します。両方のとおりCPPFLAGSCFLAGSあなたがパスを含める定義するために使用したコンパイラの呼び出しで使用されている、個人の好みの問題です。たとえばfoo.c、現在のディレクトリにあるファイルの場合

make foo.o CPPFLAGS="-I/usr/include"
make foo.o CFLAGS="-I/usr/include"

両方ともコンパイラをまったく同じ方法で呼び出します。

gcc -I/usr/include -c -o foo.o foo.c

あなたが持っている場合は、同じを必要とする複数の言語は、インスタンスのパスを、含まれていたときに2つの違いは、場に出たbar.cpp後、してみてください

make bar.o CPPFLAGS="-I/usr/include"
make bar.o CFLAGS="-I/usr/include"

その後、コンパイルは

g++ -I/usr/include -c -o bar.o bar.cpp
g++ -c -o bar.o bar.cpp

C ++の暗黙のルールもCPPFLAGS変数を使用するため。

この違いは、使用するための適切なガイドを提供します-フラグをすべての言語に使用するCPPFLAGS場合は、それを特定の言語に使用するCFLAGS場合CXXFLAGSなど。後者のタイプの例には、標準準拠フラグまたは警告フラグが含まれます。 -あなたは-std=c99あなたのC ++コンパイラに渡したくないでしょう!

その後、メイクファイルでこのようなものになる可能性があります

CPPFLAGS=-I/usr/include
CFLAGS=-std=c99
CXXFLAGS=-Weffc++

1
(特に機能テストマクロの代わりに)定義されているシンボルに影響を与えるため、スタンドアロンcppを使用して実行CPPFLAGSしても妥当な結果を期待できないことに注意してください-std=c99。代わりに、が必要$(CC) $(CPPFLAGS) $(CFLAGS) -Eです。
Jed

10

CPPFLAGSマクロは、指定に使用する1つである#includeディレクトリを。

両方CPPFLAGSCFLAGSあなたのケースで動作するため、make(1)ルールは、前処理と(両方のマクロコマンドで使用されるように)1つのコマンドでコンパイルの両方を兼ね備えています。

.フォームを使用する場合は、include-directoryとして指定する必要はありません#include "..."。また、標準コンパイラのインクルードディレクトリを指定する必要もありません。他のすべてのインクルードディレクトリを指定する必要があります。


これはもっと理にかなっていますが、CFLAGSが何をするのかはまだわかりません。あなたが示唆しているように、より複雑なプロジェクトでのコンパイルが前処理とは別のステップで行われる場合、前処理は成功しますが、CPPFLAGSがプリプロセッサ用に追加したのと同じパスをCFLAGSが追加しない場合、コンパイルは失敗しますか?プリプロセッサがすでに#includeディレクティブを処理している場合、コンパイラがインクルードパスをどのように処理するのか理解できません。
EBM

4
@EB前処理されたファイルをコンパイルする場合、インクルードパスは不要です-必要なヘッダーは前処理されたソースにすでに追加されています(gcc -Eファイルで実行するときに出力を確認してください-#includeはありません)。最近のほとんどのコンパイラーは、前処理とコンパイルのステップを組み合わせているため、これについて心配する必要はありません。
スコットウェールズ


0

暗黙のルールについて言及している人に追加するには、makeが暗黙的に定義しているものを確認し、環境を使用して以下を使用するのが最善です。

make -p

例えば:

%.o: %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

拡大する

COMPILE.c = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c

これにより、# environmentデータも印刷されます。ここでは、GCCのインクルードパスが他の役立つ情報の中で見つかります。

C_INCLUDE_PATH=/usr/include

まとめると、検索に関しては、パスは多く、光は1つです...またはそのための何か。

  1. C_INCLUDE_PATHシステム全体に適用されるため、シェルので設定します*.rc
  2. $(CPPFLAGS) プリプロセッサのインクルードパス用です。
  3. makeの一般的な検索パスを追加する必要がある場合は、次を使用します。
VPATH = my_dir_to_search

...またはさらに具体的

vpath %.c src
vpath %.h include

makeは一般的な検索パスとしてVPATHを使用するため、慎重に使用してください。VPATHにリストされている複数の場所にファイルが存在する場合、makeはリストの最初に出現するものを取得します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.