I was compiling a new branch at work today, which used a different version of Delphi than the one I had been working on, and along the way I ran into tons of spurious File Not Found errors from the compiler. The file was, in fact, right there where it should have been able to find it easily, but it kept erroring out. After speaking with another developer, I managed to track down what was really going wrong: for some reason, it was finding outdated DCUs from the old build and choking on it, giving an incorrect error. After deleting the rogue DCUs, everything built smoothly.
It made me think about the many DCU headaches I’ve had over the years. I haven’t heard an official explanation from the Delphi team for why Delphi uses DCUs, but according to Verity Stob,
As I understand it, this speed advantage [of Delphi’s compiler over Java’s] is in part achieved by the .DCU object file format, which is actually a raw-ish dump of the Delphi compiler’s output buffer. … it’s really easy to write out and load quickly [because] it’s already in the right format.
In other words, DCU essentially functions as a cache to help the compiler go faster. Unfortunately, as anyone with a few years of Delphi experience can tell you, this makes the compiler subject to one of the Two Hard Problems of Computer Science. And it kind of makes me wonder if DCUs are worth having around anymore.
The upside is that it provides caching for the compiler. This was very important in the late 80s and early 90s, due to highly limited hardware. Today, though, when “2+ GHz quad-core CPU with 4 GB of RAM and an SSD drive” isn’t even the description of a high-end system anymore, (particularly not for a software developer,) that’s a lot less of a benefit than it used to be.
There are several downsides, though:
- Caching means cache invalidation problems, as listed above.
- It makes the process of searching for units more complicated for the compiler, and harder for developers to reason about.
- Caching means cache invalidation problems, as listed above. (It’s a big enough problem to be worth mentioning twice, especially if you’re maintaining more than one project, or more than one version of the same project!)
- It gives rise to the temptation to do ridiculous things like checking DCUs into source control. (No, seriously. I know of at least one software development company using Delphi that actually does this!)
- It gives rise to the temptation, among some of the more parasitically-minded component and library vendors, to sell DCU-only libraries which then keeps the legitimate purchaser from debugging them or updating them to work with the next version of Delphi. This is something that simply should not happen, but some people are doing it just because they can.
It all makes me wonder, is it time to do away with the DCU file once and for all? The compiler’s fast enough to not need it, particularly if you’re on an SSD. (And if you’re not… seriously, go get an SSD. Now. I promise you, it’ll be the best thing you ever did for your dev environment.)
What do you think? Is DCU an outdated concept that’s doing more harm than good these days, or is it still useful for modern Delphi development? Let me know what you think in the comments.