Is it any way to add .map file as resource of the project when compiling? - delphi

I'd like to add the map file as resource, then extract the file every time that execute the system, to ensure that the map file is always right, and make the life of support easier. In Delphi 7 I can compile the project, with the map file as resource, but the map is wrong, because when an exception is raised the call stack is wrong. In Delphi Seattle, I can't even compile, because it tries to add the resource before generate the map. I know that I can add the file in a post-compile thask, but is there any way to do it in compiling/building time?
Sorry if I'm not very specific, that's my first question here. Thanks.
UPDATE
After I read some answers, I did some research. I was already using JEDI exception unit in my project, but I did not know the JEDI Debug expert. It does exactly what I want and more.
JEDI Debug expert convert a .map file to .jdbg file, wich is an encrypted file of map (map is just a text file). Also, the jdbg file is about 12% smaller then the map. It also has the options to insert the jdbg into binary (exe). To do that, I enabled the options:
Project -> JCL Debug expert -> Generate .jdbg files -> Enabled for this project
Project -> JCL Debug expert -> Insert jdbg data into binary -> Enabled for this project
Project -> JCL Debug expert -> Delete map files after conversion -> Enabled for this project (if you want to delete the file, of course)
To use this tool outside the IDE, with Jenkins for example, I had to build the project available in JEDI\jcl\examples\windows\debug\tools\MakeJclDbg.dpr. After build, it will generate the exe file in the bin directory of jcl. How to use:
MakeJclDbg -J -E -M map_filename
J - Create .JDBG files
E - Insert debug data into executable files
M - Delete MAP file after conversion
Executable files must be in the same directory as the MAP files. This will create the jdbg file (based in the map file), insert into the exe and delete the map. With this (and with the exception unit of JEDI), when an exception is raised, It's available to me the stack trace, the versions of all dll's used by the system, operation system info, and more, and also send all this to an email.
I realised that Embarcadero also have jdbg files of theirs bpl, so I think they use JCL tool as well.

No, the map file is generated after the program output is linked. It is impossible to incorporate a, not-yet generated, map file as a resource into the project.

You're missing the point.
The MAP files are generated as a separate file to avoid increasing the size of your executable. Trying to embed that file back into the executable as a resource simply defeats the purpose.
You haven't mentioned what debug framework you're using. But there are other ways to provide debug information, and I suggest you refer to the documentation of the debug framework you using for the specifics. I'll just offer some general concepts applicable to most of the frameworks I've tried.
If you're happy with increased EXE size and want debug information included within your executable: Don't use the map file option. Simply enable the linking option to include debug information. (And ensure your debug framework will use it.)
Most debug frameworks recommend compiling with stack frames turned on. This is very important because it makes it easier for the debug framework to deduce the call stack.
Some debugging frameworks have a feature that allows guessing missing call stack information. If enabled, you will need to manually ignore any stack entries that don't actually make sense.
Of course, don't forget that any units compiled without debug information won't have debug information to include in the final executable.

Related

Managing very large codebases in Delphi using a Library of Debug and Regular DCUs I built myself

I am trying to resolve this compile error, occuring only in Debug config, and only in the case described below:
[dcc32 Fatal Error] MyIndyTCPChannel.pas(22): F2051 Unit IdIOHandlerSocket was compiled with a different version of IdGlobal.IdDisposeAndNil
I am working on a very large Delphi codebase, with 2.5 million lines of in-house code, and 3 million lines of component code, which includes several large commercial Delphi component suites (Developer Express, TeeChart, and others), and a large number of open source delphi components as well, plus a fairly large in-house developed set of components, numbering 252 packages, of which about 140 are designtime+runtime or designtime, and the others are runtime packages (which are also loaded, into the IDE at runtime, by DLL-dependencies in their associated designtime package).
Our main library path has been optimized down to be small as can be, and it contains the paths that Delphi ships with as standard, plus three more we added, the primary one is a single "OurCompanyLibraryDCU" folder, which contains underneath it folders for the two platforms and two configurations that we use:
c:\dev\OurCompanyLibraryDCU\Win32\Release
c:\dev\OurCompanyLibraryDCU\Win32\Debug
c:\dev\OurCompanyLibraryDCU\Win64\Release
c:\dev\OurCompanyLibraryDCU\Win32\Debug
Each of the above folders contains the set of BPL, DCP, and DCU files in a single folder, for that platform/config combination.
A macro like the following, in the project options is used, so we can change platform, and config, and have the directories resolve correctly:
$(OURCOMPANYLIBRARYDCU)\$(Platform)\$(Config)
OURCOMPANYLIBRARYDCU is an environment variable and $(X) is the syntax to expand an environment variable, in the context of the Delphi IDE.
I am trying to get the most important and largest VCL Application project (call it BigApp.dproj) to build so that the project search directory only contains our APPLICATION source folders and does not need the project search path to contain all our third party component LIBRARY source code. To do that, we need to link against the debug DCUs, or release DCUs.
So far we have everything working except for the case where you have both Debug and Release DCUs available. The release DCUs are in the library path, and the debug DCUs are in the Debug DCU path, in the IDE settings. Confronted with the choice between these two libraries, Delphi's linker appears to fail, whenever both sets of DCUs exist, with errors in this form, when I click Build, and the Build Configuration is set to Release, I get F2051 errors. The ordinary cause of an F2051 error is that multiple incompatible binary DCUs exist and are both accessible, and the linker is failing to make it all work. However, when you want both Debug and Release DCUs both in the library path, I thought that this sort of thing would not occur, due to the Linker selecting the debug or release DCUs for you.
If I have not build the Debug DCUs, the above problem does not occur. I suspect that my Debug DCUs are subtly "invalid" or that the Debug-DCU-selection algorithm inside Delphi is not working, but have no idea why, or how to fix this.
Multi-part-Question:
A. Is having a single folder for each platform/config combination, containing the DCU, BPL, and DCP in a single folder, and then added to the IDE Library Path known to cause problems? Do I need three sub-folders, making a total of 12 folders for every platform+config+filetype, or can I keep them together by platform+config?
B. In a package compilation situation, is it okay to have the IDE Library path contain the OurCompanyLibraryDCU folder, and also have that folder configured as the DCP Output Directory, Package Output Directory, and Unit Output Directory? My concern is that by having input folder and output folders the same, there is a case where the compiler could be failing to rebuild a Unit from .pas source, and simply linking the prior compile's DCU.
C. If I'm going about this wrong, how instead, shall I prevent the over 2.5 million lines of component LIBRARY code from being compiled from source each time I build my BigApp, instead only link them via DCU, and still have the debug and release dcus work properly?
D. I can get past the original error if I go to the Win32\Debug folder and delete IdGlobal.dcu. This suggests to me that my package compilation (for debug config) is producing an INVALID IdGlobal.dcu. Is that even possible? Can delphi silently output garbled DCUs?
Notes: I'm not using, and can not use Runtime Packages, to deal with the application size problems.
Update: The first thing I should have done here is verify that ZERO additional DCU files are ANYWHERE on my harddrive, ANYWHERE. That's the standard F2051 error advice. I'll update this question after I've taken care of that. It appears possible that Delphi will itself COPY a DCU from one place to another, or that a bogus DCU that is NOT in the CURRENT search path might have been in some other project's search path. A kind of bucket-brigade of bad-DCU-copies can occur. I'll update the question once I'm sure what kind of bad-DCU-generations-or-copies are occuring.
Update 2: I have now guaranteed that no additional copies of IdGlobal.dcu exist before building, and the problem still reproduces. So the question then turns on the compiler options used when building the IdGlobal.dcu, versions the compiler options used when building BigApp.dproj in Debug build.
Update 3: Although all my package compiles appear to complete without error, it seems they were not using a correct library search path, during the time when the DCC32.exe or MSBUILD.exe is being launched to build the packages. This library path inconsistency issue appears to be the core issue, thanks to Sir Rufo for pointing that out.
Perhaps I can shed some light on the order of search paths presented to the compiler, which should make clear why the problem happens in the first place and can be cured (at least in your situation) by adding the Debug DCU path at that specific location. All these observations were made with XE7.
There are several places in the IDE where you can specify search paths:
Library path (Delphi-Options - Library)
Translated Library path (Delphi-Options - Library-Translated)
Debug DCU path (Delphi-Options - Library)
Translated Debug DCU path (Delphi-Options - Library-Translated)
Search path (via Project Options)
When the Library language is set to English, those pathes are given to the compiler in the order 5,1 or 3,5,1 depending of the setting of Use debug .dcus. This is already a bit weird as the debug dcu path takes precedence over the project search path.
So f.i. to make the compiler find our own dcu files of a newer Indy version, we have to place the corresponding paths in front of the paths under 1 and 3.
Now things get complicated when the Library language is set to something different than English. In this case the translated paths come into play resulting in the order 2,5,1 or 4,3,2,5,1 depending of the setting of Use debug .dcus.
To make the above example with a newer Indy version work, you have to tweak the translated paths, too.
The culprit lies in CodeGear.Delphi.Targets, which places the paths in this order. I was able to modify this file so that the natural order of paths is used: 5,2,1 or 5,4,3,2,1. If anyone can confirm that I am allowed to show these changes here I will do. Perhaps I can provide a patch only.
Update: Here are the changes of CodeGear.Delphi.Targets from XE7 as shown by Mercurial
## -122,20 +122,19 ##
<DcpFilename Condition="'$(DcpFilename)'!='' And !HasTrailingSlash('$(DcpFilename)')">$(DcpFilename)\</DcpFilename>
<DcpFilename Condition="'$(DcpFilename)'!=''">$(DcpFilename)$(MSBuildProjectName).dcp</DcpFilename>
- <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(DelphiLibraryPath)</UnitSearchPath>
- <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' == ''">$(DelphiLibraryPath)</UnitSearchPath>
-
+ <UnitSearchPath>$(DelphiLibraryPath)</UnitSearchPath>
<UnitSearchPath Condition="'$(DCC_TranslatedLibraryPath)' != ''">$(DCC_TranslatedLibraryPath);$(UnitSearchPath)</UnitSearchPath>
<UnitSearchPath Condition="'$(DCC_DebugDCUs)'=='true' And '$(DelphiDebugDCUPath)'!=''">$(DelphiDebugDCUPath);$(UnitSearchPath)</UnitSearchPath>
<UnitSearchPath Condition="'$(DCC_DebugDCUs)'=='true' And '$(DCC_TranslatedDebugLibraryPath)' != ''">$(DCC_TranslatedDebugLibraryPath);$(UnitSearchPath)</UnitSearchPath>
-
+ <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(UnitSearchPath)</UnitSearchPath>
+
<___ResourcePath Condition="'$(DCC_ResourcePath)' != ''">$(DCC_ResourcePath);$(DelphiLibraryPath)</___ResourcePath>
<___ResourcePath Condition="'$(DCC_ResourcePath)' == ''">$(DelphiLibraryPath)</___ResourcePath>
+ <___ResourcePath Condition="'$(DCC_TranslatedResourcePath)' != ''">$(DCC_TranslatedResourcePath);$(___ResourcePath)</___ResourcePath>
<__ResourcePath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(___ResourcePath)</__ResourcePath>
<__ResourcePath Condition="'$(DCC_UnitSearchPath)' == ''">$(___ResourcePath)</__ResourcePath>
<ResourcePath Condition="'$(BRCC_OutputDir)' != ''">$(BRCC_OutputDir);$(__ResourcePath)</ResourcePath>
<ResourcePath Condition="'$(BRCC_OutputDir)' == ''">$(__ResourcePath)</ResourcePath>
- <ResourcePath Condition="'$(DCC_TranslatedResourcePath)' != ''">$(DCC_TranslatedResourcePath);$(ResourcePath)</ResourcePath>
<NameSpace Condition="'DelphiNamespaceSearchPath'!=''">$(NameSpace);$(DelphiNamespaceSearchPath)</NameSpace>
Now I understand a source for this problem. Please upvote Sir Rufo as he put me in mind of the solution.
It is this: I was invoking DCC32.exe to compile packages (using .dpk, but no .dproj file, and not invoking msbuild to compile these packages). When I built these, I was not inserting the Debug DCU path to the head of the library path passed in via -I parameters to DCC32.exe.
Once the DCC32.exe package compilation Library Search path has the Debug DCU folders FIRST, it works.
If anyone is interested in such a package system, I am planning to open source this package build system, as part of a relaunch of the WANT project originally built by Juancarlo Anez, which I will probably call by a new name. I'll update this answer once a working demo of a component build system is available.
A brief outline of a working system to meet the requirements I asked in my question:
You will need a file (could be xml, ini, json file) that defines a list of packages to build.
You will need to invoke MSBUILD or DCC32.exe on each of these. You could write your own code, or you could use mine, which I will open source when I can.
You will need to include the Debug DCU DPROJ into the library path as the first items, ONLY when invoking the Debug item builds.
You will want to use the $(OURCOMPANYLIBRARYDCU)\$(Platform)\$(Config) macro in your project search paths and library paths.
In your Delphi IDE, you will want to hard-code $(OURCOMPANYLIBRARYDCU)\$(Platform)\Release as a path within the Library path.
In your Delphi IDE, you will want to hard-code $(OURCOMPANYLIBRARYDCU)\$(Platform)\Debug as a path within the Debug DCU path.

How to match map/dbg symbols file to delphi-written process

I have a map file created by delphi compiler and I need to use it to analyze DMP file.
I converted the map file to dbg file, using Map2dbg.
The problem is that the process has a different signeture then the symbols.
I tried to use chkmatch to match the signeture, but I'm getting:
Error: Debug information not found in the executable
I guess this is because it is a delphi process.
Does anyone know how to match the signatures?
I made a minidumpreader some time ago:
https://asmprofiler.googlecode.com/svn/trunk/MiniDumpReader/ViewMinidump.exe (old link)
https://github.com/andremussche/asmprofiler/tree/master/Releases/ViewMinidump.exe (new link)
It is written in Delphi with jclDebug.pas so it supports all delphi debug symbols.
And because of this it has line number support (which map2dbg or tds2pdb don't have).
Note: I haven't made map2dbg or tds2pdb myself, just hosting it so other can easily find it

iTunesMobileDevice.dll Could not be found

I am writing a windows application that interfaces with an iOS device. I am using mobiledevice.h header to interface with iTunes dll
http://samdmarshall.com/media/MobileDevice.h
I made sure i set the system environment path includes the Apple application support. I made sure in the project properties I added the correct .lib in the linker. I made sure in the compiler property I included all the directories in the Additional library field.
It builds, but during run time I get this error:
Unable to load DLL 'iTunesMobileDevice.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
I tried to copy the dll and place it in the same directory as the project and the debug .exe, but still the same issue when running. I've also ran dependency walker, but the only thing it said it couldnt find is IESHIMS.dll.
I can't think of anything else to try. I'm sorry if this is not detailed. If anyone needs anymore detail please let me know and I will add as much as I can.
UPDATE: SOLVED, just had to include the directory in the system paths if anyone else needs the solution
Had to add the directories to the System path which could be found under
start -> right click computer -> properties -> advanced system settings -> environment variables -> system variables -> Path
In path separate the different directories with a ';'.

C++ Builder XE: find out where a specific h file is included

I'm currently porting a rather big project from C++ Builder 5 to the newest version, C++ Builder XE. It's my first experience with C++ Builder. I'm stuck with an error in a file, but I don't want to include this file anyway (it's code of a component not required anymore). I was not able to find out where and how this file is included, however. The compiler error does not give any hint at all apart from the error itself. How do you usually find out where a file is included?
The preprocessor is perfect for this. Right click on the cpp file which gives you the error in the project manager then choose "preprocess"
The output from this tells you every file and line number in the order they are processed. You can then search for the file in question, and the line above it is the file that included it.
This could conceivably be another header file as well, so it could be a long chain, but you can determine exactly where it comes from.
In the Project Options, enable the compiler's general messages. When the compiler encounters an error, you will be able to see the chain of includes that lead to the erroneous code.
If the files in question are rather sizable, a tool like Doxygen can be helpful in showing you the include dependencies (as well as call paths, etc.).
If it's just once or twice you'll have to do this, David Dean's suggestion of the preprocessor is golden.

Why are my units "compiled with a different version" of my own files?

I'm building a program that uses plugins. Unfortunately, the plugin framework's dynamic linking forces the RTL and VCL out of my project EXE and into the BPL versions, and they don't have debug info enabled.
So I built a testing framework that links to my plugins statically so I can actually see what I'm doing while tracing through the code. But now, every time I try to recompile, I get an error: "unit turbu_skills was compiled with a different version of turbu_database.GDatabase"
I've seen this error before, but only when I've been changing things I probably shouldn't have been, like the RTL or VCL libraries. I don't understand why it's doing that with my own code. The turbu_skills and turbu_database units are both units I wrote myself. GDatabase is a global singleton variable, whose class definition I haven't changed in weeks. Any change that triggers a recompile causes this error, even if I haven't touched anything in either of the units.
Doing a full build (SHIFT-F9) causes it to compile correctly. But if I then press SPACE in a unit (any unit) and hit F9, I get the error again. What's going on and how do I stop it? This doesn't happen in the main app, only the testing framework.
EDIT: I have the source to all of my units. Deleting DCUs and similar files doesn't help. Copying the entire project to a different computer, deleting all DCUs, and building there doesn't help. There's an objective, reproducible conflict between the layout of my program and the compiler, and I want to be rid of it.
The source can be found at http://www.turbu-rpg.com/downloads/Turbu_source_setup.exe if anyone wants to test it. It requires Delphi 2009 with the JVCL already installed; the installer package will take care of the rest. Maybe having the source code available will help someone track this down. I certainly hope so, because wherever the issue is, it's beyond me. The problem can be found in testing.exe and also in turbu.exe in turbu.groupproj.
EDIT 2: Turns out this was another cross-unit generics issue. Grr. I managed to code a workaround. I just hope they get the generics problems fixed soon.
The error "unit is compiled with a different version of..." is an annoying one. It occurs in a situation like below:
+--------+
| unit A |
+--------+
| |
| |
V |
+--------+ |
| unit B | |
+--------+ |
| |
| |
V V
+--------+
| unit C |
+--------+
Both unit A and B use unit C and unit B uses C. Unit B and C are compiled and for some reason the source of unit B is not available. Now Unit C is changed (any change will do and is recompiled) And the dcu of unit C differs from the unit C used by unit B, so unit B needs to be recompiled too. But unfortunately, the source is not available so the compiler gives up.
It is not entirely clear what's wrong with your situation.
You have a test framework that links to the plugins. So where do unit X and Y fit in and do you recognize the pattern shown above?
But the fact that a complete build solves the problem is hint in this direction. And this is not the first time I saw problems with partial recompiles. So I always use the complete version.
I hate this problem. I find it pops up every now and then and although it sounds in your case to be directly related to what you are doing with plugins, I've solved this in the past by finding and deleting all the dcus, bpls and dcps of the packages that we've written and then rebuilding the packages.
How I solved the 'path madness' in Delphi XE7:
Rule1: Always separate the DCU from the PAS files
Tools -> Option -> Library path:
Path to global (3rd party) libraries (DCU folder) that never change.
c:\Delphi\Tools\FastMM\
c:\MyProjects\Packages\Third party packages\$(Platform)
c:\MyProjects\Packages\DragDrop\$(Platform)
c:\MyProjects\Packages\Graphics32\$(Platform)
Project -> Options -> Search path:
Path to personal libraries, that changes often.
Enter the path to the DCU folder first, then path to PAS file.
This way, the compiler will use the DCU files first, instead of recomilin every time from PAS files.
It will recompile anyway if you do a Build.
c:\MyProjects\Packages\cCommonControls\$(Platform)_$(Config)
c:\MyProjects\Packages\cCommonControls\
Project -> Options -> Output directory:
Leave it empty so the exe file is generated in project's folder
Project -> Options -> DCU output directory:
Use .\$(Platform)_$(Config) in order to enforce Rule1
This happens to me very often when I forget to change the DPK Build control from Rebuild as needed to Explict rebuild in Options...|Description.
Check that you don't have an strained old dcu file somewhere in source dir.
For future reference, simply pointing the compiler to source-code versions of the "problem units" fixed this for me (i.e. adding the folders containing the source code to the search path).
In my case, I added the locations of the "problem" units to my project's search path. As long as it could find it, it compiled. Of course, if you have several versions of the file in question, it could complicate matters...
Your actual .dpr file contains a reference to an incorrect version of a .pas file.
View > Project Manager > expand tree and examine the path of all the units.
There is a duplicate file in the list of search paths, and the incorrect version is found first
Are you using a modified VCL? The units you reference in your interface section also determine your interface. I would suggest making sure you do not have two different versions of any of your units with the same name (including VCL/RTL) that may be referenced from your project. Maybe it is something a silly as the background compilation is using a different version of the units then the disk compilation. So editing it triggers the background compiler, which then messes up the synchronization.
Definitely something buggy with the compiler. I have found that altering the order of the units in the uses clause will allow you to get "one free compilation" in. After that, the error re-occurs and your back to rebuilding. :-(
For me the problem was that I installed Delphi with minimum required components. And when I opened a project that was compiled with full Delphi installation it happened to me. Coping the files in the "Source" folder in Delphi installation folder from another machine with full Delphi installation solved my problem.
Unit ppParameter was compiled with a different version of ppRelatv. TppRelative :
Delete all .dcu in your program folder / your computer, then re-compile or re-build again.
Then your program will running well again.
my case and solution:
we had a main application that builds an exe file and
some plugin projects that build dll files for this exe
(the dll project also needs some of the applications source files)
sometimes when compiling the dll files the "was compiled with a different version" problem occurred
the problem was this:
the exe project was setup to create all it's dcu files in a separate directory: e.g. App\DCUs
the dll project had this DCUs directory in the search path, but also some of the application's source directories: e.g. App\Utils, App\Core, etc.
thus, when you compiled the dll project, some of the applications source files were compiled again (now possibly with a different version of other dependencies):
and we ended up with 2 different dcu's of the same *.pas file
the solution is easy: remove the App\DCUs directory from the dll project's search path.
I just had the same error message in Delphi XE. Mine was solved after closing Delphi, opening it again and recompiling my project.

Resources