web-dev-qa-db-fra.com

CFLAGS, CCFLAGS, CXXFLAGS - que contrôlent exactement ces variables?

J'utilise GNU make pour compiler mon code C++ et je voudrais comprendre comment rendre mes compilations personnalisables.

J'ai lu à différents endroits que CFLAGS, CCFLAGS et CXXFLAGS étaient utilisés à cette fin. Alors, comment devrais-je les utiliser? Si j'ai des arguments de ligne de commande supplémentaires pour le compilateur, devrais-je les ajouter à CFLAGS ou les ajouter au début? Y a-t-il une pratique commune?

Pourquoi les trois variables différentes? Je suppose que le compilateur C devrait avoir CFLAGS et CCFLAGS, tandis que le compilateur C++ devrait avoir CFLAGS et CXXFLAGS - l’ai-je bien compris?

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 supposé utiliser ne définit aucune de ces variables - est-ce typique?

Actuellement, mon Makefile ressemble à ceci et je trouve ça un peu sale:

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

Je suis à peu près 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 simplement écraser CCFLAGS à la place? Ou bien CXXFLAGS? FUD!)

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

62
anatolyg

Comme vous l'avez remarqué, il s'agit de Makefile {macros ou variables}, et non d'options du compilateur. Ils mettent en œuvre un ensemble de conventions. (Macros est un ancien nom pour eux, encore utilisé par certains. GNU make doc les appelle variables).

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

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

Dans une marque Vanilla gnu, il n’existe 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 est-il dans les deux? Conventionnellement, c'est la maison des drapeaux de préprocesseur (-D, -U) et c et c ++ les utilisent. Maintenant, l'hypothèse que tout le monde veut 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 indicateurs du compilateur C++, et non pour le préprocesseur C. Le Android NDK, par exemple).

75
bmargulies

Selon le GNU make Manuel:

CFLAGS: Drapeaux supplémentaires à donner au compilateur C.
CXXFLAGS: indicateurs supplémentaires à donner au compilateur C++.
CPPFLAGS: indicateurs 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 PreProcessor (et non Plus Plus), c.-à-d.

CPP: programme pour exécuter le préprocesseur C, avec les résultats obtenus en sortie standard; défaut '$ (CC) -E'.

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

Compiler les programmes C
n.o est créé automatiquement à partir de n.c avec une recette de la forme
"$ (CC) $ (CPPFLAGS) $ (CFLAGS) -c".

Compiler des programmes C++
n.o est créé 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

8
Mizux

Et juste pour faire ce que Mizux a dit à titre d'exemple minimal:

main_c.c

#include <stdio.h>

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

main_cpp.cpp

#include <iostream>

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

Ensuite, sans aucun Makefile:

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

fonctionne:

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

Nous comprenons donc que:

  • make avait des règles implicites pour faire main_c et main_cpp de main_c.c et main_cpp.cpp
  • CFLAGS et CPPFLAGS ont été utilisés dans le cadre de la règle implicite pour .c compilation
  • CXXFLAGS et CPPFLAGS ont été utilisés dans le cadre de la règle implicite pour .cpp compilation

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

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 aussi nommer ces variables comme bon nous semble: mais comme Make les traite déjà de manière magique dans les règles implicites, celles-ci font de bons choix de noms.

Testé sous Ubuntu 16.04, GNU Make 4.1.