tags:

views:

344

answers:

6

Our team had been using Delphi 6 for many years, then switched to Delphi 2006 years ago. With both versions we have the following problem: frequently the compiler complains about a unit which is supposedly used recursively. This unit is a 40k LOC unit which is at the core of a project with almost 1 million LOC (third party included).

The error message is incorrect: a full build on the project always works. Unfortunately, the error message does not tell us where the supposed circular reference is, just the name of that unit. Sometimes it even happens that valid error messages are listed 2-4 times until that circular reference problem is "found". Clearly the compiler is running in a circle here. Because of the size of that project it is hard to find the problem manually. Therefore I made a tool which proves that there really is no circular reference (the tool creates a directed dependency graph of the units and determines the coherence components in that graph - there are none except if I deliberately put some in).

This is not only affecting F9 compilation but also code completion / insight which is not working most of the time. Sometimes it works when I press ctrl-space a second time...

Any ideas how we can isolate or even fix the problem? Note that it will be very hard to split the 40k LOC unit into smaller ones because it contains about 15 large classes which depend on each other in the interface section (I know it's bad but should work anyway).

Update
We are constantly refactoring but this is one tough unit to refactor because everything depends on everything, almost. Have been trying to get around it via interfaces but we are talking about some classes with 100s of methods and properties. And it would be slower.

Upgrading to D2009 may be an option down the road but right now we're stuck with D2006 (the unicode stuff and the price tag are two of the stoppers here). Question is anyway if it would help since the problem is in there since D6 at least.

About trimming the uses clauses, we have been doing this frequently with Icarus. But that did not help so far. We are down to 90 custom units in the interface section now. However, with a true circular reference the problem could be in any unit. Also tried to add all units to the dpr.

The project shares a lot of code with other projects, and there are some IFDEFs. However, the defines are not set up in project options but via a common include file. Therefore all modules should see the same defines. Also, the problem reoccurs shortly after a full rebuild without switching to another project.

A: 

Do you have any other projects that use part of the same codebase? If you compile one of them under different compiler settings or IFDEFs, it might change certain things in some of the DCUs which would lead to a circular dependency. A full build rebuilds all DCUs and then the problem goes away.

Mason Wheeler
A: 

Try Icarus (free) from Peganza. If that does not tell you what the problem is, try their Pascal Analyzer.

frogb
+3  A: 

I will probably be downvoted for this. In D2005 I had a 10k loc unit (datamodule) that flat out stopped compiling. Had to separate out some datasets/code to another datamodule. That 10k unit was and is a mess. You really should consider refactoring out some code to other units. My module has since D2005 / separation grown even worse, but it still compiles in D2007. So my answer is a) refactor and b) upgrade to D2009.

Tom
+1  A: 

You write that a full build does always succeed, but shortly after the incremental build fails with this error. Assuming that you experience this in the IDE, have you tried to use the command line compiler dcc32 to do incremental builds?

If you don't feed it the "-Q" switch (which probably most Makefiles or scripts for command line builds do) it will output a lot of information what files it compiles in what order. You could either try to do an incremental build after the error appeared in the IDE, or you could keep a command line open next to the IDE and Alt+Tab to it for compilation, skipping compilation in the IDE completely.

I simply assume you have a way to build using dcc32, one way or another - with the size of your project I can't imagine otherwise.

mghie
Right, we use dcc32 in a full build script over all projects (and more). I am not really looking forward to use it as a replacement for IDE compilation; it would not help with code insight and who knows how often that would be required then.But maybe it is a way to diagnose the problem? Ideally dcc32 incremental would run into the same problem and its output triggers some ideas...
deepc
Yes, that's exactly what I was trying to suggest, maybe I didn't succeed with making it clear though :-( Sorry. Using dcc32 you should see what files are compiled several times, and after which file it all stops. Unless the IDE compiler and dcc32 are really that different, but this I wouldn't assume.
mghie
+2  A: 

We regularly fall in similar problems, and we never managed (or bothered long enough) to find the precise cause. There seems to be a problem in the order which Delphi chooses to compile the units when hitting Ctrl-F9, which is incompatible with the actual dependency order of the units.

  • Have you tried deleting "MyBigFatUnit.dcu" before hitting Ctrl-F9?
  • Have you tried to re-order the declaration of your units in your dpr/dpk files, so that units appear in a correct compilation order? (i.e.: if unit B depends on unit A, unit A should appear first in the dpr/dpk)
LeGEC
A: 

We have this problem as well, also with a fairly large codebase.

We are currently using D2009, but have had this problem with all previous versions of Delphi.

It most frequently happens immediately after doing an update from source control, so I suspect there is some timestamp issue within the Delphi build process.

In our case, if Ctrl-F9 fails and reports the circular reference, a second Ctrl-F9 will generally work

Alistair Ward