Acerca de
Tutoriales
Comunidad
Actualidad
Enlaces





En macprogramadores.org
En Internet

Trucos

Usar cabeceras precompiladas



Los compiladores de C y C++ actualmente pasan la mayoría de su tiempo compilando una y otra vez cabeceras mucho más grandes que el código fuente del fichero .c o .cpp en sí.

El compilador gcc de GNU a partir de la versión 3.3 incluye la posibilidad de usar cabeceras precompiladas, lo cual acelera mucho la compilación de programas C y C++.

En este truco se explica cómo aprovechar esta nueva característica


Durante la explicación de este truco vamos a suponer que nuestros ficheros fuente incluyen en su mayoría el fichero <iostream> con las operaciones típicas de entrada/salida C++, y el fichero <math.h> con las operaciones matemáticas más normales.

En consecuencia hemos decidido crear un fichero precompilado con estos ficheros de cabecera con el fin de acelerar la compilación de nuestro proyecto.

El fichero de cabecera en general deberá incluir sólo ficheros de cabecera que cambien poco, preferiblemente sólo los que vienen con el compilador (los que se invluyen de la forma #include <...>), y no los ficheros de cabecera de nuestro programa (que se incluyen de la forma #include "..."), ya que si no tendría que recompilarse el fichero de caberera cada vez que modificáramos uno de nuestros ficheros .h

Los ficheros de cabecera precompilados tienen el mismo nombre que el fichero .h correspondiente, pero con el sufijo .gch Por ejemplo si creamos el fichero precompiled.h con las cabeceras comunes que incluye nuestro proyecto el fichero de cabecera precompilado se llamará precompiled.h.gch

El fichero que nosotros hemos creado como ejemplo es el siguiente:

$ cat precompiled.h
#include <iostream>
#include <math.h>
using namespace std;

Lo siguiente que tenemos que hacer es precompilar este fichero para lo cual ejecutamos:

$ g++ -c precompiled.h -o precompiled.h.gch

Lo cual nos crea el fichero precompiled.h.gch con todos los ficheros incluidos por precompiled.h precompilados.

Ahora si, por ejemplo, el fichero encuadre.cpp incluye el fichero precompiled.h cuando ejecutemos:

$ g++ -c encuadre.cpp -o encuadre.o

El compilador de GNU buscará primero en el directorio actual un fichero llamado precompiled.h.gch, si lo encuentra lo usará, y sólo si no lo encuentra incluirá precompiled.h

Aquí conviene hacer varias apreciaciones: La primera es que para que el compilador de GNU use el fichero .gch que encuentre, éste deberá estar compilando exactamente con las mismas opciones con las que hemos lanzado la compilación de encuadre.cpp, es decir basta con que hubiéramos usado:

$ g++ -O1 -c encuadre.cpp -o encuadre.o

Para que no nos acepte el fichero precompilado y use el sin precompilar.

La segunda es que el compilador de GNU requiere un fichero precompilado para cada dialecto de C (C, C++, Objective-C), si quisiésemos que un fichero precompilado se usase por distintos dialectos de C necesitaríamos crear uno distinto para cada dialecto (usando la opción -x c-header, -x c++-header y -x objective-c-header). En este caso la forma de proceder es crear un directorio con el nombre precompiled.h.gch y dentro de el meter todos los ficheros precompilados para todos los dialectos que estemos usando (da lo mismo el nombre que demos a estos ficheros, gcc examina todos los ficheros del directorio en busca del que necesite).

La tercera apreciación es que si vamos a usar ficheros precompilados en un fichero Makefile conviene crear una regla que actualice los ficheros de cabecera como la siguiente:

encuadre.o: encuadre.cpp encuadre.h Matriz.h Punto.h precompiled.h.gch
precompiled.h.gch: precompiled.h
       $(CXX) $^ $(CXXFLAGS) -o $@

Desgraciadamente actualmente make no soporta el uso de reglas implícitas para los ficheros precompilados.

Por último conviene comentar que Xcode también soporta el designar a un fichero como fichero que actúe como cabecera precompilada, para ello debemos de activar dos opciones del proyecto o del target que son:

  • Prefix Header (GCC_PRIFIX_HEADER) Que indica que fichero de cabecera es el que debe precompilarse (en principio sólo soporta uno por proyecto que de hecho es lo normal). Por ejemplo aquí pondríamos precompiled.h. Esta opción no aparece por defecto en las opciones de Xcode con lo que debemos de usar el botón de añadir nueva opción y añadir la opción con clave GCC_PREFIX_HEADER y con valor precompiled.h
  • Precompile Prefix Header (GCC_PRECOMPILE_PREFIX_HEADER) Debemos de activar esta opción para que funcionen las cabeceras precompiladas dentro del proyecto o del target.