Resolving inter-linked units in Delphi VCL

I have a multi-unit program, and have just started getting problems in compiling, with one of the units (an unchanged one) stopping the completion of the compile. Running the compile a second time fixes the problem.

I am not sure how to permanently fix. Is it:
1) related to the placement of uses clauses in the interface and implementation sections?
2) the order of the units in the project?
3) something else?
GrahamDLovellAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

MerijnBSr. Software EngineerCommented:
Can you reproduce this problem every time? If yes, how to break it and how to fix it?
GrahamDLovellAuthor Commented:
It doesn't happen every time. The fix is to re-compile.
Sinisa VukSoftware architectCommented:
Make sure that your search path is ok (project option) and your unit is unique (not placed in more than one folder - just in app folder). Make sure that your unit is not circular attached to other unit(s) (unit A uses unit B and back...) . Units are compiled when compiler decide to - ex. some of depending unit is changed. Think that order in uses will not solve this - but position - implemntation uses and main uses - maybe.
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

MerijnBSr. Software EngineerCommented:
What error message do you get when it does not compile?
GrahamDLovellAuthor Commented:
Sinisa:
Yes, I reckon that interface / implementation uses clause placement is important, but I don't know the rules. Is there a reference somewhere for this?
Circular references seem to work OK, provided you get the uses clause correctly placed in each; e.g. uMain (the first unit opened) calls procedures in all the other units, and the other units call procedures in uMain. It seems to work if I put uMain in the interface uses clause of these other units.
Delphi seems to be quite good at sorting this out, most of the time.
I have also just changed the file order in the project manager to put the unit that gets most (if not all) of the complaints lower in the list than the units it calls. This might have fixed it, but if so, I don't know why, since other units compile when the same condition applies.

MerijnB:
I get a top level message, something like - could not compile "unit name", but no reason. It doesn't happen every time I make a change.
MerijnBSr. Software EngineerCommented:
Is it possible you have antivirus or backup software which has an open file handle to the dcu which is being recompiled?
GrahamDLovellAuthor Commented:
No. An immediate re-compile resolves the issue, without doing anything else.
GrahamDLovellAuthor Commented:
Backup is out; it was not running. In addition, if it were random, it could not be seen to affect at most a couple of units or repeated occasions.
MerijnBSr. Software EngineerCommented:
If this is caused by any software having an open file handle that could very well mean that it's solved when you compile it again (you just have bad luck that there is a file handle open at the first time you compile).
GrahamDLovellAuthor Commented:
What can I say? I anticipated that response, and thought I had answered it. Why would a random event repeatedly attack a single unit (or a couple of units - I cannot remember all the examples) when those units have not been changed.
MerijnBSr. Software EngineerCommented:
Ok, just wanted to make sure you made that thought process :)

What Delphi version are you using?
GrahamDLovellAuthor Commented:
XE6
MerijnBSr. Software EngineerCommented:
All I can think of now is to make this problem as small as possible. You will probably find something interesting at the point where you can't reproduce it anymore.
Sinisa VukSoftware architectCommented:
Have you consider to rewrite unit to avid circural reference. Unit A can do uses unit B, but when Unit B needs something from A - use address of callback function. Definition of callback function can be in third unit C.
GrahamDLovellAuthor Commented:
Thanks. However, I will wait until I see whether re-ordering the units in the project fixes the problem.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Geert GOracle dbaCommented:
circular unit referencing should be avoided
it can work, but the effects you get are perfectly normal when having common units across different apps
especially if they use the main form

i suppose you have common units among different projects ?

do you fix the problem with compile or build ?
build does a bit more.
you can also have very nasty behavior when using compiler directives in common units
you'll get errors when compiling and have to rebuild

i don't know the exact syntax for compiler directives, but here is the pseudo code:
common unit ABC;
{$IF NOT DEFINED XXX THEN $DEFINE XXX=1}

project X1
does not have compiler directives
> unit ABC is thus compiled with XXX=1

project X2
has compiler directive XXX=2
when compiling X2, it may throw an error as it tries to find info which is hidden for all items with compiler directive XXX=1
rebuilding the X2 project solves this problem

if you want help on solving circular unit reference problems ... just
your best option, but not the fastest and easiest, is to solve the circular unit reference
GrahamDLovellAuthor Commented:
As far as I can tell, this problem is not one of circular references, but rather of compile order. The unit which appears in the compiler complaint is quite small, and I can't see a circular reference.
Fixing the order of units in the project fixed the problem, but I have don't have a clear understanding of why it worked.
Geert GOracle dbaCommented:
if you override a class and change the order of the units ... it can cause problems

sometimes adding windows unit without explicitly using something from it can cause that too
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.