115 votes

CFLAGS, CCFLAGS, CXXFLAGS - à quoi servent exactement ces variables de contrôle?

Je suis en train d'utiliser GNU make pour compiler mon code C++, et j'aimerais comprendre comment rendre mes compilations personnalisables.

J'ai lu à différents endroits que CFLAGS, CCFLAGS et CXXFLAGS sont utilisés à cet effet. Comment devrais-je les utiliser? Si j'ai des arguments supplémentaires à passer au compilateur en ligne de commande, dois-je les ajouter à CFLAGS ou les préfixer? Y a-t-il une pratique commune?

Pourquoi les trois variables différentes? Je suppose que le compilateur C devrait recevoir CFLAGS et CCFLAGS, tandis que le compilateur C++ devrait recevoir CFLAGS et CXXFLAGS - est-ce correct?

L'utilisateur humain est-il censé définir ces variables? Est-ce que des outils automatiques (automake, autoconf, etc) les définissent? Le système Linux que je suis censé utiliser ne définit aucune de ces variables - est-ce typique?

Actuellement, mon Makefile ressemble à ceci, et je trouve que c'est un peu désordonné:

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)

... (quelque part dans le makefile, la ligne de commande pour la compilation ressemble à ceci)
    $(CC) $(CCFLAGSINT) -c $< -o $@

... (quelque part dans le makefile, la ligne de commande pour l'assemblage ressemble à ceci)
    $(CC) $(GCOV_FLAG) $(CCFLAGSINT) $(OBJLIST) $(LDFLAGS) -o $@

Je suis assez sûr qu'il n'y a pas de bugs ici; le Makefile fonctionne très bien. Mais y a-t-il quelque chose qui va à l'encontre des conventions (comme CCFLAGSINT - devrais-je juste écraser CCFLAGS à la place? Ou CXXFLAGS? FUD!)

Désolé pour tant de questions; vous n'allez évidemment pas y répondre toutes, mais j'espère que les réponses m'aideront à comprendre l'idée générale derrière ces paramétrages.

116voto

bmargulies Points 49855

Comme vous l'avez remarqué, ce sont des Makefile {macros ou variables}, pas des options de compilateur. Ils mettent en œuvre un ensemble de conventions. (Macros est un ancien nom pour eux, encore utilisé par certains. La documentation de GNU make les appelle variables.)

La seule raison pour laquelle les noms sont importants est les règles de make par défaut, visibles via make -p, qui en utilisent certains.

Si vous écrivez toutes vos propres règles, vous pouvez choisir tous vos propres noms de macro.

Dans un gnu make standard, il n'y a pas de CCFLAGS. Il y a CFLAGS, CPPFLAGS et CXXFLAGS. CFLAGS pour le compilateur C, CXXFLAGS pour C++ et CPPFLAGS pour les deux.

Pourquoi CPPFLAGS dans les deux? Conventionnellement, c'est le lieu des drapeaux du préprocesseur (-D, -U) et à la fois c et c++ les utilisent. Maintenant, l'hypothèse que tout le monde veuille le même environnement de définition pour c et c++ est peut-être discutable, mais traditionnelle.


P.S. Comme indiqué par James Moore, certains projets utilisent CPPFLAGS pour les drapeaux du compilateur C++, pas les drapeaux du préprocesseur C. Le NDK Android, par exemple.

30voto

Mizux Points 1240

Selon le manuel de GNU make:

CFLAGS: Drapeaux supplémentaires à donner au compilateur C.
CXXFLAGS: Drapeaux supplémentaires à donner au compilateur C++.
CPPFLAGS: Drapeaux supplémentaires à donner au préprocesseur C et aux programmes qui l'utilisent (les compilateurs C et Fortran).

src: https://www.gnu.org/software/make/manual/make.html#index-CFLAGS
note: PP signifie PréProcesseur (et non Plus Plus), c'est-à-dire

CPP: Programme pour exécuter le préprocesseur C, avec des résultats en sortie standard; défaut ‘$(CC) -E’.

Ces variables sont utilisées par les règles implicites de make

Compilation des programmes C
n.o est faite automatiquement à partir de n.c avec une recette de la forme
‘$(CC) $(CPPFLAGS) $(CFLAGS) -c’.

Compilation des programmes C++
n.o est faite automatiquement à partir de n.cc, n.cpp ou n.C avec une recette de la forme
‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’.
Nous vous encourageons à utiliser le suffixe ‘.cc’ pour les fichiers source C++ au lieu de ‘.C’.

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

11voto

Ciro Santilli Points 3341

Exemple minimal

Et juste pour illustrer ce que Mizux a dit comme exemple minimal :

main_c.c

#include 

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

main_cpp.cpp

#include 

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

Ensuite, sans aucun Makefile :

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

exécute :

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

Donc nous comprenons que :

  • make avait des règles implicites pour créer main_c et main_cpp à partir de main_c.c et main_cpp.cpp

  • CFLAGS et CPPFLAGS ont été utilisés dans la règle implicite pour la compilation de .c

  • CXXFLAGS et CPPFLAGS ont été utilisés dans la règle implicite pour la compilation de .cpp

  • CCFLAGS n'est pas utilisé.

    Par ailleurs, le système de construction SCons par exemple utilise CCFLAGS pour les drapeaux communs à C et C++, ce qui est une convention que je suis parfois dans mes propres règles make personnalisées.

Ces variables ne sont utilisées que dans les règles implicites de make automatiquement : si la compilation avait utilisé nos propres règles explicites, alors nous aurions dû utiliser explicitement ces variables comme dans :

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

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

pour obtenir un effet similaire aux règles implicites.

Nous pourrions également nommer ces variables comme bon nous semble : mais étant donné que Make les traite déjà magiquement dans les règles implicites, ce sont de bons choix de nom.

Testé sur Ubuntu 16.04, GNU Make 4.1.

Lié : CFLAGS vs CPPFLAGS

1voto

anatolyg Points 8076

Ceci est un complément à toutes les réponses existantes, qui décrivent principalement comment ces variables make affectent le processus de compilation. Dans cette réponse, je décris une manière suggérée d'utiliser ces variables, et toutes les considérations environnantes. Cela est en partie inspiré par une réponse à une question similaire.

Comment devrais-je les utiliser ? Dois-je les ajouter ou les préfixer ?

Les drapeaux de compilation sont de deux types :

  1. Ceux qui sont nécessaires pour que la compilation fonctionne (exemple : -I, qui indique au compilateur où trouver les fichiers h).
  2. Ceux qui personnalisent la compilation (exemple : -O, niveau d'optimisation).

Seul le type 2 (personnalisation) devrait aller dans CCFLAGS, et si l'utilisateur les spécifie, ils devraient remplacer ce qui est défini dans le Makefile. Utilisez la syntaxe ?= pour cela dans votre Makefile :

CCFLAGS ?= -O3

Les paramètres de type 1 devraient aller dans une nouvelle variable inventée, qui devrait les agréger tous, et inclure également les variables standard, comme CCFLAGS :

INC_FLAGS := -Istuff -Imore_stuff -Ietc

CCFLAGS_INTERNAL := $(INC_FLAGS) $(CCFLAGS)

Y a-t-il une pratique commune ?

Non, cela ne semble pas être le cas. Ce que j'ai décrit ci-dessus est une option, qui semble bien, mais ce n'est pas standard.

L'utilisateur humain est-il censé définir ces variables du tout ? Le système linux que j'utilise ne définit aucune de ces variables - est-ce typique ?

Oui, celles-ci servent à spécifier des options en utilisant la ligne de commande. Les variables d'environnement n'existent généralement pas.

Y a-t-il quelque chose qui va à l'encontre des conventions ? (comme CCFLAGSINT - devrais-je simplement écraser CCFLAGS à la place ? Ou CXXFLAGS ? FUD !)

Non, l'idée de ce Makefile est correcte : ajouter CCFLAGS et d'autres drapeaux à la ligne de commande du compilateur ; ne mettez pas à jour CCFLAGS.

-2voto

Code-Apprentice Points 18086

Alternativement, vous pouvez définir LDLIBS. Par exemple :

LDLIBS = -lm

Ce drapeau est utilisé par la règle de liaison implicite et placera les drapeaux -l plus tard dans la ligne de commande afin que ld trouve les bibliothèques avant de tenter de lier votre propre code source dans l'exécutable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X