When we write and compile a Delphi application, we typically generate an executable file - a standalone Windows application. Unlike Visual Basic, for example, Delphi produces applications wrapped in compact exe files, with no need for bulky runtime libraries (DLL's).
Try this: start Delphi and compile that default project with one blank form, this will produce an executable file of about 385 KB (Delphi 2006). Now go to Project - Options - Packages and check the 'Build with runtime packages' check box. Compile and run. Voila, the exe size is now around 18 KB.
By default the 'Build with runtime packages' is unchecked and every time we make a Delphi application, the compiler links all the code your application requires to run directly into your application's executable file. Your application is a standalone program and doesn't require any supporting files (like DLLs) - that's why Delphi exe's are so big.
One way of creating smaller Delphi programs is to take advantage of 'Borland package libraries' or BPL's in short.
What's a Package?
Simply put, a package is a special dynamic-link library used by Delphi applications, the Delphi IDE, or both. Packages are available in Delphi 3(!) and higher.Packages enable us to place portions of our application into separate modules that can be shared across multiple applications. Packages, also, provide a means of installing (custom) components into Delphi's VCL pallete.
Therefore, basically two types of packages can be made by Delphi:
- Run-time packages - provide functionality when a user runs an application - they operate much like standard DLLs.
- Design-time packages - used to install components in the Delphi IDE and to create special property editors for custom components.
From this point this article will deal with run-time packages and how they can help Delphi programmer.
One wrong mit: you are not required to be a Delphi component developer to take advantage of packages. Beginner Delphi programmers should try working with packages - they'll get better understanding of how packages and Delphi work.
When and when Not ot Use Packages
Some say that DLL's are one of the most useful and powerful features ever added to the Windows operating system. Many appplications being run at the same time causes memory problems in operating systems such as Windows. A lot of these programs perform similar tasks, but each contains code to do the job itself. That’s when DLLs become powerful, they allow you to take all that code off the executables and put it in a shared environment called a DLL. Probably the best example of DLLs in action is the MS Windows operating system itself with it's API - nothing more that a bunch of DLLs.DLLs are most commonly used as collections of procedures and functions that other programs can call. Besides writing DLLs with custom routines, we can place a complete Delphi form in a DLL (for example an AboutBox form). Another common technique is to store nothing but resources in DLLs. More information on how Delphi operates with DLLs find in this article: DLLs and Delphi.
Before going on to comparison between DLLs and BPLs we have to understand two ways of linking code in an executable: static and dynamic linking.
Static linking means that when a Delphi project is compiled, all the code that your application requires is directly linked into your application's executable file. The resulting exe file contains all the code from all the units that are involved in a project. Too much code, you might say. By default, uses clause for a new form unit list more than 5 units (Windows, Messages, SysUtils, ...). However, the Delphi linker is smart enough to link only the minimum of code in the units actually used by a project. With static linking our application is a standalone program and doesn't require any supporting packages or DLLs (forget BDE and ActiveX components for now). In Delphi, static linking is the default.
Dynamic linking is like working with standard DLLs. That is, dynamic linking provides functionality to multiple applications without binding the code directly to each application - any required packages are loaded at runtime. The greatest thing about dynamic linking is that loading of packages by your application is automatic. You don't have to write code to load the packages neither you have to change your code.
Simply check the 'Build with runtime packages' check box found on the Project | Options dialog box. The next time you build your application, your project's code will be linked dynamically to runtime packages rather than having units linked statically into your executable file.
At this point you are probably curious why you would choose a run-time package versus a DLL, or the other way around.
Packages differ from DLLs in that they are specific to Delphi, that is, applications written in other languages can't use packages created by Delphi. Even though a package is a special dynamic-link library used by Delphi applications, it provides more functionality to a Delphi developer.
In general we built DLLs in Delphi to store collections of custom procedures and functions that can be used by many applications and/or different environments. Packages can contain units with code, components and forms, but also Delphi classes - this enables us to write object oriented code. What Packages can and DLL's cannot is to store your complete custom Delphi components inside them.
Both DLLs and BPLs play a great role in code reduction. A primary reason behind using packages or DLL's is to reduce the size of your applications. This should lead to caution, of course. The packages and DLLs that you need to ship with your application can be quite large. Note that the you still have to distribute your packages; the primary VCL package, vcl50.BPL, is almost 2MB in size alone.
However, if you distribute several Delphi applications that share the same package, you might end up distributting less code. Consider the benefit of giving users the option of downloading smaller versions of the application when pieces of the application might already exist on their system (like standard Delphi BPLs). This should certainly urge you to start deploying your project's over the Internet.
Packages save memory. As a result of dynamic linking, only one copy of the VCL resides in memory for all Delphi applications that use run-time packages.
Package Versioning Problem
When you want to update your DLL (change some function's implementation), you simply compile it, export some new routines and ship the new version. All the applications using this DLL will still work (unless, of course, you've removed existing exported routines).On the other hand, when updating a package, you cannot ship a new version of that package without also updating the executable. As you will see, a package is nothing more than a collection of units. All the DCU files (compiled units) contain version information. This is why we cannot use a unit compiled in Delphi 7 in a Delphi 2006 project unless we have the unit's source. When we change something in the interface part of the unit all the units listed in the uses clause need to be recompiled. The compiler checks the version information of DCU's and decides whether an unit has to be recompiled. You cannot provide a package written in Delphi 2006 to be used by an application written in Delphi 7. Any package that you provide for your application must be compiled using the same Delphi version used to compile the application.
Therefore, when giving names to packages be sure to include the version of Delphi in the package name (like 'AboutDP_70' vhere 70 stands for Delphi 7). This will prevent any confusion with your package users as to which version of the package they have and to which version of the Delphi compiler they apply.
If you distribute run-time or design-time packages to other Delphi developers, be sure to supply both .DCP and .BPL files as well as all the .DCU files of the units contained in your packages.
Creating a Package
Creating a package is easy, but before creating a new package, you'll need to decide on a few things. Firstly, you need to know what type of package you're going to create: runtime or design or both. Second, create, debug, test and test again all the units you want to place in a package. Finally, you need to decide what will be the name of your newly created package and where you want to store the package project.To create a new run-time package, folow these steps:
- Start Delphi - this will result (by default) in an empty form and a new project (prior Delphi 2006). Select File | Close All to start from "nothing".
- Select File | New... This will call the "New items" dialog box. On the "new" page double-click the Package icon. This will call the Package Editor. As you can see the Package Editor contains two folders: Contains and Requires.
- Click the Add button, to add a unit (with custom component or a simple code unit). Notice that you add the PAS file, that is the unit's source not the compiled version of it (DCU). Add as many units as you want to the package. While you are adding units, their names are showing in the Contains folder. For this purpose try adding FindFile and PictureClip units.
- Open the Requires folder. This list indicates the packages required by your package. At the minimum, your package need to refer to vcl.dcp which contains most of the standard VCL components.
- When you are done adding units, click the Options button. In the Usage options group you select whether this package is design-time, run-time or both. Select Runtime only. This will create a run-time package. Other developers (users of this package) will not be able to install those two component on the IDE.
- Use File | Save As to save Packages project file (DPK). Save the package as AboutDP70. The package naming is very important as you'll see later.
- In the Package editor, click the Compile package speed button to compile your package.
- If everything goes well your package is compiled and a package library (BPL file) is created. If you get a message indicating that you have to add some other packages (like VCLDB70), simply do so. Those packages will be listed under the Requires folder.
- That's it. The Borland package library is created and waiting to be used.
Besides the DPK file with the source file, Delphi generates a BPL file with the dynamic lik version of the package and a DCP file with the symbol information. The DCP is nothing more that the sum of the symbol information of the DCU files of the units contained in the package. Check out "Filename Extensions in Delphi" for more on file types created by Delphi.
Programming with run-time packages
As stated earlier to use dynamic linking in your applications you don't have to write code to load the run-time packages neither you have to change/rewrite your code. Only one visit to Project | Options will do the trick. Packages listed in the Runtime Packages edit box are automatically linked to your application when you compile. To use a custom runtime package with an application, choose Project | Options and add the name of the package to the Runtime Packages edit box on the Packages page. Of course, be sure to check a 'Build with runtime packages' check box.Note: although an application is linked to run-time packages, the program's units must list all the units they require in the uses clause. Compiling with run-time packages only tells the application where to find it's component code.
Packages, of course, enable us to store Delphi forms - like About Boxes - inside them. See "Dynamic World of Packages" on how to store a Delphi form inside a BPL. Find out about dynamically embedding forms into an application from runtime packages.
When deploying an application that uses run-time packages, make sure that your users have the executable file as well as all the library (.BPL or .DLL) files that the application needs. If the library files are in a different directory from the .EXE file, they must be accessible through the user’s Path (autoexec.bat). The best place would be in the Windows\System directory.
If you've come this far...Packages give you flexibility in deciding how to deliver your applications and also make installing custom components easier. Additionally, packages reduce the size of applications using them.