c++ unit-testing dependencies precompiled-headers stdafx.h

¿Hay alguna manera de usar encabezados precompilados en VC++ sin requerir stdafx.h?



unit-testing dependencies (9)

Cuando normalmente usa encabezados precompilados, "stdafx.h" tiene 2 propósitos. Define un conjunto de archivos de inclusión estables y comunes. También en cada archivo .cpp, sirve como un marcador como donde terminan los encabezados precompilados.

Parece que lo que quieres hacer es:

  • Deje el encabezado precompilado activado.
  • Deje la inclusión de "stdafx.h" en cada archivo .cpp.
  • Vacíe las inclusiones de "stdafx.h".
  • Para cada archivo .cpp, averigüe qué elementos eran necesarios del antiguo "stdafx.h". Agregue estos antes del #include "stdafx.h" en cada archivo .cpp.

Entonces ahora tiene el conjunto mínimo de dependencias, y todavía está usando encabezados precompilados. La pérdida es que no estás precompilando tu conjunto común de encabezados solo una vez. Esto sería un gran golpe para una reconstrucción completa. Para el modo de desarrollo, donde solo está recompilando algunos archivos a la vez, sería menos exitoso.

Tengo un montón de código heredado para el que necesito escribir pruebas unitarias. Utiliza encabezados precompilados en todas partes, por lo que casi todos los archivos .cpp tienen una dependencia en stdafx.h, lo que hace que sea difícil romper las dependencias para escribir pruebas.

Mi primer instinto es eliminar todos estos archivos stdafx.h que, en su mayoría, contienen directivas #include y colocar esos #includes directamente en los archivos fuente según sea necesario.

Esto haría necesario desactivar encabezados precompilados ya que dependen de tener un archivo como stdafx.h para determinar dónde se detienen los encabezados precompilados.

¿Hay alguna manera de mantener encabezados precompilados sin las dependencias de stdafx.h? ¿Hay una mejor manera de abordar este problema?


Los encabezados precompilados se basan en la idea de que todo incluirá el mismo conjunto de cosas. Si desea utilizar encabezados precompilados, debe vivir con las dependencias que esto implica. Todo se reduce a una compensación de las dependencias frente a la velocidad de compilación. Si puede construir en un tiempo razonable con los encabezados precompilados apagados, hágalo por todos los medios.

Otra cosa a considerar es que puede tener un pch por biblioteca. Por lo tanto, es posible que pueda dividir su código en bibliotecas más pequeñas y que cada una de ellas tenga un conjunto más ajustado de dependencias.


Mi consejo es: no elimines los encabezados precompilados a menos que quieras que tus compilaciones sean muy lentas. Básicamente tienes tres opciones aquí:

  1. Deshacerse de los encabezados precompilados (no recomendado)
  2. Cree una biblioteca separada para el código heredado; de esa manera puedes construirlo por separado.
  3. Use múltiples encabezados precompilados dentro de un solo proyecto. Puede seleccionar archivos C ++ individuales en su Solution Explorer y decirles qué encabezado precomiled debe usar. También necesitaría configurar su OtherStdAfx.h / cpp para generar un encabezado precompilado.

No, probablemente NO haya una mejor manera.

Sin embargo, para un archivo .cpp individual determinado, puede decidir que no necesita el encabezado precompilado. Puede modificar la configuración para ese archivo .cpp y eliminar la línea stdafx.h.

(En realidad, sin embargo, no sé cómo el esquema de encabezado precompilado está interfiriendo con la escritura de las pruebas de su unidad).


No. Los encabezados precompilados se basan en un solo encabezado incluido por todas las fuentes compiladas de esta manera. puede especificar que una sola fuente (o todas) no use encabezados precompilados en absoluto, pero eso no es lo que desea.

En el pasado, el compilador de Borland C ++ realizaba una compilación previa sin un encabezado específico. sin embargo, si dos archivos de fuentes incluían los mismos encabezados pero en orden diferente, se compilaron por separado, ya que, de hecho, el orden de los archivos de encabezado en C ++ puede ser importante ...

Por lo tanto, significa que los encabezados precompilados de borland ahorraron tiempo solo si incluyó fuentes de manera muy rígida en el mismo orden, o si incluyó un único archivo de inclusión (primero) en todos los demás archivos ... - ¿le suena familiar?!?!


Sí. El nombre "stdafx.h / stdafx.pch" es solo una convención. Puede otorgar a cada archivo .cpp su propio encabezado precompilado. Esto probablemente sería más fácil de lograr mediante un pequeño script para editar el XML en su .vcproj. A la baja: terminas con una gran pila de encabezados precompilados, y no se comparten entre TU.

Posible, pero inteligente? No puedo decirlo con certeza


Solo uso encabezados precompilados para el código que debe incluir las cosas afx___, generalmente solo la interfaz de usuario, que no pruebo de forma individual. El código de UI maneja la IU y llama a las funciones que sí tienen pruebas unitarias (aunque la mayoría actualmente no se debe a que la aplicación sea heredada).

Para la mayor parte del código, no uso encabezados precompilados.

GRAMO.


Sí, hay una mejor manera.

El problema, en mi humilde opinión, con el ''estilo de asistente'' de los encabezados precompilados es que fomentan el acoplamiento no requerido y hacen que el código de reutilización sea más difícil de lo que debería ser. Además, el código que se ha escrito con el estilo ''solo pegue todo en stdafx.h'' es propenso a ser difícil de mantener, ya que es probable que cambiar todo en cualquier archivo de encabezado vuelva a compilar todo el código base en todo momento. Esto puede hacer que la refactorización simple dure para siempre ya que cada ciclo de cambio y recompilación lleva mucho más tiempo de lo que debería.

Una mejor manera, una vez más en mi humilde opinión, es utilizar #pragma hdrstop y / Yc y / Yu. Esto le permite configurar fácilmente configuraciones de compilación que utilizan encabezados precompilados y también configuraciones de compilación que no usan encabezados precompilados. Los archivos que usan encabezados precompilados no tienen una dependencia directa en el encabezado precompilado en sí en el archivo de origen, lo que les permite compilarse con o sin el encabezado precompilado. El archivo del proyecto determina qué archivo fuente crea el encabezado precompilado y la línea #pragma hdrstop en cada archivo fuente determina qué incluye se toman del encabezado precompilado (si se usa) y cuáles se toman directamente del archivo fuente ... Esto significa que cuando Al realizar el mantenimiento, utilizaría la configuración que no usa encabezados precompilados y solo se reconstruirá el código que necesita reconstruir después de que se modifique el archivo de encabezado. Al realizar compilaciones completas, puede usar las configuraciones de encabezado precompiladas para acelerar el proceso de compilación. Otra cosa buena acerca de tener la opción de compilación de encabezado no precompilado es que se asegura de que sus archivos cpp solo incluyan lo que necesitan e incluyan todo lo que necesitan (algo que es difícil si usa el ''estilo de asistente'' del encabezado precompilado).

He escrito un poco acerca de cómo funciona esto aquí: http://www.lenholgate.com/blog/2004/07/fi-stlport-precompiled-headers-warning-level-4-and-pragma-hdrstop.html ( ignorar las cosas sobre / FI) y tengo algunos ejemplos de proyectos que se compilan con el método #pragma hdrstop y / Yc / Yu aquí: http://www.lenholgate.com/blog/2008/04/practical-testing-16- --fixing-a-timeout-bug.html .

Por supuesto, pasar del uso de encabezado precompilado de "estilo de asistente" a un estilo más controlado a menudo no es trivial ...


Los encabezados precompilados pueden ahorrar mucho tiempo al reconstruir un proyecto, pero si un encabezado precompilado cambia, cada archivo fuente que dependa del encabezado se volverá a compilar, independientemente de si el cambio lo afecta o no. Afortunadamente, los encabezados precompilados se usan para compilar , no vincular ; cada archivo fuente no tiene que usar el mismo encabezado precompilado.

pch1.h:

#include <bigHeader1.h> #include ...


pch1.cpp:

#include "pch1.h"


source1.cpp:

#include "pch1.h" [code]


pch2.h:

#include <bigHeader2.h> #include ...


pch2.cpp:

#include "pch2.h"


source2.cpp

#include "pch2.h" [code]

Seleccione pch1.cpp , haga clic con el botón derecho, Propiedades , Propiedades de configuración, C / C ++, Encabezados precompilados .
Encabezado precompilado: Crear (/ Yc)
Archivo de encabezado precompilado : pch1.h
Archivo de salida de encabezado precompilado : $ (intDir) pch1.pch

Seleccione source1.cpp
Encabezado precompilado: uso (/ Yu)
Archivo de encabezado precompilado : pch1.h
Archivo de salida de encabezado precompilado : $ (intDir) pch1.pch (no creo que esto importe para / Yu)

Haga lo mismo para pch2.cpp y source2.cpp , excepto establezca el archivo de encabezado y el archivo de salida de encabezado en pch2.h y pch2.pch . Funciona para mi.