How to automatically copy resources to the DCU output folder - delphi

I would like to know, is there a way to automatically make the IDE/Compiler/other copy all the resource that needs to be linked with the DCU to the DCU output folder.
I often use forms that I pre-compile to avoid the needs to recompile the unit all the time in my main projects. The DCU gets updated, but we need to copy the DFM manually everytime it changes. Same goes for any {$R *.res} specified. Maybe we could maintain those file directly in the DCU folder... but doesn't quite make sense to have a .DFM in a different folder than a .PAS
I looked for a compiler switch that would do it... Unsuccesfully.
Anyone knows if/how it can be achieved?
I'm using Delphi 2010

You could create a simple Post Build event which performed the copying. That way whenever you did a build, the system would copy the necessary files for you. The build events are available from the Project Options menu, there is a Pre-build and a Post-Build script.

For *.res files you can specify output path in "Project Options | Resource Compiler | Directories and Conditionals | Output directory for .res files"
But for *.DFM files you have to use skamradt's suggestion (Post Build event).

Related

Can one build an EXE project against a BPL/DCP with "Build With Runtime Packages" unchecked, based solely on the BPLs/DCPs?

I have a BPL project (with some base stuff) and an EXE project which has in it's Search Path the location of the other project's output (BPL and DCP). When the EXE project is built with "Build With Runtime Packages", it builds fine. However, it requires me to deploy the EXE and the BPL. So far so good.
Since I'd rather deploy just the EXE (no matter it gets bigger), I'd guess that I'd just uncheck "Build With Runtime Packages" and that'd be it, but it's not the case. It won't build, and start complaining about the missing classes. The only way I can compile the EXE project is if I add the path to the actual BPL project's DCUs to the EXE project's Search Path. I can do that, but why am I forced to point to the DCUs? Can't Delphi just take them from the BPL? It's not just a matter of taste, if I go this way, and link to the DCU's, when it comes to DCUs belonging to forms, it will then ask me for the forms DFMs, forcing me to also include my sources folder to the EXE project's Search Path, and now it would seem as they are getting compiled, which is prohibitive. I can't recompile my BPL project codebase each time I want to compile my EXE project.
I hope I have made myself clear.
Any help on how to achieve what is asked in the title is appreciated.
Thank you.
There are two ways to link external libraries: static and dynamic.
When you are using runtime packages, this is a dynamic linking. Actual implementation is in the BPL file (which is a simple dll actually), methods and classes are imported from it on the process start. This reduces exe size, but requires BPL file to be shipped (same as usual dll). DCU files are not needed, because everything is already compiled and linked, linker need only to create import section.
When runtime packages are disabled, linker has to take object files for all classes and methods and combine it into the one executable. It could not extract this data from the BPL, because its is already linked executable. It would have to unlink it first, separating different modules implementation, which is basically impossible. So you have to provide DCU files, containing compiled object code to link your program.
So answer for your question title is simple - no it is not possible.
No, you can't. If you want to use runtime packages you have to turn on the compiler option to build with runtime packages.
As to the second part of your question:
Building with runtime packages uses the *.dcp files to compile (the .dfm streams are linked into packages' resources so the *.dfm files are not needed directly).
Building without runtime packages needs the *.dcu and *.dfm files (and any other required files).
In either case, you need to have the required files in your library/search path to be able to compile/build.
It is possible, but is very hard to implement.
And you will need to create a third project for this purpose - a loader.
You need to turn your original EXE project to a DLL built with runtime pckages.
The loader can include your DLL project, rtl.bpl, vlc.bpl and your BPL project as resources inside loader executable.
Loader will need to manually do all things that are done by LoadLibrary Windows API.
You can read more about how to load DLLs from memory and find some code samples to start with here.

Where can I configure DCC_ExeOutput?

Is it possible to configure DCC_ExeOutput from Delphi? I could only change this by editing the dproj file.
I couldn't find where to edit this option even using Delphi IDE Insight.
Update 1:
This is my Project Options:
#TOndrej have suggested me change output directory, but I have already done this, and DCC_ExecOutput didn't change. The only way was editing dproj file.
Update 2:
My purpose is organize the folder structure of Delphi projects like suggested by Zarco Gajic in his article How to Layout Delphi Project Files - Best Practice.
Delphi creates folders for each platform to store .dcu, .exe and other files. .\$(Platform)\$(Config) is the default for Delphi. So in the same level of .dproj Delphi creates the folders Win32, Win64, Android, etc.
As you can see in the picture above, I've configured Delphi to put those files in a better organized form, in my opinion. Below an example:
My_Delphi_Project_folder
Bin
|___Debug
| |____Win32
| |____Win64
| |____Android
|___Release
|____Win32
|____Win64
|____Android
But after compile, the resulted structure was like below:
My_Delphi_Project_folder
Win32
Win64
Android
Bin
|___Debug
| |____Win32
| |____Win64
| |____Android
|___Release
|____Win32
|____Win64
|____Android
After investigating .dproj file I found the guilty. It was DCC_ExeOutput.
As I didn't find a way to configures it in Delphi, I asked for help here.
It has a long time that I don't work with Delphi, and I thought that could be a very simple thing that I have passed up. That's the cause of lack of information in my question.
See "Output Directory" in Project Options.
The important information here is the type of project. Your project is a package. As such the DCC_ExeOutput setting is not relevant. It has no impact on the build process. What matters for a package is the DCC_BplOutput setting. The IDE still appears to emit to the .dproj file a value for the DCC_ExeOutput setting, but this value is ignored, and can be removed from the .dproj file.
Package projects
Main source file begins with package.
The output location for the package is determined by the DCC_BplOutput node in the .dproj file.
In the IDE this setting corresponds to the Package output directory option in the project options dialog.
The IDE's new package dialog produces a .dproj file that contains a DCC_ExeOutput node. This node is ignored and can safely be removed from the .dproj file. There is no option in the IDE that corresponds to the DCC_ExeOutput node in a package .dproj file.
Executable and library projects
Main source file begins with program or library.
The output location for the project is determined by the DCC_ExeOutput node in the .dproj file.
In the IDE this setting corresponds to the Output directory option in the project options dialog.

Does the .res file need to be in source control?

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.

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.

Where to keep Delphi DCU files?

Currently I have not set any specific output directory for Delphi DCUs in my main project. This results in the DCU files ending up in the same directory as my .pas source files. To me, this feels ugly as I don't like the idea of mixing .pas and .dcu files in the same directory. What is the best practice for storing Delphi .dcu files - keep them all one directory for each project? Or maybe create one DCU directory for each source folder? Any ideas welcome.
The best way to do it is to create a DCU folder for each project, especially if you have more than one project that uses the same files. Otherwise, you can end up with different compiles with different compiler settings stomping each other's DCUs.
.dcu's are also dependant on defines, and e.g. debugging vs release configuration (*).
(*) While Delphi XE allows to put the "configuration" in the output path, IMHO that cure is worse than the problem
So I regularly recursively delete all .dcu's from the root of the dir where I do all my SVN checkouts.
The directory with components has a delphi version suffixed, and is outside the SVN checkout directory.
Agreed...mixing PAS and DCU files in the same directory is 'dirty'.
Whenever you start a new application, dll, or other Delphi project, one of the first things to do is to set the output directory. In later versions of Delphi this is done for you as the output directory is set as .\$(Config)\$(Platform) which correlates to the Debug or Release config option and Win32 platform. (Ending up with a default output directory of Debug\Win32)
If you build with custom compiler defines then it would be wise to have different project build options to include separate output directories for each set of custom compiler defines otherwise you have to do a full build to ensure that units are built correctly.

Resources