CFLAGS, CCFLAGS, CXXFLAGS - was genau steuern diese Variablen?

76

Ich verwende GNU make, um meinen C ++ - Code zu kompilieren, und ich möchte verstehen, wie ich meine Kompilierungen anpassbar machen kann.

Ich las in verschiedenen Orten , dass CFLAGS, CCFLAGSund CXXFLAGSwerden für diesen Zweck verwendet. Wie soll ich sie verwenden? Wenn ich zusätzliche Befehlszeilenargumente für den Compiler habe, sollte ich sie anhängen CFLAGSoder voranstellen? Gibt es eine gängige Praxis?

Warum die drei verschiedenen Variablen? Ich nehme an, der C-Compiler sollte bekommen CFLAGSund CCFLAGS, während der C ++ - Compiler bekommen sollte CFLAGSund CXXFLAGS- habe ich es richtig gemacht?

Soll der menschliche Benutzer diese Variablen überhaupt setzen? Haben alle automatischen Tools ( automake, autoconfusw.) sie setzen? Das Linux-System, das ich verwenden soll, definiert keine dieser Variablen - ist das typisch?

Derzeit sieht mein Makefile so aus und ich finde es etwas schmutzig:

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 $@

Ich bin mir ziemlich sicher, dass es hier keine Fehler gibt. Das Makefile funktioniert sehr gut. Aber gibt es etwas, das gegen Konventionen verstößt (wie CCFLAGSINT- sollte ich CCFLAGSstattdessen einfach überschreiben ? Oder CXXFLAGS? FUD!)

Entschuldigung für so viele Fragen; Sie werden natürlich nicht alle beantworten, aber ich hoffe, die Antworten helfen mir, die allgemeine Idee hinter diesen Einstellungen zu verstehen.

Anatolyg
quelle
Ist es fair zu sagen, basierend auf diesen Antworten, dass sich diese Umgebungsvariablen nicht ändern / nicht von den gccoder den clangCompilern selbst verwendet werden ?
Iono
CFLAGS vs CPPFLAGS: stackoverflow.com/questions/2754966/cflags-vs-cppflags
Ciro Santilli 27 冠状 病 六四 事件 27

Antworten:

83

Wie Sie bemerkt haben, handelt es sich hierbei um Makefile {Makros oder Variablen}, nicht um Compileroptionen. Sie implementieren eine Reihe von Konventionen. (Makros ist ein alter Name für sie, der immer noch von einigen verwendet wird. GNU make doc nennt sie Variablen.)

Der einzige Grund, warum die Namen wichtig sind, sind die Standard-Make-Regeln, die über sichtbar sind make -pund einige davon verwenden.

Wenn Sie alle Ihre eigenen Regeln schreiben, können Sie alle Ihre eigenen Makronamen auswählen.

In einem Vanille-Gnu-Fabrikat gibt es keine CCFLAGS. Es gibt CFLAGS, CPPFLAGSund CXXFLAGS. CFLAGSfür den C-Compiler, CXXFLAGSfür C ++ und CPPFLAGSfür beide.

Warum ist CPPFLAGSin beiden? Herkömmlicherweise sind hier Präprozessor-Flags ( -D, -U) zu Hause , und sowohl c als auch c ++ verwenden sie. Die Annahme, dass jeder die gleiche definierte Umgebung für c und c ++ haben möchte, ist vielleicht fraglich, aber traditionell.


PS Wie von James Moore erwähnt , verwenden einige Projekte CPPFLAGS für Flags für den C ++ - Compiler, nicht für Flags für den C-Präprozessor. Das Android NDK zum Beispiel.

bmargulies
quelle
7
Ich habe Sie dafür abgelehnt, dass Sie etwas falsch liegen, aber Sie sind nah genug dran, dass es sich nicht lohnt, eine völlig separate Antwort zu geben. $(CPPFLAGS)sind Flags für den Präprozessor. Die Tatsache, dass sie in den Aufrufen von $(CC)und verwendet werden, $(CXX)ist zufällig. Außerdem handelt es sich um Makefile-Variablen, nicht um Makros.
Jack Kelly
2
@ Jack: GNU Make ruft sie Variablen auf; Einige andere Quellen, einschließlich der Beschreibung von make durch die Single Unix-Spezifikation , nennen sie Makros. Gleiche Sache.
John Marshall
2
@ Jack im Jahr 1982, als ich make traf, nannten sie sie Makros.
Bmargulies
4
aaund ich bin gründlich zur Schule gebracht worden. Danke Leute.
Jack Kelly
2
@ Jack, nein, nein nein. Ich versuche nicht, dich zu schulen, nur um zu erklären, woher meine besondere Ansicht kam. In der Tat,
achten Sie
12

Nach dem GNU makeHandbuch:

CFLAGS: Zusätzliche Flags für den C-Compiler.
CXXFLAGS: Zusätzliche Flags für den C ++ - Compiler.
CPPFLAGS: Zusätzliche Flags für den C-Präprozessor und die Programme, die ihn verwenden (die C- und Fortran-Compiler).

src: https://www.gnu.org/software/make/manual/make.html#index-CFLAGS
Hinweis: PP steht für PreProcessor (und nicht für Plus Plus), d. h

CPP: Programm zum Ausführen des C-Präprozessors mit Ergebnissen zur Standardausgabe; Standard '$ (CC) -E'.

Diese Variablen werden von den impliziten Regeln von verwendet make

Das Kompilieren von C-Programmen
no erfolgt automatisch aus nc mit einem Rezept der Form
'$ (CC) $ (CPPFLAGS) $ (CFLAGS) -c'.

Das Kompilieren von C ++ - Programmen
no erfolgt automatisch aus n.cc, n.cpp oder nC mit einem Rezept der Form
'$ (CXX) $ (CPPFLAGS) $ (CXXFLAGS) -c'.
Wir empfehlen Ihnen, das Suffix '.cc' für C ++ - Quelldateien anstelle von '.C' zu verwenden.

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

Mizux
quelle
2

Minimales Beispiel

Und nur um das, was Mizux sagte, als minimales Beispiel zu nennen:

main_c.c

#include <stdio.h>

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

main_cpp.cpp

#include <iostream>

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

Dann ohne Makefile:

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

läuft:

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

Also verstehen wir das:

  • makehatte implizite Regeln zu machen main_cund main_cppvon main_c.cundmain_cpp.cpp
  • CFLAGS und CPPFLAGS wurden als Teil der impliziten Regel für die .cKompilierung verwendet
  • CXXFLAGS und CPPFLAGS wurden als Teil der impliziten Regel für die .cppKompilierung verwendet
  • CCFLAGS wird nicht verwendet

Diese Variablen werden nur automatisch in den impliziten Regeln von make verwendet: Wenn die Kompilierung unsere eigenen expliziten Regeln verwendet hätte, müssten wir diese Variablen explizit wie folgt verwenden:

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

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

einen ähnlichen Effekt wie die impliziten Regeln zu erzielen.

Wir könnten diese Variablen auch benennen, wie wir wollen: Da Make sie jedoch bereits in den impliziten Regeln magisch behandelt, treffen diese eine gute Namensauswahl.

Getestet in Ubuntu 16.04, GNU Make 4.1.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle