2009-05-24 14 views
8

Nuestro equipo ha estado utilizando Delphi 6 durante muchos años, luego cambió a Delphi 2006 años atrás. Con ambas versiones tenemos el siguiente problema: con frecuencia el compilador se queja de una unidad que supuestamente se usa recursivamente. Esta unidad es una unidad LOC de 40k que se encuentra en el núcleo de un proyecto con casi 1 millón de LOC (incluido un tercero).Error de referencia circular incorrecto

El mensaje de error es incorrecto: una compilación completa en el proyecto siempre funciona. Lamentablemente, el mensaje de error no nos dice dónde se encuentra la supuesta referencia circular, solo el nombre de esa unidad. A veces, incluso ocurre que los mensajes de error válidos se enumeran de 2 a 4 veces hasta que el problema de referencia circular se "encuentra". Claramente el compilador se está ejecutando en un círculo aquí. Debido al tamaño de ese proyecto, es difícil encontrar el problema de forma manual. Por lo tanto, hice una herramienta que prueba que realmente no hay referencia circular (la herramienta crea un gráfico de dependencia dirigida de las unidades y determina los componentes de coherencia en ese gráfico; no hay ninguno excepto si incluyo deliberadamente alguno).

Esto no solo está afectando a la compilación F9 sino también a la finalización/visión del código que no funciona la mayor parte del tiempo. A veces funciona cuando presiono ctrl-space por segunda vez ...

¿Alguna idea de cómo podemos aislar o incluso solucionar el problema? Tenga en cuenta que será muy difícil dividir la unidad de 40k LOC en otras más pequeñas porque contiene alrededor de 15 clases grandes que dependen una de la otra en la sección de interfaz (sé que es malo, pero debería funcionar de todos modos).

actualización
Estamos constantemente refactorización pero esto es una unidad resistente a refactorizar, porque todo depende de todo, o casi. Hemos intentado sortearlo a través de interfaces, pero estamos hablando de algunas clases con cientos de métodos y propiedades. Y sería más lento.

La actualización a D2009 puede ser una opción en el futuro, pero ahora estamos atrapados con D2006 (las cosas Unicode y el precio son dos de los topes aquí). La pregunta es de todos modos si ayudaría ya que el problema está ahí desde D6 al menos.

Para recortar las cláusulas de uso, hemos estado haciendo esto frecuentemente con Icarus. Pero eso no ayudó hasta ahora. Ahora tenemos 90 unidades personalizadas en la sección de interfaz. Sin embargo, con una verdadera referencia circular, el problema podría estar en cualquier unidad. También intenté agregar todas las unidades al dpr.

El proyecto comparte mucho código con otros proyectos, y hay algunos IFDEF. Sin embargo, las definiciones no están configuradas en las opciones del proyecto, sino a través de un archivo de inclusión común. Por lo tanto, todos los módulos deberían ver lo mismo define. Además, el problema vuelve a ocurrir poco después de una reconstrucción completa sin cambiar a otro proyecto.

Respuesta

0

¿Tiene algún otro proyecto que use parte de la misma base de código? Si compila uno de ellos en diferentes configuraciones de compilador o IFDEF, podría cambiar ciertas cosas en algunas de las DCU que darían lugar a una dependencia circular. Una compilación completa reconstruye todas las DCU y luego el problema desaparece.

0

Probar Icarus (gratis) desde Peganza. Si eso no te dice cuál es el problema, prueba su Pascal Analyzer.

2

Parece claro que esto se debe a una pequeña diferencia entre el compilador de fondo y el real. Puede mirar alrededor (QualityCentral) lo que se conoce sobre ese tema.

Además, como no indicó explícitamente esto, debe eliminar las unidades innecesarias y mover las declaraciones de usos a la implementación si es posible. Tal vez su herramienta podría ayudar con esto.

Y solo para asegurarse de que debe verificar los alias de unidad y la configuración de ruta.

4

Probablemente estaré des-invitado por esto. En D2005 tuve una unidad loc de 10k (módulo de datos) que dejó de compilar por completo. Tuve que separar algunos datasets/code a otro datamodule. Esa unidad de 10k fue y es un desastre. Realmente debería considerar refactorizar algún código a otras unidades. Mi módulo desde D2005/separation creció aún peor, pero aún se compila en D2007. Entonces mi respuesta es a) refactor yb) actualizar a D2009.

2

Usted escribe que una compilación completa siempre tiene éxito, pero poco después la compilación incremental falla con este error. Suponiendo que experimente esto en el IDE, ¿ha tratado de usar el compilador de línea de comandos dcc32 para hacer compilaciones incrementales?

Si no lo alimenta, el modificador "-Q" (que probablemente la mayoría de los Makefiles o scripts para las compilaciones de líneas de comando sí) generará mucha información sobre qué archivos compila en qué orden. Puede intentar hacer una compilación incremental después de que aparezca el error en el IDE, o puede mantener una línea de comando abierta al lado del IDE y Alt + Tab para compilar, omitiendo la compilación en el IDE por completo.

Simplemente supongo que tienes una forma de compilar usando dcc32, de una forma u otra, con el tamaño de tu proyecto no puedo imaginar lo contrario.

+0

Derecho, utilizamos dcc32 en una secuencia de comandos de compilación completa sobre todos los proyectos (y más). No estoy esperando usarlo como un reemplazo para la compilación IDE; no ayudaría con la perspectiva del código y quién sabe con qué frecuencia sería necesario entonces. ¿Pero tal vez es una forma de diagnosticar el problema? Idealmente dcc32 incremental se encontraría con el mismo problema y su resultado desencadena algunas ideas ... –

+0

Sí, eso es exactamente lo que estaba tratando de sugerir, tal vez no lo logré aclarar :-(Lo siento. Usando dcc32 debería ver qué archivos se compilan varias veces, y después de qué archivo todo se detiene. A menos que el compilador IDE y dcc32 sean realmente tan diferentes, pero esto no lo asumiría. – mghie

2

Caemos regularmente en problemas similares, y nunca logramos (o molestamos lo suficiente) encontrar la causa exacta. Parece que hay un problema en el orden que Delphi elige para compilar las unidades al presionar Ctrl-F9, que es incompatible con el orden de dependencia real de las unidades.

  • ¿Has probado a eliminar "MyBigFatUnit.dcu" antes de presionar Ctrl-F9?
  • ¿Ha intentado volver a ordenar la declaración de sus unidades en sus archivos dpr/dpk, para que las unidades aparezcan en un orden de compilación correcto? (es decir: si la unidad B depende de la unidad A, la unidad A debe aparecer primero en dpr/dpk)
0

También tenemos este problema, también con una base de código bastante grande.

Actualmente estamos usando D2009, pero hemos tenido este problema con todas las versiones anteriores de Delphi.

Suele ocurrir inmediatamente después de hacer una actualización desde el control de código fuente, por lo que sospecho que hay algún problema de marca de tiempo dentro del proceso de compilación Delphi.

En nuestro caso, si Ctrl-F9 falla y reporta la referencia circular, una segunda Ctrl-F9 generalmente trabajará

0

Una manera me han dicho que lidiar con esto es para abrir otro archivo arbitrario en el proyecto , cambie ese archivo, guárdelo y luego intente ejecutar de nuevo la compilación incremental. Sorprendentemente, esto generalmente funciona.

Tenemos un proyecto de 4 MLOC donde esto aparece de vez en cuando y esta "solución" funciona para mí.

0

He peleado esto antes, en mi experiencia el error es casi legítimo.Ha pasado bastante tiempo (el error no tiene nada que ver con la versión) pero mi memoria de la situación es que implica un ciclo en el que parte del ciclo está en la implementación.

La Unidad A usa B en la implementación. La Unidad B usa A en la interfaz. Si compila B primero llama a A pero como la llamada a B está en la implementación, tiene éxito. Si compila A primero, llama a B, B da la vuelta y llama a A en la interfaz, boom. Dichos bucles solo son seguros si ambas referencias cruzadas están en la implementación.

La solución es diseñar cosas de modo que haya un mínimo de material utilizado en la interfaz y asegurarse de que no haya nada parecido a un bucle en esas unidades. Siempre que mantenga sus definiciones de tipo separadas de las unidades con código, esto es bastante fácil de hacer.

El error que viene y va dependiendo de lo que está haciendo es un sello distintivo de este problema, ya que se trata de cómo entrar en el ciclo. Cuando haces una construcción completa, el orden es constante y lo obtienes al 100% o al 0%, no es aleatorio.

+0

Loren, puedo ver tu punto, pero lo que describes es perfectamente código válido y debería funcionar. Está documentado así: un compilador que funciona la mayor parte del tiempo sigue siendo un compilador roto, ¿verdad? FWIW, una vez intenté mover la mayoría de los "usos" de la interfaz a la implementación. recuerde cuántas unidades quedaron en la interfaz, pero recuerdo que no sirvió de nada. Es frustrante, ¿por qué este mensaje de error no enumera la referencia circular exacta? Especialmente ahora, cuando el supuesto círculo es un código válido, ayudaría a un ton para aprender exactamente lo que tuvo que ser cambiado. –

+0

@deepc: estoy de acuerdo, debería funcionar. Ha pasado tanto tiempo desde que lo vi que no recuerdo la redacción, ¿no da el nombre de la unidad que lo ha estropeado? También encontré útil el compilador de la línea de comandos para descifrarlo: redirija el resultado a un archivo para que pueda ver realmente qué archivos compiló, y no solo en qué está trabajando ahora. Si mantiene sus tipos separados de su código, de todos modos no es un problema, a menos que el diseño de su unidad sea espagueti. –

Cuestiones relacionadas