GCC y encabezados precompilados
Después de leer este bonito artículo (El cuidado y alimentación de los encabezados precompilados), tengo algunas dudas sobre cómo pueden funcionar en la vida real. Más específicamente, ¿cómo puedo saber que necesito activar la reconstrucción del encabezado precompilado en los siguientes escenarios?
- Decido
#define
algo en uno de mis archivos .cpp que altera la forma en que el preprocesador interpreta algunos encabezados que ya están incluidos en mi encabezado precompilado. - Incluyo otro encabezado en uno de mis archivos .cpp que
#define
es una directiva de preprocesador específica que altera la forma en que el preprocesador interpreta un encabezado ya incluido en el encabezado precompilado. - Peor aún, el problema anterior puede ocurrir de forma recursiva, cuando ciertos encabezados
#include
otros encabezados
¿El uso de encabezados precompilados debería imponer un cierto estilo de codificación restrictivo, como limitar el número de encabezados incluidos en los archivos .cpp a uno y nunca #define
incluir elementos en un archivo .cpp?
Si bien el compilador de Microsoft probablemente hace un trabajo decente con encabezados precompilados (aplicando algo de vudú específico de MS) porque, hasta donde yo sé, proporciona las opciones /Yc
y /Yu
que se supone hacen toda la plomería, para GCC parece que esto La funcionalidad requiere mucho trabajo manual y creatividad en Makefile y no pude encontrar una plantilla que se supone solucione todos los problemas del uso de encabezados precompilados.
Por ejemplo, si tengo un proyecto que construye varias bibliotecas, para no reconstruirlas todas después de cada cambio, tengo que usar algunos sed
trucos realmente lindos en el Makefile para detectar si uno de los encabezados #include
de la biblioteca actual fue modificado. (o es #include
un encabezado modificado). Me temo siquiera pensar en las complicaciones que implicarían los encabezados prediseñados para que el script de compilación los reconstruya cada vez que sea necesario.
El GCC actual (es decir, 4.7) y sus versiones anteriores funcionan bien con encabezados precompilados solo cuando tiene un único encabezado común para su aplicación, y cuando ese único encabezado (que incluye a su vez todos los del sistema y los específicos de la biblioteca, es necesario). por la aplicación) es #include
-d (como el primer lexema sin comentarios de sus fuentes) por cada fuente de su aplicación.
Por lo tanto, debe tener un único yourapp.h
archivo fuente y todos los archivos fuente (es decir, cada unidad de compilación) comenzando yourapp
con las #include "yourapp.h"
mismas opciones de preprocesamiento (es decir, -D
o -I
o -U
) en la línea de comando. Ese youapp.h
archivo de encabezado generalmente #include
incluye muchos otros, por ejemplo, encabezados del sistema (o GTK o Qt) como <stdlib.h>
o <sys/poll.h>
o [en C++] <algorithm>
o <gtk/gtk.h>
o <QtGui>
etc.
Recuerda que -H
es una opción útil para que gcc
te digan qué incluye.
Es posible que sus archivos fuente tengan algunos #include
archivos posteriores #include "yourapp.h"
adicionales si así lo desea.
Después de que GCC haya incluido un [único] encabezado precompilado, puede, por supuesto, #define
macros, #include
algunos encabezados no precompilados, realizar una compilación condicional con #ifdef
, etc. ¡Pero ese preprocesamiento no será "precompilado"!
Es posible que esto no se ajuste a sus necesidades o hábitos.
Algunas personas (especialmente de Google, en particular Diego Novillo) están trabajando en la rama PreParsed Header (pph) para mejorar la situación, pero la troncal GCC actual aún no ha conseguido ese trabajo.
La explicación sobre ese comportamiento de GCC es que un encabezado preprocesado es esencialmente un punto de control serializado persistente de todo el montón de GCC (relacionado con la administración de memoria dentro de GCC a través de Ggc y GTY y gengtype
). Ese montón con puntos de control se puede cargar solo cuando gcc
está en su estado vacío inicial. Tan pronto como se sabe algo gcc
(en realidad cc1
o cc1plus
), ya no puede cargar ningún archivo de encabezado precompilado *.h.gch
y volverá a analizar el archivo de encabezado textual *.h
.
adendas (noviembre de 2014 y posteriores)
Incluso GCC 4.9 quiere un único encabezado precompilado. El esfuerzo de encabezado previamente analizado por Diego Novillo et al. ha sido abandonado.
Las versiones futuras (posteriores a C++ 14 ) del estándar C++ podrían definir un mecanismo de módulo. Véase, por ejemplo, la propuesta n4047 y el estándar C++20 .
(Apéndices adicionales, verano de 2020) Esto sigue siendo válido para GCC-10 , donde existen varias opciones de analizadores estáticos . Véase también el analizador estático de Clang y este borrador del informe. Considere usar Frama-C .