Pregunta

Cualquiera de las prácticas recomendadas para la limpieza de "encabezado de espagueti", que está causando muy lentos los tiempos de compilación (Linux/Unix)?

Es allí cualquier equvalent a "#pragma once" con GCC?
(encontrar mensajes contradictorios con respecto a este)

Gracias.

¿Fue útil?

Solución

Suponiendo que usted está familiarizado con el "incluyen a los guardias" (#ifdef en el principio de la cabecera..), otra manera de acelerar el tiempo de construcción es de uso externo de incluir los guardias.Fue discutido en "A Gran Escala De C++ Diseño De Software".La idea es que los clásicos incluyen los guardias, a diferencia de #pragma once, no de repuesto que el preprocesador de análisis necesarios para ignorar el encabezado del 2do tiempo (ej.todavía tiene que analizar y buscar el inicio y el final de la inclusión de la guardia.Con externos incluyen los guardias de colocar el #ifdef alrededor de la línea #include sí mismo.

Por lo que se ve como esto:

#ifndef MY_HEADER
#include "myheader.h"
#endif

y por supuesto dentro de la H archivo que tiene el clásico incluyen la guardia

#ifndef MY_HEADER
#define MY_HEADER

// content of header

#endif

De esta manera el myheader.h archivo no está aún abiertos / leídos por el preprocesador, y le puede ahorrar un montón de tiempo en proyectos de gran envergadura, sobre todo cuando los archivos de encabezado de sentarse en el intercambio de lugares remotos, como a veces lo hacen.

de nuevo, todo está en ese libro.hth

Otros consejos

Si quieres hacer una limpieza completa y tener el tiempo para hacerlo, entonces la mejor solución es eliminar todos los #incluye en todos los archivos (excepto por obvias por ejemplo,abc.h en abc.cpp) y, a continuación, compile el proyecto.Añadir el necesario avance de la declaración o de cabecera para corregir el primer error y, a continuación, repita el procedimiento hasta que comple limpiamente.

Esto no soluciona los problemas subyacentes que pueden resultar en incluir temas, pero asegura que la única incluye son los requeridos.

He leído que el GCC considera #pragma once en desuso, aunque aún #pragma once sólo se puede hacer mucho para acelerar las cosas.

Para intentar desenredar la #include espaguetis, usted puede mirar en doxygen.Debe ser capaz de generar gráficas de incluye los encabezados, que puede darle una ventaja sobre la simplificación de las cosas.No puedo recordar los detalles de improviso, pero el gráfico de funciones puede requerir la instalación de GraphViz y dígale a doxygen la ruta de acceso donde se puede encontrar GraphViz del dotty.exe.

Otro enfoque podría considerar si el tiempo de compilación es su principal preocupación es la configuración de Encabezados Precompilados.

Leí el otro día sobre un truco para reducir el encabezado de las dependencias:Escribir una secuencia de comandos que se

  • encontrar todos los #include
  • quitar una instrucción a la vez y se vuelve a compilar
  • si la compilación falla, agregar la instrucción include de vuelta en

Al final, te esperamos terminar con el mínimo requerido incluye en su código.Podría escribir un script similar que re-organiza incluye para averiguar si son auto-suficientes, o que requieren de otras cabeceras para ser incluidos antes de que ellos (incluir el encabezado de la primera, a ver si la compilación falla, informe).Que debe de alguna forma, para la limpieza de tu código.

Algunas notas más:

  • Los compiladores modernos (gcc entre ellos) reconocer el encabezado de los guardias, y optimizar de la misma manera como pragma once, sólo abrir el archivo una vez.
  • pragma una vez puede ser problemático cuando el mismo archivo tiene diferentes nombres en el sistema de archivos (es decir,con soft-enlaces)

  • gcc apoya #pragma once, pero dice que es "obsoleta"
  • pragma once no está soportado por todos los compiladores, y no forma parte del estándar de C

  • no sólo los compiladores pueden ser problemáticos.Herramientas como Incredibuild también tienen problemas con #pragma once

Richard fue un poco a la derecha (¿por Qué su solución fue anotado?).

De todos modos, todos los C/C++ encabezados deben utilizar internos incluyen los guardias.

Dicho esto, ya sea:

1 - Su legado, el código no es realmente mantiene ya, y se debe utilizar encabezados precompilados (que son un hack, pero bueno...Su necesidad es para acelerar la compilación, no refactorizar mantenido código)

2 - Su legado sigue vivo.A continuación, utilice los encabezados precompilados y/o los guardias/externo guardias para una solución temporal, pero al final, tendrás que eliminar a todos tus incluye, uno .C o .CPP en un momento, y compilar cada uno .C o .Archivo CPP uno a la vez, incluye la corrección de sus con-declaraciones o incluye, cuando sea necesario (o incluso rompiendo un gran incluir en los más pequeños para asegurarse de que cada uno de ellos .C o .Archivo CPP obtendrá sólo los encabezados que necesita).De todos modos, las pruebas y la eliminación de obsoletos incluye es parte del mantenimiento de un proyecto, así que...

Mi propia experiencia con los encabezados precompilados, no era exactamente una buena, porque la mitad del tiempo, el compilador no se pudo encontrar un símbolo que había definido, y por lo que he intentado en un pleno "limpio/a reconstruir", para estar seguro de que no era el encabezado precompilado que era obsoleta.Así que supongo que es para uso de librerías externas que ni siquiera tocar (como la STL, la API en C de encabezados, Boost, lo que sea).Aún así, mi propia experiencia fue con Visual C++ 6, por lo que supongo (espero?) ellos lo hicieron bien, ahora.

Ahora, una última cosa:Encabezados siempre debe ser auto-suficiente.Esto significa que si a la inclusión de encabezados depende del orden de inclusión, entonces usted tiene un problema.Por ejemplo, si usted puede escribir:

#include "AAA.hpp"
#include "BBB.hpp"

Pero no:

#include "BBB.hpp"
#include "AAA.hpp"

porque BBB depende de la AAA, entonces todo lo que tienes es una dependencia de la que nunca reconoció en el código.No reconociendo con un definen sólo hará que su compilación en una pesadilla.BBB debe incluir AAA, demasiado (aunque podría ser un poco más lento:en la final, adelante-declaraciones de todos modos limpio inútil incluye, por lo que debe tener un más rápido compilar temporizador).

Utilice uno o más de esos para acelerar el tiempo de construcción

  1. Usar Encabezados Precompilados
  2. El uso de un mecanismo de almacenamiento en caché (scons por ejemplo)
  3. El uso de un sistema de generación distribuida ( distcc, Incredibuild($) )

En los encabezados:incluir encabezados sólo si usted no puede utilizar declaración forward, pero siempre #incluir cualquier archivo que usted necesita (incluir dependencias están mal!).

Como se mencionó en la otra respuesta, que sin duda debe utilizar declaraciones forward siempre que sea posible.A mi conocimiento, GCC no tiene nada equivalente a #pragma once, que es por eso que me quedo con el viejo estilo de la moda de incluir los guardias.

Gracias por las respuestas, pero la pregunta es con respecto al código existente que incluye estrictas "incluir la orden", etc.La pregunta es si hay herramientas y scripts para aclarar lo que realmente está pasando.

Encabezado guardias no son la solución, ya que ellos no evitar que el compilador de leer todo el archivo de nuevo y de nuevo y ...

PC-Lint va a ir un largo camino para la limpieza de espaguetis encabezados.También se va a resolver otros problemas para usted también, como no inicializado las variables de ir invisible, etc.

Como onebyone.livejournal.com comentó en respuesta a su pregunta, algunos compiladores de apoyo incluyen guardia de optimización, que la página que he enlazado define de la siguiente manera:

La inclusión de la guardia de la optimización es cuando un compilador reconoce la interna incluyen la guardia lenguaje descrito anteriormente y toma medidas para evitar abrir el archivo varias veces.El compilador puede buscar en un archivo de inclusión, tira de comentarios y espacios en blanco y el trabajo de si la totalidad de el archivo está dentro de incluir los guardias.Si es así, se almacena el nombre del archivo y se incluyen guardia de la condición en un mapa.La próxima vez que el compilador se pidió incluir el archivo, se puede comprobar la inclusión de la guardia condición y tomar la decisión de omitir el archivo o #include sin necesidad de abrir el archivo.

A continuación, de nuevo, usted ya respondió externos incluyen los guardias no son la respuesta a su pregunta.Para el esclarecimiento de los archivos de encabezado que debe ser incluido en un orden específico, sugiero los siguientes:

  • Cada .c o .cpp el archivo debe #include la correspondiente .h archivo primero, y el resto de su #include las directivas deben ser ordenadas alfabéticamente.Generalmente, usted recibirá errores de compilación cuando este se rompe sin dependencias entre los archivos de encabezado.
  • Si usted tiene un archivo de encabezado que define mundial de las definiciones de tipos para los tipos básicos o global #define las directivas que se utilizan para la mayoría del código, cada .h el archivo debe #include el archivo primero, y el resto de su #include las directivas deben ser ordenadas alfabéticamente.
  • Cuando estos cambios producen errores de compilación, por lo general tendrá que agregar explícita la dependencia de un archivo de encabezado a otro, en la forma de un #include.
  • Cuando estos cambios no provocar errores de compilación, ya que podrían causar cambios en el comportamiento.Esperamos que usted tenga algún tipo de paquete de prueba que puede utilizar para comprobar la funcionalidad de la aplicación.

También suena como parte del problema podría ser que las generaciones incrementales son mucho más lentos de lo que deberían ser.Esta situación se puede mejorar con el avance de declaraciones o de un sistema de generación distribuida, como otros han señalado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top