Is there a way to trace through only project source in Delphi? - 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.

Related

What could cause a mismatched DCU file?

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.

How to divide a Delphi project into BPLs properly?

The company I work for develops a system in Delphi, that contains dozens of exe modules, and each of them is identical to a certain degree if it comes to source code. Sadly, nobody has ever cared about using libraries to put the shared code in. This means that each time there is a bug fix to do in the code all these modules share, a programmer has to make corrections in all of them separately! It always takes so much time...
I decided to find a method to put the shared code into libraries. I considered DLLs and BPLs. In this case BPLs seemed much more programmer-friendly and much less troublesome, especially that the code is used only in our software and only in Delphi.
I put all the code shared by all the exe modules into BPLs and everything seems fine, but there are certain things I don't understand and would be grateful if you explained them to me.
What I expected after dividing the code into BPLs was that it would be enough to deploy exe files with the BPLs I created. But it turned out that they need an rtl100.bpl and vcl100.bpl as well. Why is it so? I want to deploy exes and my BPLs only. I don't want to provide end users with a whole bunch of libraries supplied by Borland and third party companies :). I want them to be compiled within exes as they used to be compiled before. Is it possible to do that?
What I did so far was:
I put all shared pas units to BPLs. Each BPL contains units belonging to the same category so it is clear for programmers what code to expect in a given BPL.
Each BPL is a "runtime and designtime" library.
Each BPL is "rebuilt explicitly".
The two latter are default project settings for BPLs.
And if it comes to the exe projects:
I deleted all units that I had earlier put to BPLs.
I installed my BPLs from the Tools->Install package menu in BDS 2006.
In my exe project settings I checked the option "build with runtime packages" and I listed all my BPL packages in the edit box below (only my packages, as I cleared all other ones that appeared there).
This is all I did. The exe projects compile properly, but I have no access to the source code of BPLs (I can't navigate into that code from my exe projects), even though all BPLs are stored together with their source code files. Why? It seems strange to me.
I always tend to write lengthy descriptions - sorry for that :). I will appreciate your help. I just need a few words of explanation to the points I mentioned: deploying exe with my BPLs only, the correctness of what I did as a whole, and the inability to navigate into BPL source codes. Thank you very much in advance!
Thank you all for the discussion. Some said the approach I chose was not a good idea. Our software consists of more than 100 modules (most of them being something like drivers for different devices). Most of them share the same code - in most cases classes. The problem is that those classes are not always put into separate, standalone pas units. I mean that the shared code is often put into units containing code specific to a module. This means that when you fix a bug in a shared class, it is not enough to copy the pas unit it is defined in into all software modules and recompile them. Unfortunately, you have to copy and paste the fixed pieces of code into each module, one by one, into a proper unit and class. This takes a lot of time and this is what I would like to eliminate, choosing a correct approach - please help me.
I thought that using BPLs would be a good solution, but it has some downsides, as some of you mentioned. The worst problem is that if each EXE needs several BPLs, our technical support people will have to know which EXE needs which BPLs and then provide end users with proper files. As long as we don't have a software updater, this will be a great deal for both our technicians and end user. They will certainly get lost and angry :-/.
Also compatibility issues may happen - if one BPL is shared by many EXEs, a modification of one BPL can bee good for one EXE and bad for some other ones - #Warren P.
What should I do then to make bug fixes quicker to make in so many projects? I think of one of the following approaches. If you have better ideas, please let me know.
Put shared code into separate and standalone pas units, so when there is a bug fix in one of them, it is enough to copy it to all projects (overwrite the old files) and recompile all of them.
This solution seems to be OK as far as a rearly modified code is concrened. But we also have pas units with general use functions and procedures, which often undrego modifications - we add new functions there whenever necessary, but in single projects. So imagine that you write a new function in one of the 100 modules and put it into its general use unit. After a month or two you modify a different module and you think you need the same function you wrote 2 months ago. You have to find the module (it's difficult if you don't remember which one it was) and copy the function to your code. And obviously - the general use units become completely different in each module as long as they are stored in each project separately. And then, if there is a bug fix to do... the whole story repeats.
Create BPLs for all the shared code, but link them into EXEs, so that EXEs are standalone.
For me it seems the best solution now, but there are several cons. If I do a bug fix in a BPL, each programmer will have to update the BPLs on their computer. What if they forget? But still, I think it is a minor problem. If we take care of informing each other about changes, everything should be fine.
#CodeInChaos: I don't know if I understood you properly. Do you mean sharing pas files between projects? How to do that? We store source codes in SVN. This means that we would have to store shared code in a separate folder and make all projects search for that code there, right? And download from the SVN a project and all folders it is dependent on...
Please, help me choose a good solution. I just don't want the company to lose much more time and money than necessary on bugfixes just because of a stupid approach to software development.
Thank you very much.
Even though this question has an accepted answer I'm going to take a stab at it.
The title asks how to divide a project into bpls but the real question appears to be:
"What's the best way to share code between projects?"
There are a few ways to do this:
Shared units
Dlls
BPLs
Regardless of which direction you go you will likely need to restructure your projects. From your description it sounds like each project is developed in relative isolation. Code is shared using copy/paste, which quickly gets out of sync and result in a lot of duplicated effort. So lets examine each of the techniques for sharing code.
Shared units
This is the most straightforward approach. You create a shared location and place code you would like to reuse among your projects into this location. The units are statically linked into your projects so you don't need to worry about deploying extra dependencies along with the main executables. Statically linked units are by far the easiest to troubleshoot and debug.
The compiler needs to be able to find your shared units. There are 4 ways to tell the compiler where to look.
Add them to the project - SHIFT+F11 - Adds a reference to the unit into the project files (dpr, dproj). The IDE will normally use relative paths if the unit is located under the same directory tree as the project files, otherwise it will use absolute paths, which can be problematic if developer machines aren't configured identically.
The project's Search Path - CTRL+SHIFT+F11 Delphi Compiler > Search path - Add a directory and the compiler will look there to find units mentioned in the uses clause of any unit in the project. Its best to use relative paths if you can. You can also use environment variables: $(MyPath)
Global Search Path - Tools > Options > Environment Options > Delphi Options > Library - Win32 > Library Path - Any paths listed here are available to all projects on a machine. This is machine dependant
Command line - If you build from a script or build automation tool you can set the search path using the dcc32's -U switch or msbuild's /property:UnitSearchPath= switch.
Options 1 and 2 will be the most useful.
As far as your SVN repository goes you have a few options for organizing the projects and shared units. The simplest would be to place all projects under single trunk along with the shared units:
Projects
trunk
ProjectA
ProjectB
ProjectC
Library (shared units)
If for some reason the above structure isn't possible you could try this alternative:
ProjectA
trunk
Library (branch of main library)
ProjectB
trunk
Library (branch of main library)
ProjectC
trunk
Library (branch of main library)
Library
trunk (main library)
In this configuration changes made to each project's library folder would not be immediately available to the other projects. Each project would need to synchronize changes with the main Library project on a regular basis. A side effect of this is that changes that break other projects will be delayed until the other projects are synchronized. Whether you consider this a good or bad thing depends. On the one hand bugs are easier and cheaper to fix when the code they involve is still fresh in the developer's mind. On the other hand if you don't practice unit testing (which I highly recommend you do) or the code is very fragile or you just have developers prone to making reckless changes you may want to control how frequently those changes get pushed into other projects.
Dlls
Dlls allow you to share code by linking to it at runtime. They expose functions that can be called from a main executable or another dll.
While dlls are always linked at runtime you decide whether they are loaded at application startup or only when needed. Loading at startup is called static loading and in Delphi is accomplished using the external directive. The vast majority of the rtl/vcl classes that wrap system api calls use static loading. Dynamic loading lets to delay the loading of a dll until it is required. This uses the WinAPI functions LoadLibrary and GetProcAddress. A corresponding call to FreeLibrary will unload a dll.
Unfortunately standard dlls limit what kind of datatypes can be passed. If you need to access a dll from non-Delphi projects you will need to limit yourself to using c style data types. If you will only be using a dll with Delphi projects you can safely use Delphi strings and dynamic arrays as well if you use the SharedMem unit in the dll and any projects that use it.
You can safely use object's within the dll without problems but if you want to pass objects between the dll and the application you'll need to extract the object's data and pass it as primitive types and reassemble it into an object on the other end. This is called (de)serialization or marshalling and there are much easier ways to do this than rolling your own.
COM (Component Object Model) is well supported in Delphi but it has a bit of a learning curve. Consuming COM objects is pretty straightforward but designing one will take time if you're not familiar with COM. COM has the advantage that it is language neutral and is supported in the majority of languages targeting the Windows platform (including languages targeting the .NET framework).
Bpls
Bpls (also called simply "packages") are specially formatted dlls that make working with objects a lot easier. Like standard dlls they are linked at runtime and can be statically or dynamically loaded. They are easier to learn and use than COM dlls and provide more seamles integration into your projects than COM. Packages are composed of two parts: the bpl and the dcp. The dcp is like the dcu files generated when you compile a normal unit file except it contains a whole bunch of units in it. Using a class that is compiled in a bpl is as simple as adding the dcp to the project's package list then adding a unit to a uses clause of one of the project's units.
When you deploy the app you'll need to install the bpl as well. As other's have noted you have to include the rtl package at a minimum and most likely the vcl package if you use any forms. There is a way around deploying Borland supplied bpls with your projects. You can create a "mini" rtl package that contains only the units your project need. The difficultly is in determining which units to include.
Summary
From the description you've given creating a library of shared unit files to statically link against may be the most expedient route. I would also suggest trying out a program called Simian. It will help you track down duplicate code in your code base for inclusion in your shared library. It doesn't directly support pascal but it does a decent enough job using the plain text parser with a little tweaking of its configuration.
Also I can't stress enough the value of unit testing. Especially if you're moving toward shared libraries. A suite of well written unit tests run on a frequent basis will give you instant feedback when a developer changes a class and it breaks an unrelated project.
Imagine you have a project with an EXE and two different BPL modules, and somewhere in that codebase, there's a line that says if MyObject is TStringList then DoSomething;. The is operator works by examining the object's class metadata, stored in the VMT, and then following a chain of VMTs through the ClassParent pointer, to see if any of them match the class reference (also a VMT pointer) for TStringList. In order to make sure that this will work correctly, there needs to be one single VMT for TStringList that's the same throughout your entire program, no matter how many BPLs it's divided up into, which means it has to be in its own package. That's why system runtimes like rtl*.bpl and vcl*.bpl are necessary, and there's not much you can do about that. It's part of the price of using BPLs.
As for not being able to debug, you need to make sure that the BPLs are built with debug info enabled and that the debugger knows how to find the folder where the DCP (the file containing the debug info for the BPL) is located. And you won't be able to trace into system BPLs, because debug-enabled DCPs weren't shipped with your version. They were added pretty recently, I think in XE but it might have been in D2010.
Why can't I browse my source code? Is there a way to fix this?
You can not browse the source code of the units included in the packages because they are neither in your project, your library or search path.
The way I solve this is adding the directories to the project search path. This way the compiler does not know about those files (and does not try to recompile them) but the IDE let's you browse their content and debug into them.
"In my exe project settings I checked the option "build with runtime packages"
That is why you cannot deploy without the BPL's etc - this option is confusing for a lot of developers -"build with runtime packages" means that you will need the bpl's present at runtime. Uncheck that option and the packages will be linked into your exe at compileTime. (Your exe will g-r-o-w in size.) The idea behind the "build with runtime packages" is to keep the size of exe's down and allow several apps to share common bpl's because they are NOT linked into the exe # compileTime - that's the upside. The downside you are now experiencing - you must distribute your bpl's with your exe.

Delphi: how to exclude units from debugger?

Sometimes as I am debugging step-by-step, just before a FormCreate Event or just after the FromDestroy the debugger starts to open DevExpress units (cxContainer.pas, ...) and so before FormCreate my "F8" leads me to cxContainer instead of going into the next line of my code.
(this is just an example, it can happen of course with any 3rd party library)
How do I tell the debugger "debug only my units" (only the pas files listed in dpr file?)
Of course sometimes it is useful to debug libraries, but in most cases it isn't.
You'd better follow VCL convention for your third-party components:
Change DCU output path in all the third-party packages to a folder different than the folder you store the PAS files.
Compile each package once in Debug mode, and save the generated DCU files in a folder (e.g. Debug DCUs).
Compile each package once again, but this time in Release mode, and save the generated DCU files in a folder (e.g. Release DCUs).
Go to Delphi options and add path of release DCUs to "Library path".
In Delphi options, add path of source files to "Browsing path".
In Delphi options, add path of debug DCUs to "Debug DCU path".
This way, Delphi will only see release DCUs of that third-party component when you are compiling your project, so the debugger cannot step into the source code.
On the other hand, since source path is included in "Browsing path", you can still navigate to the source code inside IDE by Ctrl+Click on unit name, or anything defined in those units.
If you want to debug component, you can go to "Project | Options | Delphi Compiler | Compiling", and enable "Use debug .dcus". This will force compiler to use "Debug DCU path" instead of "Library path".
VCL works the same, generally you don't step into VCL source code when you are debugging your project, but if you enable "Use debug .dcus" you can debug VCL source code too.
JVCL also organizes its packages and source code the same way.
EDIT:
If you take this approach, and want to have code browsing (Ctrl+Click) working; please take note that when you compile release version of packages, you must set Symbol Reference Info in "Project | Options | Delphi Compiler | Compiling" to "Reference Info"; otherwise, Ctrl+Click won't work for those units. By default, Release build configuration sets Symbol Reference Info to None.
A quick and simple solution is disabling the DEBUG switch ({$D-}) for any libraries you're using. Many libraries (including DevExpress) use a global include file, usually at the top of each source file, or right above or below the "unit" statement (e.g. unit cxContainer; {$I cxVer.inc} interface ). Open that include file (click on it and press CTRL-Enter) and add {$D-} right at the top, and comment out any existing {$D+}.
There is only one way to tell the compiler not to debug a unit: compile it without debug information.
If you have the source to your libraries, you can rebuild their package after having turned off the "include debug info" compiler option for each package in the library. If you are lucky, your libraries will include an .inc file which specifies the compiler options they need and which they include in each unit. In that case all you have to do is edit this inc file and rebuild all packages.
If you don't have the source to your libraries, the library makers may have provided two sets of dcu's: one compiled with, the other without debug information. In that case, simply point your library path to the one you need.
Turn off debug info in units you don't want the debugger going into.

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.

How can I find all the units in my Delphi app?

It's easy enough to find all your external dependencies. Just run the program and open up the Modules info window. But how can I find all my internal dependencies? I know the program keeps a list of all the units, because I've traced my way through the initialization code a time or two. But is there any easy way to access this list from the debugger?
The Delphi debugger can show you which units were compiled into a module (exe, dll or package). You can see this in the Modules view (View | Debug Windows | Modules). Click on a module in the upper left pane, and the lower left pane will show all the compilation units that were built into that module. If a particular compilation unit was made up of multiple source files (i.e a .pas and a .inc file), that will be shown too (when you expand the comp unit).
Alternatively, you can have the Delphi compiler show you a list of used .dcus by passing --depends when you compile a project. It will output a .d file with a list of the .dcus (and .dcps) that were required.
Another, but rather cumbersome way, is to generate a map file, it contains a list of all units used in a program.
see also this answer:
How can I find all the units in my Delphi app?
I use the GExperts Project Dependencies.
With the "Used By...", you can see units included but not used by anyone.
But you can't see unit included in uses clauses that could be removed when they don't have any code actually called.
Here's the help:
Project Dependencies
The project dependency expert enables you to see what units a particular unit uses, and in turn what units use a particular unit. When this expert is activated, it parses all of the current project's source code for uses clauses and builds up a list of dependencies. To view the dependency information for a particular unit, click on it in the left pane. The right pane will contain the dependency information. Indirect dependencies are units that are used by used units of a particular unit.
You can refresh the dependency information at any time by clicking the refresh button on the toolbar and you can sort the file listing by clicking on the column headers.
(source: gexperts.org)
OTOH, you can also use free Peganza's ICARUS as a more detailed reporting tool but less interactive...
Have you looked at Pascal Analyzer or the free limited version, Icarus, from Peganza Software? They will create "uses reports" telling you what module uses what others, so that should give you the info you're after.
Marc
GExperts has a Project Dependencies tool. I have used it before when trying to track down used units. You can't search in it but you can export the list to a CSV file and search there. This also only lists what is in the uses section. If you have a module included that is not being used it will still show up.
I know of at least two ways you could try to get a view of all the units used in your project
CTRL-SHIFT-B opens the object browser. If I'm not mistaken, here you can get a view of used units. I'm not entirely sure about this method and don't have Delphi available to verify it.
Use Modelmaker; Modelmaker can give you a tree like view of all your unit dependancies. Look at the Visualizing existing code section for more information.
The easiest way is to compile program and check which .dcu was created by compiler. Make sure to setup compiler to create .dcu in a separate directory, for example c:\dcu. I have created simple utility that searches .pas for every .dcu file in directories that are in a compiler search path (that can be read from .cfg, .dof or .bdsproject file).
You can use a MAP file in conjunction with MapFileStats, this will not just give you all your dependencies, but the amount of code (and resources) they contribute in the final executable.
Useful to spot units you have dependencies to, but use little of, as well as spotting "fat hog" units, which take everything plus the kitchen sink with them.
FWIW, reducing dependencies and eliminating hogs isn't just beneficial to executable size, it's also beneficial down the road when it'll be time to upgrade to a new version.
There is a (rather old) utility called UsgParse. It builds a treeview of all units referenced by a project.
I found a copy on the NexusDB site via
http://coding.derkeiler.com/Archive/Delphi/borland.public.delphi.thirdpartytools.general/2004-03/0231.html
source: http://www.nexusdb.com/downloads/USGParse/USGParse_src.zip
binary: http://www.nexusdb.com/downloads/USGParse/USGParse.zip

Resources