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
, CCFLAGS
und CXXFLAGS
werden 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 CFLAGS
oder voranstellen? Gibt es eine gängige Praxis?
Warum die drei verschiedenen Variablen? Ich nehme an, der C-Compiler sollte bekommen CFLAGS
und CCFLAGS
, während der C ++ - Compiler bekommen sollte CFLAGS
und CXXFLAGS
- habe ich es richtig gemacht?
Soll der menschliche Benutzer diese Variablen überhaupt setzen? Haben alle automatischen Tools ( automake
, autoconf
usw.) 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 CCFLAGS
stattdessen 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.
quelle
gcc
oder denclang
Compilern selbst verwendet werden ?Antworten:
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 -p
und 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
,CPPFLAGS
undCXXFLAGS
.CFLAGS
für den C-Compiler,CXXFLAGS
für C ++ undCPPFLAGS
für beide.Warum ist
CPPFLAGS
in 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.
quelle
$(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.Nach dem
GNU make
Handbuch: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
Diese Variablen werden von den impliziten Regeln von verwendet
make
src: https://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
quelle
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:
make
hatte implizite Regeln zu machenmain_c
undmain_cpp
vonmain_c.c
undmain_cpp.cpp
.c
Kompilierung verwendet.cpp
Kompilierung verwendetDiese 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:
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.
quelle