CFLAGS vs CPPFLAGS

104

Entiendo que CFLAGS (o CXXFLAGS para C ++) son para el compilador, mientras que CPPFLAGS es usado por el preprocesador.

Pero todavía no entiendo la diferencia.

Necesito especificar una ruta de inclusión para un archivo de encabezado que se incluye con #include, ya que #include es una directiva de preprocesador, ¿es el preprocesador (CPPFLAGS) lo único que me importa?

¿Bajo qué circunstancias necesito darle al compilador una ruta de inclusión adicional?

En general, si el preprocesador encuentra e incluye los archivos de encabezado necesarios, ¿por qué es necesario que se le informe sobre directorios de inclusión adicionales? ¿Para qué sirve CFLAGS?

(En mi caso, descubrí que AMBOS de estos me permiten compilar mi programa, lo que aumenta la confusión ... Puedo usar CFLAGS O CPPFLAGS para lograr mi objetivo (al menos en el contexto de autoconf). ¿Qué ocurre?)

EBM
fuente
2
posible duplicado de stackoverflow.com/questions/495598/…
Michael Mrozek

Respuestas:

154

La regla de creación implícita para compilar un programa en C es

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

donde la $()sintaxis expande las variables. Como ambos CPPFLAGSy CFLAGSse usan en la llamada del compilador, el que use para definir rutas de inclusión es una cuestión de gusto personal. Por ejemplo, si foo.ces un archivo en el directorio actual

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

ambos llamarán a su compilador exactamente de la misma manera, es decir

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

La diferencia entre los dos entra en juego cuando tiene varios idiomas que necesitan la misma ruta de inclusión, por ejemplo, si tiene bar.cpp, intente

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

entonces las compilaciones serán

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

ya que la regla implícita de C ++ también usa la CPPFLAGSvariable.

Esta diferencia le brinda una buena guía para usar: si desea que la bandera se use para todos los idiomas, colóquela CPPFLAGS, si es para un idioma específico CFLAGS, CXXFLAGScolóquela , etc. Ejemplos de este último tipo incluyen cumplimiento estándar o banderas de advertencia - ¡no querría pasar -std=c99a su compilador de C ++!

Entonces podría terminar con algo como esto en su archivo MAKE

CPPFLAGS=-I/usr/include
CFLAGS=-std=c99
CXXFLAGS=-Weffc++
Scott Gales
fuente
1
Tenga en cuenta que no se puede ejecutar independiente cppusando CPPFLAGSy esperar ningún resultado razonable, porque -std=c99afecta a los símbolos que se definen (en especial, en lugar de macros de prueba de funciones). En cambio, necesitas $(CC) $(CPPFLAGS) $(CFLAGS) -E.
Jed
10

La CPPFLAGSmacro es la que se usa para especificar #includedirectorios.

Ambos CPPFLAGSy CFLAGSfuncionan en su caso porque la makeregla (1) combina el preprocesamiento y la compilación en un comando (por lo que ambas macros se usan en el comando).

No es necesario especificarlo .como un directorio de inclusión si usa el formulario #include "...". Tampoco es necesario especificar el directorio de inclusión del compilador estándar. Necesita especificar todos los demás directorios de inclusión.

Steve Emmerson
fuente
Esto tiene más sentido, pero todavía no veo qué hace CFLAGS, entonces. Si, como parece insinuar, la compilación en proyectos más complejos se realiza en un paso separado del preprocesamiento, ¿el preprocesamiento tendrá éxito pero la compilación fallará si CFLAGS no agrega las mismas rutas que CPPFLAGS agregó para el preprocesador? Supongo que no entiendo qué hace el compilador con rutas de inclusión si el preprocesador ya procesó las directivas #include.
EBM
4
@EB Si está compilando archivos preprocesados, las rutas de inclusión no son necesarias; los encabezados necesarios ya se han agregado a la fuente preprocesada (observe la salida cuando se ejecuta gcc -Een un archivo; no hay #includes). La mayoría de los compiladores modernos combinan los pasos de preprocesamiento y compilación, por lo que no tiene que preocuparse por esto.
Scott Wales
0

Para agregar a aquellos que han mencionado las reglas implícitas, es mejor ver qué make ha definido implícitamente y para su env usando:

make -p

Por ejemplo:

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

que se expande

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

Esto también imprimirá # environmentdatos. Aquí, encontrará la ruta de inclusión de GCC entre otra información útil.

C_INCLUDE_PATH=/usr/include

En make, cuando se trata de buscar, los caminos son muchos, la luz es una ... o algo por el estilo.

  1. C_INCLUDE_PATHes para todo el sistema, configúrelo en su shell *.rc.
  2. $(CPPFLAGS) es para la ruta de inclusión del preprocesador.
  3. Si necesita agregar una ruta de búsqueda general para make, use:
VPATH = my_dir_to_search

... o incluso más específico

vpath %.c src
vpath %.h include

make utiliza VPATH como ruta de búsqueda general, así que utilícelo con precaución. Si un archivo existe en más de una ubicación enumerada en VPATH, make tomará la primera aparición en la lista.

67 Hz
fuente