What could cause a mismatched DCU file? - delphi

When I open my project and I double click on a specific pas file in the Project Manager, bds.exe freezes and continues using 25% of the cpu. I have to kill the process through the Windows Task Manager. (1)
When I open my project and I press F12 on that exact same file, I see what I would have expected to see earlier, the contents of the pas file.
When I open my project and I compile it first, then double click on the file, everything is fine.
I'm trying to figure out how, what I assume to be a mismatched DCU file, snuck into my project and what the best way is to prevent a similar issue in the future. Can I force all DCU files to be rebuilt? Can I simply delete all dcu files and recompile or is that a dangerous thing to do? My DCU files are currently also stored in the same directory where I keep the pas and dfm files, that is a bit messy.
(1) our application also shows behaviour in production where it sometimes crashes while it continues to use a steady cpu usage or simply continues to work as expected but shows a steady cpu usage in the background. We have been unable to trigger it in a compiled version but see it popping up from time to time. We assume the dcu mismatch is at the source of this problem.

There are numerous issues in your question, some entirely unrelated, but the assumption that the problem is a "mismatched" DCU is unlikely to be correct (by which I presume you mean an "old" or otherwise incorrect DCU compiled in the past or with different source).
First your problems.
IDE Behaviour
The problem with the IDE locking up when double-clicking a unit in the Project Manager is unlikely to be anything to do with a "mismatched" DCU.
Do you have source files located on a network drive ? Is this unit such a file ? Is that network location available/valid ? i.e. is the path to the file using a network drive letter that is no longer mapped or otherwise not available ?
If there is no explicit path in the unit reference in the DPR, do you have network locations listed in your system, IDE or project PATH ?
Difficulty accessing file locations is the most likely explanation for the IDE appearing to lock up when trying to simply open a file.
As to why it should behave differently when using F12 rather than the Project Manager, unfortunately the Delphi IDE is notorious for using different mechanisms to achieve the same thing in different places so it isn't surprising that sometimes when one of these mechanisms breaks the others still work (and can give different results even when both work).
Runtime Behaviour of your App
If we work on the basis that you do indeed have a "mismatched" DCU then performing a full build of your project will resolve that mismatch, as long as you have the source for all the required DCU's and that the correct and appropriate source for each DCU is available.
However, even though the mismatch may be resolved, rebuilding may or may not fix the issue, depending on whether that issue remains in the source code for that unit itself when recompiled.
The simple fact of the DCU being "mismatched" cannot cause aberrant application behaviour. With the exception of OS or RTL bugs etc, if there are errors in the behaviour of an application then those errors will be the result of errors in the source code as compiled.
Simply recompiling source code containing an error will not remove that error.
As such, if there is such an error then far more information will be needed if anyone is to be able to give any assistance on that score (and this should be a separate question, once you have done some initial debugging and diagnostics yourself).
Runtime Packages
If you are using runtime packages then things get more complicated because with a runtime package, the DCU employed for any particular unit could be part of a package file. In that case, the DCU file on disk is produced when you compile the package itself but any project that uses that package will not use the DCU on disk but will instead use the version that has been compiled into the package.
So if you are using runtime packages then as well as rebuilding your project you need to also rebuild any and all runtime packages that may have changed.
Now, for your actual questions.
Q1: Can I Rebuild all The DCU's ?
Yes, of course. But see above w.r.t Runtime Packages, if your project uses them.
I would strongly recommend that you change your project settings to output DCU files to a specific location, separate from the source files.
For example, you could have a project specific DCU folder using a relative path. i.e. set your DCU output folder to something like ".\dcu" and create a dcu folder within the folder where your DPR is located.
For Delphi versions supporting multiple platforms and configurations it is best to include the environment variables for the platform and configuration in that path, so that you don't end up using units compiled for DEBUG in a RELEASE build.
e.g.
.\dcu\$(Platform)\$(Config)
or
.\$(Platform)\$(Config)\dcu
What Is Compiled in a Build ?
When you do a Build on a project (as distinct from a "Compile"), all units referenced by that project will be recompiled, with the exception of any VCL/RTL units (i.e. those provided with Delphi). Those get special treatment.
At a minimum, rebuilding a project will forcibly recompile all units explicitly listed in the DPR, but will also recompile all other units that are used by those units (or units that they use etc etc).
NOTE: DCU's With Missing Source
A unit will only be recompiled if the source can be located.
If you have a DCU and the source file is missing or cannot be located on the project, IDE or system path, then the compiler will simply assume that you want to use the existing DCU.
This is the case even with a full "Build".
3rd Party DCU's
It may seem obvious but you should also be careful that you don't delete DCU's that may be your only copy of any 3rd party libraries you may be using for which you do not have the source.
This is highly inadvisable, but I guess we mustn't rule out the possibility that you may be in this situation.
Q2: Should I Delete all the DCU's ?
In general, yes. As noted above, even a full build will be successful if you are missing the source code for a unit that is referenced, as long as there is a DCU (or required package, if using runtime packages) that can be found.
So the only way to be sure that you have the current source for all DCU's is to first delete the DCU's that any previous builds may have used.
This is of course much easier when you have a specific, explicit location in which all your project DCU's are output.
It's slightly more involved if you are using Runtime Packages, though if you are organising your DCU's sensibly then the only real complication is that you need to repeat the same exercise for all the projects involved, working through starting each of the runtime packages that are used and finishing with the projects that in turn use them.

Yes, you can rebuild all DCU files in your project;
In the project group window, right click on the project and select Build.
It is OK to delete all DCUs in your project, but not necessary (or desirable in case you make a mistake...).
Note that this only builds DCUs explicitly in you project (as shown in your project tree) not any implicit ones imported as a result of your uses clauses.

Three things may be going on that have not been adressed in other answers.
Note that I only have experience with Delphi XE2 and Seattle 10, but they may apply to your version.
Delphi can be slow when switching from form to source view, especially if you have many components on your form. In migrating from XE2 to 10, we noticed an improvement here. We are talking seconds here, this does not seem to be your issue.
Delphi can be notoriously slow when switching between projects. After a switch the IDE can take a very long time (20-30 seconds) to respond. You cannot type anything; code completion takes a long time; initiating a project search with Alt-S-D waits a long time, then fails. In migrating from XE2 to 10, we noticed a large deterioration here.
Conditional compilation. If you have IFDEFs in your code compiling stuff for one project but not for another, your IDE can hang completely, and there's nothing else you can do then killing BDS.EXE. This happens in Delphi Seattle 10 if you switch projects and accidentally Compile instead of Build.
You may experience variations of these.

Related

Delphi 5 BPLs Not Linking For One Program Only

I'm still using Delphi 5.
I have a program which is a rewrite of an earlier program and in fact uses the root unit from the earlier program. When I compile it, Delphi doesn't link the BPLs into the EXE for some reason. New programs and old programs compile fine, so the problem is obviously with this one program. I've compared the project options for Linking and Compiling with other programs which are linking just fine. The compiler options in the main unit are the standard ones.
While the program is on my development box, it runs as expected, obviously reading the BPLs in the development area. But of course it won't run on another machine unless I copy the BPLs over, which is obviously not very clever.
I've read everything I can find on the subject, but although I've found references to linking not working, I haven't found anything which helps to work out why the linking isn't working in just this one case.
Can anyone point me at some documentation about this or point out something I've obviously missed looking at? I know it's something I've done, but despite spending hours on it I can't work out why!
Since there are no errors generated, I can't show you where it went wrong. Any suggestions about where I might find the problem would be much appreciated.
If you go to the Packages tab of your Project Options, is the Build with runtime packages checked?
If it is, you need to deploy the other packages to other machines if they aren't already on those machines at locations where they can be found by the OS.
If it isn't, Delphi will compile and link your project as an .Exe file and the code from the DCUs in the packages will be statically linked into your .Exe so you won't need to deploy the .BPLs (and they would be ignored even if you did).
AFAIK, when Delphi compiles a project to an .Exe (that is, if Build with runtime packages isn't checked), the compiler gets the other units' code to link from the .DCU files, rather than from the .BPL files. If it can't find the .DCU files, or you have told the compiler to do a "Build" it will attempt to generate the .DCUs them from the corresponding .PAS files if it can find them either in the project directory or via the Seach Path under Directories/Conditionals.

Same code, missing qtintf70.dll

Compiling some old code, my application will no longer run. Newly compiled exe-file won't start "because qtintf70.dll is missing from your computer".
Strange thing: an older exe file compiled from exact same code runs just fine. Both exe files tested on same system, but compiled on different Delphi installations (both Delphi 7 running on VirtualBox).
Googling, someone suggested "You have pulled in Clx somehow. Clx apps require the QT library. Look for units in your uses clauses that start with Q." but again: this is the exact same code. I've checked and can't find anything.
Suggestions?
In D7, the only source code units which reference qtintf70.dll are QForms.Pas and Qt.Pas.
So, what you need to do is to
Move all instances of these two files and their corresponding .DCU files to somewhere not on your project's search paths. Use a utility like SwiftSearch to make sure you find all of them.
Do a full build of the project.
The build should grind to a halt somewhere with a complaint that the compiler can't find one or other of these units. The source unit that is being compiled at the time is the one which contains a reference to one or other of them.

Moving to use of Delphi packages - best practice please?

I am trying to start making my own libraries avaialble as packages prior to compiling my Apps with these packages hence modularising my code. For years I've 'sort of' understood packages, breathing a sigh of relief when I load a component package and click on 'Install' and it does. I understand that the process of installing a component (or components) is via the creation of a BPL which is then registered with the IDE.
Where I begin to get lost is how to make files available so that I can compile with EITHER a package OR pre-compiled dcu's (like the third party vendors do) and without pointing my project at the source code all the time. I can create a package with the following settings:
where I've specified that all my output will go into 'c:\scratch\wow'. After a build I find TEST.BPL, TEST.DCP and lots of DUC's. Now, when I point another project at this folder to use the DCU's, I get a missing DFM error (one of the units is a form). Should I be manually copying needed DFM's into this output folder? The DPK knows about this form, so why do I not get the DFM copied for me? I presume that using TEST.BPL, that file contains everything, but I wish to work in the two modes. Of course I can get around this by including the source folder in my project search path to find the DFM but third party libraries seem to already have the DFM's in their output folder. Did they install them there using the installer?
Thanks
instead
As others say you could use post-build events to copy your DFM files into place. Other people use a one-time external batch file that copies the DFMs to the DCU folder.
Personally I see very little benefit to making packages for things which are not developed also as reusable components. I also see very little benefit in partitioning an existing application into packages, when you don't reasonably need to use the same subsection or package more than once, or at designtime.
Things I would put into packages:
Delphi visual and non-visual components.
Things which absolutely must be plugged in at runtime, or left out. For example, supposing I sell MetaWare Light and MetaWare Pro, and instead of using compiler IFDEFs to build a differnt binary, I preferred for some reason to simply not ship the ADVANCEDFEATURE.BPL with my systems.
Things to beware of with packages:
I have run into a lot of compiler bugs when combining packages with generics. I have also run into IDE crashes and lockups, in Delphi 2009, 2010, XE and XE2. (I believe XE3 is better)
You should learn a bit about BorlandMM.dll and shared memory management in the BPL world before you move to it. There are some subtleties.
Packages limits the ability of the linker to decide what to remove. In fact, it pretty much destroys it. Packages contain everything that is linked into them, and nothing publically accessible can be removed.
Once you've created a binary package and shipped it to even one customer, you have a pretty difficult to modify contract (this BPL contains a particular signature or application binary interface) you have to be careful in the future to never change them, or mix and match them. Beware of DLL hell, even among your own customers, and be prepared to use versioning on your packages. Just as delphi packages have a version suffix, I recommend you use version suffixes in your own packages right off the bat, and bump them whenever binary compatibility has changed.
Delphi handles build dependencies between packages about as well as could be hoped, which is less well than a single monolithic application. In applications that I have that make heavy use of packages, I find project groups that contain a bunch of packages that depend on each other are very difficult to manage and build quickly. In fact, I have experienced that both compiles and builds are slower and more frustrating than they would be in a singular 750Kline megaproject.
I really wonder if you're not that into the package area of Delphi (you breath a sigh of relief whenever a delphi component actually builds and installs without issue?) if you really want to move into the Packages World totally. By all means, you should experiment. But I wouldn't bet the farm on it yet. Learn some more first.
Yes, you should copy the .dfm to the directory with the compiled units (.dcus), if that is the only directory you want in your search path. The BPL will of course contain the .dfms, and you need a .dcp to be able to link a BPL with your app.
Third party tools must have put the .dfms together with the .dcus in the directory using their installer, indeed.
Instead of copying *.DFM manually you can use Post-Build Event (Project/Options/Build Event), ex:
copy “$(PROJECTDIR)\Unit1.DFM” “c:\Scratch\wow\Unit1.DFM”
I found a way to do this without moving .dfm files to the directory of .dcu files, so you can have a directory for .dcu files only one for .dcp files only and another for .bpl files only.
All you need to do is to create another directory on your good structure, as I do. The directory is called RES and in it should be placed all the resource files (.res files, not .dcr files) that are used by applications compiled using your packages (components). In the Delphi Library Path, you must include in addition to the DCU directory (you should already have) a directory named RES.
On your component (design time) do everything you want with the form (design it, put other components, etc). In the source code of the unit you replace {$R *.dfm} with {$R UnitName.dfm}. In doing so, save all and close the DPK. Now move the .dfm file (do not copy, move!) to the RES folder (the .dfm file is a resource file to the Delphi. The {$R} directive is proof!) and after that open the DPK again to understand what has changed.
First realize that you may not open the form (F12) from his unit, though no error was issued by Delphi about "DFM missing".
Now, do a Build on your package and then install it. Realized again? No errors displayed! This happened because you have indicated the location of .dfm file in the Delphi library search path (RES directory).
Done! You can use your component and dfm will be found when your component is included in an application.
Many of you can now say that this way I will not longer be able to visually edit a form in the component design time. Yes this is true, but if you think about it, why would I want to change so often a form into a component that, in practice, should only be used and slightly edited? Draw your own conclusions ;)

Is there a way to trace through only project source in Delphi?

I'm using Delphi 2010 and I'm wondering if there's a way to trace through code which is in the project without tracing through calls to included VCLs.
For example - you put in a breakpoint and then use Shift+F7 to trace through line-by-line. Now you run into a call to some lengthy procedure in a VCL - in my case it's often a Measurement Studio or other component that draws the doodads for a bunch of I/O, OPC, or other bits. At any rate, what happens is that the debugger hops out of the active source file, opens the component source, and traces through that line by line. Often this is hundreds or thousands of lines of code I don't care about - I just want to have it execute and return to the next source line in MY project.
Obviously you can do this by setting breakpoints around every instance of an external call, but often there are too many to make this practical - I'd be spending an hour setting a hundred breakpoints every time I wanted to step through a section of code.
Is there a setting or a tool somewhere that can do this? Allow one to trace through code within the project while silently executing code which is external to the project?
The debugger won't step through units that don't have debug information, so the goal is to make the compiler omit debug information from the units you're not interested in.
Put your library units in a separate library project. That gives you the ability to have separate compilation settings for those units without affecting your project. Compile the library without debugging information enabled. Then remove those library units from your project. You can continue using them, but they won't belong to your project anymore.
An important aspect here is that the DCUs should reside in a separate directory from the source code. If the compiler finds DCUs and it happens to see the source code in the same folder, then it's liable to recompile that code when you really don't want it to. Set your projects' "DCU output folder" to something other than the default.
To really do it right, you can do what the VCL does and compile two different versions of your libraries. Compile one with debug information, and one without, and put the compiled files in different directories. Add the directory with the debug versions to your Delphi configuration; there should already be a folder listed there that contains the Delphi-provided debug DCUs.
When you set up two different versions, you allow yourself to choose whether you want to step into the library code. Simply toggle the "use debug DCUs" option in your project settings. Delphi will automatically add and remove the debug-version folder from the search path when you toggle that setting.
Note that even though you'll have a separate library project for your library units, you don't need to link to or distribute the DLL or package that that project generates. You can continue using the DCU files directly in your EXE project. You're only setting up the separate project so that you can select different compilation settings for those units. Add the library project's DCU output folder to your EXE project's search path, and you can continue using the units directly without any need to distribute the library project's DLL or package.
The IDE may try to add new directories to the search path automatically. Don't stand for that. If there's a source directory there that the IDE added for you and you don't want it there, feel free to remove it. The IDE is just trying to be helpful, but it doesn't know about your plan to have separate source and compiled folders.
Just to complete your options: If your libraries for some reason must be compiled with debug information (I usually use everything with debug info, including the VCL and RTL.) and you accidentally trace into a method you are not interested in, you can use Shift+F8 to run until the method returns to your code.
Another method is to use the debug information and Local symbol information compiler directives - add {$D-$L-} to the start of each unit.
This will ALWAYS suppress the generation of debug information for that unit. If you do need to trace into the code, comment out the directives.

Delphi Compile and Build produce different binary on same project

In a fresh VCL application Compile and Build operation produce the same binary and map file (with minor differences at the end of .exe file even if "include version information in project" option is switched off - already discussed). Map file is the same byte to byte. But wen I add any third-party component the binary and map(!) file produced by Build and Compile are significantly different!
Tested on two versions of Delphi:
- Version 7.0 (Build 8.1)
- CodeGear™ RAD Studio 2007 Version 11.0.2902.10471 (+December 2007 Update)
Step to reproduce:
Create New VCL Application. Possibly add any native Delphi component (I try all components from Standart, Additional, Win32 and System tab).
Turn on Detailed Map file on Linker tab of the Project Options.
Build project.
Rename output .exe and .map file (for example: project1.exe to project1b.exe and project1.map to project1b.map).
Compile project.
Rename output .exe and .map file (for example: project1.exe to project1c.exe and project1.map to project1c.map).
Compare files from step 4 and 6. (I use WinMerge
2.12.4.0).
We have little different .exe files and fully identical .map files. Then if we repeat all steps again but use in the project third-party component (I try ODAC, DOA, DevExpress and selfmade) we get more different .exe and different .map files.
Why? Any suggestions?
UPDATE
Some information about how I found this and why it's interests me:
Project is build from simple script with MSBuild. When in the project was added translation thru ITE (dll with resources) I found that when project was Build (from script or from IDE) - translated version work wrong - some text on button, labels etc. got from wrong place (literally from another button, labels). When project Compiled from IDE - everything is ok. So I start compare Build and Compile output...
What you're seeing is simply an artifact of the built-in make logic of the compiler. When you do a build, it tells the compiler to build all available sources. So Delphi processes each source file and for each unit in the uses lists for which it finds source, it will then build that file. It does this recursively. When you do a compile, only the existing .dcu files are loaded and if they're found to be up-to-date, nothing is done. This can actually lead to a different order in which the units are discovered since each .dcu will effectively "flatten" the uses list. Since the units are discovered and loaded in a different order, they are in-turn, linked in a different order. This is why your map files look so different. Given the same sources, the map file should be the same if you do two builds in a row or two compiles in a row.
Other causes for differences are more mundane and include things like the PE header time stamp, and other bits of padding and alignments.
There is two parts to this answer I believe.
Part of the problem your seeing, IIRC, is that the compiler doesn't zero out memory before doing a compile/build. Thus anything left in uninitialized memory becomes filler in the output for alignment purposes.
I also seem to recall that there is a date time stamp included in the pe header information for the application. that will cause a difference every time.
I'm not the best person to confirm this but this is what I seem to recall from past discussions.
People like Allen Bauer or Barry Kelly would probably be able to give better/more accurate information on this.
If you use compiler defines in your project and just changed those, if you do a compile, you won't see any changes to the dcu's and the resulting module (exe or dll). If you do a full rebuild the compiler defines are used in the newly created dcu's and modules.
I have seen this in a large project group where we use modules in different projects with different defines and all dcu's are stored in the same directory.
Ergo: The compiler does not enforce the dependancies on the defines in this case.
Perhaps you did see the same issue.

Resources