web-dev-qa-db-ja.com

CFLAGS、CCFLAGS、CXXFLAGS-これらの変数は正確に何を制御しますか?

GNU makeを使用してC++コードをコンパイルしています。コンパイルをカスタマイズ可能にする方法を理解したいと思います。

CFLAGSCCFLAGS、およびCXXFLAGSがこの目的に使用されることをさまざまな場所で読みました。それで、それらをどのように使うべきですか?コンパイラーに追加のコマンドライン引数がある場合、それらをCFLAGSに追加するか、先頭に追加する必要がありますか?一般的な慣行はありますか?

なぜ3つの異なる変数なのでしょうか? CコンパイラはCFLAGSCCFLAGSを取得するはずですが、C++コンパイラはCFLAGSCXXFLAGSを取得する必要があります。

人間のユーザーはこれらの変数を設定することになっていますか?自動ツール(automakeautoconfなど)はそれらを設定しますか?私が使用することになっているLinuxシステムは、これらの変数のいずれも定義していません-これは典型的なものですか?

現在、私のMakefileは次のようになっていますが、少し汚い気がします。

ifdef code_coverage
    GCOV_FLAG := -fprofile-arcs -ftest-coverage
else
    GCOV_FLAG :=
endif

WFLAGS := -Wall

INC_FLAGS := -Istuff -Imore_stuff -Ietc

CCFLAGSINT := -O3 $(WFLAGS) $(INC_FLAGS) $(CCFLAGS)

... (somewhere in the makefile, the command-line for compilation looks like this)
    $(CC) $(CCFLAGSINT) -c $< -o $@

... (somewhere in the makefile, the command-line for linking looks like this)
    $(CC) $(GCOV_FLAG) $(CCFLAGSINT) $(OBJLIST) $(LDFLAGS) -o $@

ここにはバグがないと確信しています。 Makefileは非常にうまく機能します。しかし、慣例に反するものはありますか(CCFLAGSINTなど-代わりにCCFLAGSを上書きするだけですか?またはCXXFLAGS?FUD!)

非常に多くの質問でごめんなさい。あなたは明らかにそれらすべてに答えるわけではありませんが、答えがこれらの設定の背後にある一般的なアイデアを理解するのに役立つことを願っています。

62
anatolyg

お気づきのとおり、これらはMakefile {マクロまたは変数}であり、コンパイラオプションではありません。一連の規則を実装します。 (マクロはそれらの古い名前であり、今でも一部で使用されています。GNU make docはそれらを変数と呼びます。)

名前が重要な唯一の理由は、デフォルトのmakeルールであり、make -p、それらのいくつかを使用します。

独自のルールをすべて作成すると、独自のマクロ名をすべて選択できるようになります。

Vanilla gnu makeには、CCFLAGSのようなものはありません。 CFLAGSCPPFLAGS、およびCXXFLAGSがあります。 Cコンパイラの場合はCFLAGS、C++の場合はCXXFLAGS、両方の場合はCPPFLAGS

両方にCPPFLAGSがあるのはなぜですか?従来は、プリプロセッサフ​​ラグ(-D-U)およびcとc ++の両方がそれらを使用します。さて、全員がcとc ++の同じ定義環境を望んでいるという仮定は疑わしいかもしれませんが、伝統的です。


追伸 James Moore で述べたように、一部のプロジェクトでは、Cプリプロセッサへのフラグではなく、C++コンパイラへのフラグにCPPFLAGSを使用しています。 Android NDK、1つの大きな例です。

75
bmargulies

による GNU makeマニュアル:

CFLAGS:Cコンパイラに与える追加のフラグ。
CXXFLAGS:C++コンパイラーに与える追加のフラグ。
CPPFLAGS:Cプリプロセッサーおよびそれを使用するプログラム(CおよびFortranコンパイラー)に与える追加フラグ。

src: https://www.gnu.org/software/make/manual/make.html#index-CFLAGS
注:PPはPreProcessor(プラスプラスではない)を表します。

CPP:Cプリプロセッサを実行するためのプログラム。結果は標準出力に出力されます。デフォルトは「$(CC)-E」です。

これらの変数は、makeの暗黙のルールによって使用されます

Cプログラムのコンパイル
n.oは、n.cから次の形式のレシピで自動的に作成されます。
「$(CC)$(CPPFLAGS)$(CFLAGS)-c」。

C++プログラムのコンパイル
n.oは、n.cc、n.cpp、またはn.Cから次の形式のレシピで自動的に作成されます。
「$(CXX)$(CPPFLAGS)$(CXXFLAGS)-c」。
C++ソースファイルには、「。C」の代わりに接尾辞「.cc」を使用することをお勧めします。

src: https://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules

8
Mizux

そして、最小限の例として Mizuxが言った を作るだけです:

main_c.c

#include <stdio.h>

int main(void) {
    puts("hello");
}

main_cpp.cpp

#include <iostream>

int main(void) {
    std::cout << "hello" << std::endl;
}

次に、Makefileなしで:

make CFLAGS='-g -O3' CXXFLAGS='-ggdb3 -O0' CPPFLAGS='-DX=1 -DY=2' main_c main_cpp

実行:

cc -g -O3 -DX=1 -DY=2   main_c.c   -o main_c
g++ -ggdb3 -O0 -DX=1 -DY=2   main_cpp.cpp   -o main_cpp

そのため、次のことを理解しています。

  • makeには、main_cおよびmain_cppからmain_c.cおよびmain_cpp.cppを作成する暗黙のルールがありました
  • CFLAGSおよびCPPFLAGSは、.cコンパイルの暗黙的なルールの一部として使用されました
  • CXXFLAGSおよびCPPFLAGSは、.cppコンパイルの暗黙ルールの一部として使用されました

これらの変数は、makeの暗黙のルールでのみ自動的に使用されます。コンパイルが独自の明示的なルールを使用した場合、次のようにこれらの変数を明示的に使用する必要があります。

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

main_cpp: main_c.c
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $<

暗黙のルールに同様の影響を与えるため。

必要に応じてこれらの変数に名前を付けることもできます。ただし、Makeはすでに暗黙のルールでそれらを魔法のように扱っているため、適切な名前を選択します。

Ubuntu 16.04でテスト済み、GNU Make 4.1。