Encabezados precompilados con GCC

91

¿Alguien ha tenido éxito al conseguir que los encabezados precompilados funcionen con GCC? No he tenido suerte en mis intentos y no he visto muchos buenos ejemplos de cómo configurarlo. Probé cygwin gcc 3.4.4 y usé 4.0 en Ubuntu.

Lee Baldwin
fuente
Lo probé y tuve el caso de uso óptimo para los encabezados precompilados porque mi fuente c es generada por el compilador y no escrita por el usuario. Sun Studio y especialmente Visual Studio mejoraron mucho el tiempo de compilación. En gcc empeoraba aún más sin los encabezados precompilados. Esto fue con 3.4. No he probado con 4.x, pero la velocidad y gcc son mutuamente excluyentes.
Lothar
@Lothar ¿cuál era el código? Encuentro g ++ aproximadamente 10 veces más rápido que los compiladores recientes de Visual Studio, en algunos códigos con muchas plantillas.
el cerdo
No estoy usando plantillas en mi código C ++. Es solo el manejo de excepciones de C + + buenas extensiones de C ++. Incluso ahora, 6 años después de esta pregunta, VS2010 es una magnitud más rápida. Pero mientras tanto tengo 16 núcleos para poder vivir con ellos.
Lothar

Respuestas:

58

Definitivamente he tenido éxito. Primero, utilicé el siguiente código:


#include <boost/xpressive/xpressive.hpp>
#include <iostream>

using namespace std;
using namespace boost::xpressive;

//A simple regex test
int main()
{
    std::string hello( "hello world!" );

    sregex rex = sregex::compile( "(\\w+) (\\w+)!" );
    smatch what;

    if( regex_match( hello, what, rex ) )
    {
        std::cout << what[0] << '\n'; // whole match
        std::cout << what[1] << '\n'; // first capture
        std::cout << what[2] << '\n'; // second capture
    }
    return 0;
}

Este fue solo un saludo a todo el mundo de Boost Xpressive (ver el enlace a continuación). Primero, compilé con el-H opción en gcc. Mostró una enorme lista de encabezados que utilizó. Luego, eché un vistazo a las banderas de compilación que estaba produciendo mi IDE (código :: bloques) y vi algo como esto:

g++ -Wall -fexceptions -g -c main.cpp -o obj/Debug/main.o

Así que escribí un comando para compilar el archivo Xpressive.hpp con exactamente las mismas banderas:

sudo g++ -Wall -fexceptions -g /usr/local/include/boost/xpressive/xpressive.hpp

Volví a compilar el código original con el -H y obtuve este resultado:

g ++ -Wall -fexceptions -H -g -c main.cpp -o obj / Debug / main.o
! /usr/local/include/boost/xpressive/xpressive.hpp.gch
main.cpp
. /usr/include/c++/4.4/iostream
.. /usr/include/c++/4.4/x86_64-linux-gnu/bits/c++config.h
.. /usr/include/c++/4.4/ostream
.. /usr/include/c++/4.4/istream
main.cpp

Los ! significa que el compilador pudo usar el encabezado precompilado. Una x significa que no pudo usarlo. El uso de las banderas del compilador adecuadas es crucial. Me quité la -H y realicé algunas pruebas de velocidad. El encabezado precompilado tuvo una mejora de 14 segundos a 11 segundos. No esta mal, pero tampoco grandioso.

Nota: Aquí está el enlace al ejemplo: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples No pude hacer que funcione en el enviar.

Por cierto: estoy usando el siguiente g ++

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Usuario1
fuente
20
Agregar -Winvalid-pch lo ayudará a depurar si algo sale mal en el uso de PCH y por qué.
lefticus
Los encabezados precompilados "no están mal pero no son excelentes" son útiles cuando tiene muchos encabezados que se vuelven a vincular entre sí, por lo que reducirán el tiempo de compilación en proyectos muy grandes que usan bibliotecas grandes o muchas bibliotecas.
jokoon
4
"no está mal pero no es genial": usando gcc 4.4.7, 136 archivos .cpp 35.5 Mb de tamaño total, 148 archivos .h 5.5 Mb de tamaño total, el archivo .gch es de 48 Mb, la compilación de depuración toma 2'20 "(vs 2 '14 "sin pch), la compilación optimizada de -O2 tarda 4'30" (frente a 5'33 "sin pch) El efecto se esperaría cerca de las compilaciones de depuración, pero es solo la compilación optimizada la que se beneficia de la precompilación ... No estoy seguro de por qué. ¡La precompilación es mucho más espectacular en Windows!
Andreas Vergison
1
(continuación) Los archivos de salida pch / non-pch correspondientes tienen exactamente el mismo tamaño de bytes, eso es bueno. Los tiempos anteriores parecen variar cuando se repiten las compilaciones, por ejemplo, -O2 non-pch varía entre 3'45 "y 5'33", por lo que no es una ciencia exacta, quizás debido a que se ejecuta en VMware. De todos modos, gcc pch no parece beneficioso en absoluto en mi caso. Compárelo con la misma base de código en Windows VS2012 (x64, compilación de un solo subproceso): depure 46 "pch, 2'50" no pch, lanzamiento 2'13 "pch, 5'02" no pch. Y, por supuesto, mucho más rápido cuando se habilita el multiprocesador ...
Andreas Vergison
@AndreasVergison - ¿Ha intentado usar -Winvalid-pchpara asegurarse de que el encabezado precompilado se esté usando correctamente? Notamos una gran mejora al usar pch para nuestras compilaciones de depuración, así que me pregunto si hay algún problema con su configuración.
Josh Kelley
52

En primer lugar, consulte la documentación aquí .

Compila encabezados como cualquier otro archivo, pero coloca la salida dentro de un archivo con un sufijo .gch.

Entonces, por ejemplo, si precompila stdafx.h, tendrá un encabezado precompilado que se buscará automáticamente en stdafx.h.gchcualquier momento que incluyastdafx.h

Ejemplo:

stdafx.h:

#include <string>
#include <stdio.h>

a.cpp:

#include "stdafx.h"
int main(int argc, char**argv)
{
  std::string s = "Hi";
  return 0;
}

Luego compila como:

> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out

Su compilación funcionará incluso si elimina stdafx.h después del paso 1.

Brian R. Bondy
fuente
8

El -xespecificador para los encabezados precompilados de C ++ es -x c++-header, no -x c++. A continuación, se muestra un ejemplo de uso de PCH.

pch.h:

// Put your common include files here: Boost, STL as well as your project's headers.

main.cpp:

#include "pch.h"
// Use the PCH here.

Genere el PCH así:

$ g++ -x c++-header -o pch.h.gch -c pch.h

El pch.h.gchdebe estar en el mismo directorio que pch.hpara poder ser utilizado, así que asegúrese de ejecutar el comando anterior desde el directorio donde pch.hestá.

psaghelyi
fuente
3
Esto debería ser -c pch.h, -c pch.cpp¿ no ?
MM
7

He logrado que los encabezados precompilados funcionen bajo gcc una vez en el pasado, y recuerdo que también tuve problemas en ese momento. Lo que hay que recordar es que gcc ignorará el archivo (header.h.gch o similar) si no se cumplen ciertas condiciones, una lista de las cuales se puede encontrar en la página de documentación del encabezado precompilado de gcc .

En general, es más seguro que su sistema de compilación compile el archivo .gch como primer paso, con las mismas opciones de línea de comando y ejecutable que el resto de su fuente. Esto asegura que el archivo esté actualizado y que no haya diferencias sutiles.

Probablemente también sea una buena idea hacer que funcione primero con un ejemplo artificial, solo para eliminar la posibilidad de que sus problemas sean específicos del código fuente de su proyecto.

Pablo
fuente
7

Llame a gcc de la misma manera que lo llama para su archivo fuente pero con un archivo de encabezado.

p.ej

g++ $(CPPFLAGS) test.h

esto genera un archivo llamado test.h.gch

Cada vez que gcc busca test.h busca primero test.h.gch y si lo encuentra lo usa automáticamente.

Puede encontrar más información en Encabezados precompilados de GCC

Simón
fuente
Estoy usando gcc 3.4 y la línea g ++ stdafx.h no se compilará, obtendrá el error "g ++: compilación del archivo de encabezado solicitado", pero esto se compilará, aunque no estoy seguro si eso es lo que quiero: "g ++ -c -x c ++ stdafx.h -o stdafx.h.pch "
stefanB
1

Asegurate que -include your_header.h

Así es como precompilé y usé la bits/stdc++.hcolección.

Código

#include <bits/stdc++.h>

Luego localicé la biblioteca compilando mi archivo con -H y mirando la salida

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

donde vi

. /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h

Así que hice un nuevo directorio bitsdentro del actual y lo copié stdc++.hdesde allí.

Entonces corrí

g++ bits/stdc++.h -O3 -std=c++14  -pthread

que generó bits/stdc++.gch

Normalmente compilé mi código a través de

g++ sol.cpp -O3 -pthread -lm -std=c++14 -o executable

, pero tuve que modificar eso para

g++ sol.cpp -include bits/stdc++.h -O3 -pthread -lm -std=c++14 -o executable

ya que solo resolvió .gchpresentar en lugar de .hcon -include bits/stdc++.h Eso fue clave para mí. Otra cosa a tener en cuenta es que debe compilar el *.harchivo de encabezado con casi los mismos parámetros que compila su *.cpp. Cuando no incluí -O3o -pthreadignoró el *.gchencabezado precompilado.

Para comprobar si todo está correcto, puede medir la diferencia de tiempo comparando el resultado de

time g++ sol.cpp ...

o corre

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

nuevamente y busque rutas de encabezado y si ahora obtiene !antes de la ruta de la biblioteca, por ejemplo

! ./bits/stdc++.h.gch
....
Íhor Mé
fuente