Find all compilation errors in a Delphi project - delphi

I am doing some refactoring of my Delphi project. I want to be able to make a change, then see all the places in the project that break due to that change. Similar to how Eclipse lists all the compile errors for a project (in Java).
In Delphi, I can make a change, then recompile my project, but the compiler stops when it finds the first Unit that does not compile. I have to fix that Unit, compile again, which will then show me the next error, etc etc.
I want to be able to see all the compile errors in the project at once. Then I can decide if the change is worth doing or not. For example, if the change will require hand fixing of 50 separate source files, it's not worth doing. But if it only breaks 2 files then that's an easy change to make.
Is there any way to do this in Delphi? Can I tell the compiler to keep going even after finding a Unit that does not compile?
I am using Delphi 2010

Delphi units, as a modularity feature, are conceptually at a similar level to Java jars or .NET assemblies; they compile to individual files. In neither Java nor .NET can you compile dependent modules when you have compile errors in a referenced module.
The reason they are more granular than .NET assemblies etc. owes to their history. They were designed in part around the segmented x86 architecture; the data associated with any one unit could not be any larger than 64KB. Similarly, units served as a natural division between near code and far code. If you're familiar with 16-bit x86, you'll know that pointers to far data required a value for the segment as well as the offset, while near data only needed an offset. Calling near code was also faster than calling far code. Programs were also smaller and less complex back then; the unit was a reasonable granularity of module for an entire subsystem's worth of behaviour. This is much less the case today.

There's no way to do that with the Delphi compiler, but if you're considering making a breaking change to some part of a unit's public interface, you can use the refactoring tools that come with the IDE to find all references to whatever it is you're about to change before you change it, which will give you the information you're looking for.

The Delphi compiler already tries to compile as much as it can.
Unfortunately, very often, an error is critical enough to prevent the compiler to move past the error as it cannot make an assumption as to what the code should be it if were compilable.
Moreover, very often, the errors a compiler can give after the 1st error has been encountered are not reliable and may even disappear after the 1st error has been fixed. (witnessed by all the red squiggly lines appearing and disappearing when you type)
What the compiler does however is to provide all the hints and warnings (which are called errors for some other compilers).

You can use Ctrl-Shift-Enter to see all occurances of the variable, property, method or wahtever is currently under the cursor. With that information you can decide to do your changes or not.
Alas, with the current version this feature doesn't work as reliable as it should.

Related

How to determine Borland's original compiler options for RTL and VCL .dcu files?

Background: as D7 is now officially unsupported, I'm trying to create a definitive stable and fast D7 Pro development environment, with all fixes applied directly to the source code instead of complicated patching or adding units to every project.
Borland did provide a makefile for the RTL dcu files, but even that does not produce the same size files as the official ones.
I'm wondering whether something is wrong with my setup. As an aside, what is the recommended way of creating the initial development environment now? I thought the best option would be to start afresh by downloading D7Pro and the update 7.1 from cc.embarcadero.com.
To the very best of my knowledge, the VCL is expected to be compiled with default compiler settings. Any variations to that are specified explicitly in the source code.
Of course there are debug and release versions. The former does not have optimizations enabled, the latter does.
There are some special requirements for the very low level RTL units but judging from what you say in the question, you are on top of that.
You are concerned that you will encounter the unit compiled against different version of XXX errors. But that will not occur since, as I understand it, you will be compiling the entire RTL and VCL.
Even if you re-compile piecemeal just the units that you modify, you will have no problems so long as you use default compiler options. Of course, you would have to refrain from making changes to the interface section of any unit in that case.
And even if you compile piecemeal you have to understand that there are some compiler options that have no influence on whether or not the .dcu files are compatible with others. A good example is optimisation.
I do wonder whether or not you are doing this needlessly. It sounds like you have a working solution. And nothing has changed recently. Delphi 7 updates dried up a decade ago. Why do you feel compelled to change now?

Pascal Delphi - Undeclared Identifier

I'm using the Synapse library in a Delphi project to do some networking.
When I try and use one of the Types that are defined in the external units, i.e: 'TTCPBlockSocket', it has the red underline and says "Undeclared Identifier 'TTCPBlockSocket'".
The files are all in the correct folders and the 'uses' statement can find them and shows no errors.
The strange thing is that I've had an identical setup in another project and there have been no errors in that project.
As a note: I can't install/edit the software/settings, so I can't add any fixes.
This is a well-known bug in Error Insight. It has existed since Error Insight was first introduced in Delphi 2005 or 2006, and still exists today in Delphi XE5.
It's caused by a different compiler being used for Error Insight, apparently, that doesn't have access to the same symbol set used by the Code Insight compiler (the one that helps you find symbols in the Code Editor) or the command-line compiler (the one used to actually compile your code for an application or package). It therefore only uses files that are actually referenced in the project (.dpr) file to locate symbols, and since the majority of files in the uses clause in your code aren't in the .dpr, it can't find them.
There are two fixes (one that is very easy, and one that works but is a pain in the backside):
(The easy one). Turn off Error Insight totally, in Tools->Options, the Editor Options section, Code Insight; just uncheck the box for Error Insight. I prefer this one because Error Insight doesn't work properly anyway, and it avoids the annoyance of having to use the other option every 10 minutes. This is the first thing I do when I install a new version of the IDE and see the red underlines.
(The pain way). Use Project->Add to project for every unit that contains one of the underlined symbols. This adds a reference to every unit to the project .dpr file, which causes it to increase in size drastically. It's a pain because you typically have to do that for every single unit (in my experience, including those that are part of the standard VCL/RTL) that hasn't already been added, and it very quickly becomes irritating. Error Insight doesn't tell you anything that a quick Ctrl+F9 won't anyway, IMO.

How to avoid Delphi fatal error F2051 when not all programmers have access to complete source

In our team new programmers does not get access to all the source of our application.
As long as they have to access program forms that depend only classes they can access the source, all is ok. When they have to use other classes from units they have only the .dcu, they get the F2051 error when the classes in the dcu change their interface.
Is there a clean way to get both ?
possibility to hide part of the source from new programmers
avoid the F2051 error when the classes in the "hidden" units change
I searched for a way to compile the Delphi code to a intermediate representation the way to hide the sources but to permit compilation, but I did not find anything.
You have to compile the code after the interface changes, and distribute the new .dcu to each programmer that needs to use it without source, and then they need to rebuild their applications. There is absolutely no other way to do it; the compiler requires it if there are changes in the interface.
For those "hidden" units, put the .dcu in the source control along with the .pas and make sure they are updated and in sync.
The "authorized" developers will fetch the new .pas, while the underlings will only see and fetch the .dcu.
If you really want to go that route of having 2nd class programmers, you have to do the management work that go with it.
That being said I'm personally more often that not stepping into the VCL source code when chasing a bug and trying to understand what's going on.
And I really don't like not having it (like with some low level Delphi SKU)
If you really want to create a stable binary unit that you can share with people you don't trust to read your source code, why don't you put the "secret" bits into a DLL and then load that DLL from the rest of the code.
It's called an "Application Binary Interface", either done natively with plain old pascal procedures exported from a DLL, or with COM Interfaces and a COM type-library.
Delphi has both DLL and BPL technology, to help you create something that isn't source code, but which has a stable ABI, and which will help you avoid whatever crazy little mess it sounds like you've got on your hands right now.

How do I remove dead code from an EXE file? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reduce exe file
What are some tools that, given an EXE file, remove all unused code and make a new EXE file with code really used by the application? I think that something like that should exist. Just for curiosity; but I think that it can be really good as tools for producing a smaller EXE file without unused code.
P.S.: Delphi produces standalone EXE files that contain code of all object used in an application, but not all elements of this object are really used. This makes big files.
I remember the first version of Pascal that include only code really used and did not insert unused code, and EXE files were smaller.
Current Delphi also excludes unused code. You can easily see this in Delphi. If you compile, you get 'blue dots' in the gutter of your code. Functions that are not used don't have blue dots, meaning they are excluded. If you check the Optimization checkbox in project options, code is rewritten to make more use of registers thus eliminating certain variables.
Nevertheless, Delphi executables grow, especiall when using certain units. I think the smallest .exe you can create in Delphi 7 is about 10Kb. In later versions this will probably be a bit larger.
Important causes of file size is
resources. Large or lots of images consume a lot of space. If you use icons on multiple forms, make sure to put them in a central image list (on a shared datasource). Use one of the available PngImageList implementations for smaller image size against better quality.
rtti. The runtime type information causes class definitions to consume extra space. Thise space is partly due to the meta information about the class, but mainly because all extra code. Any methods that may be called using RTTI could be bound in a kind of 'late binding' fashion. Therefor, the compiler cannot know whether the methods can be eliminated, so it needs to include them in the executable.
registered classes. Similar to 2. If a class is registered, it can be fetched and instantiated using its name as a string. Those classes must be included in the project, even if they are never used, just because the compiler cannot know if they are needed.
It's a fact that RTTI is expanded in recent Delphi versions. I think this also causes the RTTI meta information about classes to consume more space. There's only so much you can do about that.
In general, I think the Delphi compiler still does a lot of optimizing. You shouldn't have to worry about exe file size. If you do, you could try a packer like upx. I've got good esperiences with upx. It cuts down the executables to about a fifth or less of their original size, while retaining all functionality.
If you application is huge, check if you don't have a lot of debug info compiled in.
Try a release build and check if it's any smaller.
What i sometimes do is configure the project to compile all .dcu files into a single folder. That way you quickly see all of the useless units that get compiled into your .exe. It often happens that you include a single unit for a single function, but in turn you get a whole tree of dependent units. You'll just have to search your uses clauses and try to get rid of these dependencies somehow.
I think both gexperts and cnpack contain tools to show dependencies, or to scan for unused units in your project. They can be helpful with this.
After you've removed useless dependencies, you can always compress your compiled exe with upx. There are supposed disadvantages to that (barry kelly wrote about it some time ago), but i've got good experiences with it. It sometimes makes the file 4x as small which can be a big deal.

Errors using THashSet from DeHL collections library

I'm pretty new to Delphi and I'm trying to use the DEHL Collections library. (see http://code.google.com/p/delphi-coll/ ) I'm have a little trouble with it from the IDE perspective. It compiles and runs correctly, but Delphi XE shows errors anywhere I use the HashSet library. The biggest grievance is that is prevents me from using code completion.
The first location I get the error is in an object declaration:
uses
SysUtils, Windows, Collections.Base, Collections.Sets, Collections.Lists,
adscnnct, adstable,
uOtherClass;
type
OneClass = class(OtherClass)
private
_bad: THashSet<string>; // THashSet underlined
_good: TList<string>; // No problems
end;
The error states: "Type arguments do not match constraints"
I don't think it's configuration as I can use TList just fine, but here is how I set it up: I've copied the library to Projects/Libs/DeHLCollections/Library and compiled the library to Projects/Libs/bin. I've included the bin directory in my global library path, which got it to compile and run. I have tried adding everything (/libs, /DeHLCollections, /Library) to it as well in hopes of getting the IDE to help me out, but it doesn't seem to be helping.
Anyway to fix this, or do I just have to deal with it?
Using DeHL Collections version 1.1.1.119
Welcome to the troubles with using Generics laden code. DeHL and generics work a lot better in Delphi XE than in any previous Delphi version, but that's not the same as it "not having any problems". The problems I experience are exactly like yours.
My opinion is that DeHL shows every sign of having been written by a master delphi programmer, and that it's a thing of beauty, in some ways. It's also a source of great pain, through no fault of its own.
Delphi contains not one or two, but at least three (maybe four?) separate parsers, including the full compiler parser, and a few IDE-parsers used for things like Error Insight (the errors you see even before you build) and the code completion data parser. Each has different language support limitations with regards to generics. It is possible perhaps that DeHL could be written to avoid parser problems with all the various Delphi parsers. I have not seen a guide ever written that shows the limitations, but I wouldn't be surprised if complex type declarations in the form TSomething<TSomething<ISomethingElse>,TBar<IFoo>> breaks more than a few of those parsers.
If you intend to use Generics very heavily, you may as well turn off Code Completion and Error Insight. You might also want to save often, and be prepared to experience a lot of compiler problems. And don't try to compile generics-heavy code and put it in packages either. I have experienced a lot of URW and AV (internal compiler faults) when I write generics based code. I find that the Delphi compiler team is great at fixing whatever gets reported, but that the Generics are really most stable for me when I restrict myself to using the Generics.Collections that come with Delphi, and not using other generics based code. It seems it is possible to write stuff using the generics features, that the IDE and two-way tools, and code-completion is not yet fully ready to handle. That means, phenomenal cosmic Generic powers come at a cost to the classic RAD IDE productivity features.
That being said, the latest DeHL sources from Subversion work fine for me and build and run with no errors, but the most recent source ZIP of the entire DeHL collection had problems for me.
I expect that over the next few releases of Delphi, whatever issues have been found (and DeHL seems to be a great place to push the boundaries, and that's one of the reasons i'm a big fan of it) will be fixed, and you won't be wondering why heavy-generics break your IDE features, because they'll all be working again.

Resources