CFLAGS vs CPPFLAGS


103

Capisco che CFLAGS (o CXXFLAGS per C ++) sono per il compilatore, mentre CPPFLAGS è utilizzato dal preprocessore.

Ma ancora non capisco la differenza.

Devo specificare un percorso di inclusione per un file di intestazione incluso con #include - poiché #include è una direttiva del preprocessore, il preprocessore (CPPFLAGS) è l'unica cosa che mi interessa?

In quali circostanze devo fornire al compilatore un percorso di inclusione aggiuntivo?

In generale, se il preprocessore trova e include i file di intestazione necessari, perché è mai necessario che gli venga detto di directory di inclusione extra? A cosa servono le CFLAGS?

(Nel mio caso, ho effettivamente scoperto che ENTRAMBI questi mi consentono di compilare il mio programma, il che aumenta la confusione ... Posso usare CFLAGS O CPPFLAGS per raggiungere il mio obiettivo (almeno nel contesto di autoconf). Cosa succede?)


Risposte:


153

La regola make implicita per la compilazione di un programma C è

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

dove la $()sintassi espande le variabili. Poiché entrambi CPPFLAGSe CFLAGSvengono utilizzati nella chiamata del compilatore, che si utilizza per definire i percorsi di inclusione è una questione di gusto personale. Ad esempio, se foo.cè un file nella directory corrente

make foo.o CPPFLAGS="-I/usr/include"
make foo.o CFLAGS="-I/usr/include"

chiameranno entrambi il tuo compilatore esattamente nello stesso modo, vale a dire

gcc -I/usr/include -c -o foo.o foo.c

La differenza tra i due entra in gioco quando hai più lingue che richiedono lo stesso percorso di inclusione, ad esempio se devi bar.cppprovare

make bar.o CPPFLAGS="-I/usr/include"
make bar.o CFLAGS="-I/usr/include"

poi le compilation saranno

g++ -I/usr/include -c -o bar.o bar.cpp
g++ -c -o bar.o bar.cpp

poiché la regola implicita C ++ utilizza anche la CPPFLAGSvariabile.

Questa differenza ti dà una buona guida da usare: se vuoi che il flag sia usato per tutte le lingue, inseriscilo CPPFLAGS, se è per una lingua specifica, inseriscilo CFLAGS, CXXFLAGSecc. Esempi di quest'ultimo tipo includono la conformità agli standard o i flag di avviso - non vorresti passare -std=c99al tuo compilatore C ++!

Potresti quindi finire con qualcosa di simile nel tuo makefile

CPPFLAGS=-I/usr/include
CFLAGS=-std=c99
CXXFLAGS=-Weffc++

1
Si noti che non è possibile eseguire l' cppuso autonomo CPPFLAGSe aspettarsi risultati ragionevoli perché -std=c99influisce sui simboli definiti (specialmente al posto delle macro di test delle funzionalità). Invece, hai bisogno $(CC) $(CPPFLAGS) $(CFLAGS) -E.
Jed

10

La CPPFLAGSmacro è quella da utilizzare per specificare le #includedirectory.

Entrambi CPPFLAGSe CFLAGSfunzionano nel tuo caso perché la makeregola (1) combina sia la preelaborazione che la compilazione in un comando (quindi entrambe le macro vengono utilizzate nel comando).

Non è necessario specificare .come directory di inclusione se si utilizza il modulo #include "...". Inoltre, non è necessario specificare la directory include del compilatore standard. È necessario specificare tutte le altre directory di inclusione.


Questo ha più senso, ma non vedo ancora cosa fa CFLAGS, quindi. Se, come sembra implicare, la compilazione in progetti più complessi viene eseguita in un passaggio separato dalla preelaborazione, la preelaborazione avrà esito positivo ma la compilazione fallirà se CFLAGS non aggiunge gli stessi percorsi che CPPFLAGS ha aggiunto per il preprocessore? Immagino di non capire cosa fa il compilatore con i percorsi di inclusione se il preprocessore ha già elaborato le direttive #include?
EBM

4
@EB Se stai compilando file preelaborati, i percorsi inclusi non sono necessari - le intestazioni richieste sono già state aggiunte alla sorgente preelaborata (dai un'occhiata all'output quando esegui gcc -Esu un file - non ci sono #include). La maggior parte dei compilatori moderni combina i passaggi di pre-elaborazione e compilazione, quindi non devi preoccuparti di questo.
Scott Wales


0

Per aggiungere a coloro che hanno menzionato le regole implicite, è meglio vedere cosa ha definito implicitamente e per il tuo env usando:

make -p

Per esempio:

%.o: %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

che si espande

COMPILE.c = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c

Questo stamperà anche i # environmentdati. Qui troverai il percorso di inclusione di GCC tra le altre informazioni utili.

C_INCLUDE_PATH=/usr/include

In effetti, quando si tratta di ricerca, i percorsi sono tanti, la luce è una ... o qualcosa in tal senso.

  1. C_INCLUDE_PATHè a livello di sistema, impostalo nella tua shell *.rc.
  2. $(CPPFLAGS) è per il preprocessore include path.
  3. Se è necessario aggiungere un percorso di ricerca generale per make, utilizzare:
VPATH = my_dir_to_search

... o anche più specifico

vpath %.c src
vpath %.h include

make utilizza VPATH come percorso di ricerca generale, quindi usalo con cautela. Se un file esiste in più di una posizione elencata in VPATH, make prenderà la prima occorrenza nell'elenco.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.