Does the .res file need to be in source control? - c++builder

In C++Builder XE5.
My understanding is that the binary file MyProject.res (which is created by the compiler in the same directory as the .cbproj file) contains compiled versions of the program icon and the project version details (although mine also seems to contain an XML manifest).
But this info is also contained in the .cbproj file and the .ico files; and if I delete the .res file then it seems to get recreated exactly was it was next time I open the project.
So is it safe to mark *.res as not being in source control? (I use git). And/Or is it possible to have it generated in the same directory as the object files instead, so it's not mixed in with the source?
(This certainly wasn't safe in C++Builder 5 - if you deleted the .res file then it complained it couldn't find it, and you lost your icons).
Update: Does this also apply to the .tlb file? This seems to be compiled based on the .ridl file, and if I delete it then it is automatically regenerated.

C++ Builder 6.0 and later will recreate RES files if deleted. I treat them as other temporary/build files (like OBJ files) and do not put them in version control software. I do have nightly backups that include all of these files though, which I think is still good practice.
I am not sure about TLB files. I would temporarily delete (aka-rename) one and see if it gets recreated to the same state. If so, should be same as RES files.
This does not hold true for 3rd party libraries though, if all you have is compiled resources. In that case, I still do not place in my version control though, since I am not going to be modifying them. I just have my backups.

For what it's worth, the TFS source control defaults are to exclude *.res but include *.tlb.
So you should expect *.res files to be created by their associated builds. If the build isn't going to be present, then the *.res file should be included.
I suspect that you're right about *.tlb files being built as well, but perhaps TFS doesn't exclude these on default because the extension isn't entirely unique to OLE type library files alone.

Related

Delphi 7 to Delphi XE2 .res file issue

When I open a Delphi 7 Project in Delphi XE2 and open the Project Option I get an error:
"Unable to set Icon: Cannot open file "........\AppName_Icon.ico".
The system cannot find the file specified".
I also notice that the Version info of the Project is missing.
The Delphi 7 project has .Res file that has the MAINICON along with the version information stored.
Why is Delphi XE2 not able to use this .Res file to retrive the MAINICON & Version information.
Also if I try to compile the application in XE2 I get an error -
[BRCC32 Error] MtxReq.vrc(2): file not found: MtxReq_Icon.ico
The MTXReq.vrc file (a new file) is created and the MtxReq.res file is deleted.
Why is this happening? I don't want to loose my project icon and version settings from .res file.
Is there a way to force XE2 to use the .res file and not delete it?
Any help will be greatly appreciated.
Sorry I can't post a comment yet (need more repotation points) ...
Warren - here the reponse to your question (Wouldn't just deleting your .dproj file and keeping the .dpr only, have been faster?)
I deleted the .dproj, .dproj.local
Opened the .dpr in XE2 and it recreated the .dproj file.
It brough back the icon from the .res but I lost project version info. Only File Version and Product Version info got migrated but lost all other versioning info. (This is because of the default manifest file).
I then tried what I explained in Step 1 of my solution.
I open the .dproj file in notepad deleted the tag entries under and reopened the .dproj file and all my version info now was recovered. The problem here is the $(BDS)\bin\default_app.manifest.
Also I noticed that Version info is stored in tag under the tag in the .dproj file and once you delete the default manifest entries, the IDE pickups the version key information correctly from the .
So basically by deleting the .dpr file I skipped the step of extracting and adding the .ico file to the project, but had to edit the newly created .proj file and delete the entries for default manifest to retrieve the version info. (another solution would have been to manully add the version info and saving the project. I did not try this)
Update 2015: Remy's idea of recreating .DPROJ files carefully by hand, is excellent advice and should be considered first, even though my answer is marked accepted.
Delphi versions prior to XE2 used resource files as an INPUT and an OUTPUT in the compilation process. For example, your delphi 7 project icon is embedded in that .res file, which you "want delphi xe2 to use", however, that's problematic in delphi 7, and now flat out impossible in XE2. Instead you now treat the .res file as a pure output artifact, the same as executable files. Don't bother checking .res files into version control any more, and don't try to pretend that the .res file is the place where you permanently store your icons. It's an output file produced automatically by the compiler, as it always should have been.
If you are a modern developer, the old way Delphi 7 worked might have annoyed you (it sure annoyed me) because you have the interesting and unsolveable question about what to do for version control: Do you check in the .RES file, or don't you? There were drawbacks to both approaches, and the fact that .RES files are now output artifacts only in XE2 is for the best. So learn to live with that.
Now that XE2 supports icons not only for a PC but also for a Mac, it must handle things differently, and they have cleaned this up. This is the origin of the problem you're seeing with the .ICO file. I have seen exactly the same error, and I have ignored it, and simply added the icon back to the project after it has otherwise been converted.
Converting a delphi 7 project (.dpr and .cfg) to Delphi XE2 is not as big a problem as the conversions between various levels of .dproj files -- each version starting with Delphi 2005,2007,2009,2010, and onwards has implemented changes in the dproj format. When problems occur with converting these projects, I do not do as Remy suggests, because it's a waste of time. What I do is DELETE the DPROJ and let it convert up from a .dpr file only.
But Remy's advice to start from scratch has many advantages, including that you may simplify your project layout.
Anyways, here's what you do:
Ignore error.
Add icon to project yourself.
Continue merrily along, and don't worry about the deletion of the .res file, that's intentional, and for good reasons. A new one will be created whenever needed. The filename of the .ico file on disk will be read by using the contents of the XE2 .dproj file and compiled into the .res file, as it should be.
As is always the case, you should NEVER let the IDE convert a project from an older version to the newer version. The conversion RARELY works correctly. You should ALWAYS create a new project in the newer IDE and then add your existing source files to it as needed.
Thanks everyone for your inputs and suggestions.
After I submitted my posting, I tried these steps to resolve the .ico issue and the missing Version issue/version info carry over issues :
Step 1. Edited the .dProj file and removed the reference to default_app.manifest related entries under tag (My project platform is 32 bit)
I deleted all tags under this except tag related to namespace System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
Without this my application was always showing the version info as 1.0.0.0 and ignoring everything else that I had specified.
(I am not sure if this is a right step but it solved my version info issue. There may be a simpler/another solution for this...)
Step 2. Extracted the ico from the old .res file, named it and added that .ico file to the Project from the Project Options.
the physical .ico file is the the projects folder and will be checked in source control (VSS in my case).
These two steps bought me to what I needed and then I can modify the Version number and compile the project.
From this point on there are no issues.
These were much simpler than the total conversion/migration I had to do for my applications from D7 to XE2 - Unicode conversion, migrating customized Raize 5 componets to Raize 6, Turbo Power, Virtual Tree View, Hypergrid etc. etc. etc... Luckily I found XE2 versions of all these components.

How to recreate "default" .res file from command line?

When the "default" .res file of your project is missing Delphi will offer to recreate it when you open the project in the IDE. Can this functionality be invoked from command line?
Background:
A project is under version control, its .res file is not checked in (some musings about why can be found here). The project is checked out automatically and build from command line. The problem now is the missing .res file which causes the build to fail. Can I somehow invoke the auto-creation feature the IDE uses from command line? Otherwise it seems like I am forced to check in the .res file.
No, there is no command-line tool in Delphi to re-create the default resource file.
That's just as well since you don't need the default resource file. It would contain a generic version number and a generic icon, which you obviously don't want in any project important enough for automated builds.
Binary resource files don't do well in source control, which is what prompted the other question. Write .rc files instead, and compile them as part of your build. Delphi won't auto-increment build numbers anymore, but it's easy enough to reproduce that in your build script as well by updating your .rc file (or generating an included file) prior to compilation.
If you really want a binary resource file, then you could store one in source control, but under a different name or location than what the compiler expects to find. After checkout but before the build, copy it into the proper location. Changes to the copy won't be recorded in source control.

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 ;)

How to remove duplicate resources (RES, DFM) while using Delphi with non specific Library paths?

I followed the advice received in a previous discussion ( Should "Library path" point to the source files of packages? ) and now my Library Path points to folders containing the compiled code (DCU) and NOT to the source code of my controls.
The problem is that I have to duplicate the RES and DFM files and copy them from the 'source code' folder to the 'compiled' folder. It is not a elegant solution at all since, every time I change something (and I do often) to my controls I have to remember to copy the new resource files to the compiled folder.
There must be an elegant way to solve the mystery of the paths! All I want is to push the compile button and to have my program compiled. It doesn't seem so complicated. Right? Well, actually it work with my previous setup (point Delphi to source code of all controls). I just changed it to do it the way the 'good people' are doing it.
Addendum
I still think this is the wrong approach since Delphi's (scarce) documentation says that Library path should point to the "source files for the package".
Using:
Delphi 7, Win 7 (32), simple Delphi setup (single developer with no versioning system installed).
You have two solution:
Use a build tool to build and copy all files where they should be properly deployed (my preferred solution) after each build
Put the .pas/.dfm/.res directory after the .dcu ones. It will find the .dcu first and won't recompile unless you build, and it will keep on looking for .res/.dfm, etc.
If you look inside a D2007 project file (*.dproj) you'll see that the search path occurs multiple time for each configuration. There is
<DCC_UnitSearchPath>,
<DCC_ResourcePath>,
<DCC_ObjPath> and
<DCC_IncludePath>.
Maybe you can point <DCC_ResourcePath> to the source directory containing the resource files while you point the other variables to the DCU directory.
NB: I haven't tried this and can't check if the situation is different in other Delphi versions.
Though answers provided here by others are definitively good and correct (everybody receives a vote up), after experimenting a bit I decided to keep my previous (KISS) set up. It worked for years and it will work for many more. I know, it trades speed (recompiling the source code) for stability but it keeps the "paths, libraries, source, browsing and output folders" madness at bay. I just don't have to worry about settings paths anymore (except first time when I install Delphi but this can be automated) or to quit current DPR Delphi project and load a DPK library and compile it every time I add changes to it.

How to correctly set "Directories/Conditionals" and "Library" path

How to set "Directories/Conditionals" in Project Options and "Library" path in Environment Options? Delphi help don't say much about these very important settings. I have all kind of strange errors because of wrong dependencies between my VCLs.
1.
I have merged a large set of 3rd party controls in a package called ThirdPartyPackages_D7.dpk. This is useful when I reinstall Delphi because I don't have to reinstall all those 3rd party VCLs amnually.
Then, I have my own controls in MyControls_D7.dpk which depends on the ThirdPartyPackages VCL. I also have another package BlgPackage.dpk that depends on MyControls.
At the end of the chain is my application (DPR project) which is using the controls in BlgPackage.
ThirdPartyPackages.dpk -> MyControls.dpk -> BlgPackage.dpk -> MyApplication.dpr
When I change/edit something to the second package (MyControls.dpk) and build the DPR application, it works. The compiler sees the changes made into that package.
However, if I close the project and load and compile the BlgPackage, it throws a nasty message that function xyz cannot be found in MyControls because I delete it (I have loaded MyControls' units into IDE in parallel with application's units). It seems that building the application only refreshes the DCU files for all used packages but not the DCP/BLP files.
How do I write and compile the code in the packages without explicitly loading the packages into the IDE and building them?
(Note: I have a nasty bug that does not allow me to switch between projects without restarting the IDE or to load a group of projects/packages (*.bpg) at the same time.)
2.
Another problem is that I want to store the compiled files (DCP/BPL/DCU) of a package in its folder (for example c:\MyProjects\Blg).
If I set the "Output directory", "Unit output directory" and "DCP output directory" boxes of BlgPackage package to its folder, not only its BPL/DCU/DCP files will be stored there but also the BPL/DCP files of MyControls will be stored there.
How can I have the binary files of each package in a separate folder?
Delphi 7, Win XP, all projects set to "Rebuild as needed"
You should explicitely compile packages - just compiling package files is not enough and as you have noticed leads to problems.
In modern Delphi versions you can create a project group (not sure about Delphi 7) that contains an application and packages you want to develop with the application, and you can easily switch between them and complile packages without need to close/reopen the application.
BlgPackage should not have an access to MyControls package sources (through "Library" path or by using the same directory), it should access only already compiled MyControls package, else the files from MyControls are compiled every time you build BlgPackage and the compiled files are stored in BlgControls DCU directory
ADDED
The "Library" path should lead to compiled files (.dcp, .dcu) and (if needed) resource files (.res, .dfm) only - it is enough to compile applications and packages that requires "MyControls" package. You can set the directory for compiled files directly in the package settings, and you should copy the resource files (if you need them) to the same directory manually. This directory should be included into "Library" path, or else you can use a directory already contained in "Library" path.
The "Library" path should not lead to source files (.pas) if you don't want these files to be compiled every time you build your BlgPackage or an application that requires "MyControls" package.
I use much simpler way for 3rd partie components and reinstalling Delphi.
Open regedit and find
[HKEY_LOCAL_MACHINE/SOFTWARE/Borland/Delphi/xxx] where xxx is version and export whole
branch.
Open file and delete keys LMKEY, LMLIC.
Copy C:\Program Files\Borland\Delphi x\Projects\Bpl folder to another location
Copy C:\Program Files\Borland\Delphi x\Imports to another location
Reinstall Delphi including any updates and GExpert
Import previously saved registries
Restore Bpl And Imports Folder
And whoala, Delphi is back with all 3rd partie components and IDE settings. Only limitation is that all components must reside in same folder before and after reinstalling Delphi.
This also restores TeamSource settings. If you are reinstalling Windows as well, be sure to make windows user with same user name as before.
MY solution (kinda dirty, but hey it works):
I put ALL 3rd party libraries.controls in a single package (a super-package). I put all my controls in a single package.
Now, when I migrate the packages to a different PC all I have to do is to copy/paste two folders and set two paths.
Works for me - others may not agree with it and I can't blame them. I blame the 'hell designers' from Borland/Embarcadero. If you look on StackOverflow you will see that until now nobody provided an elegant solution to this.

Resources