To most Delphi developers a package is typically where you would place components so that you can drop them on your forms.
So one might assume that a 3rd Party Component developer would know how packages work. Well over the years I have seen several of these developers make basic mistakes when it comes to Delphi packages.
The application I work on is built with runtime packages. We currently have to deploy 208 packages.
Management of Packages and having the built correctly is paramount for us. Not all packages involve components, but the most common mistakes happen at that level.
This blog post is my attempt to help developers understand one area of packages, that I typically see mistakes.
A package is just a collection of units that are complied together into a BPL.
Here is the package sources for brand new package with a single unit.
package Package2;
{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$IMPLICITBUILD ON}
requires
rtl;
contains
Unit13 in 'Unit13.pas';
end.
There are two key sections
requires and
contains.
Contains is the list of units that your package contains. Requires is the list of other packages your package needs to compile. For example say you have a
pkgBaseBall.bpl that contains a unit called
baseball.pas.
Then you create a new packages called
pkgSports.bpl that contains a unit called
sports.pas which listed
baseball.pas in it's uses clause. You will need to add
pkgBaseBall to the requires clause the package named
pkgSports.bpl
Key Files involved in package development.
- *.DPROJ - XML File in MSBUILD format that contains project options and files.
- *.DPK - Main source code of the package. (It's the code listed above)
- *.BPL - Compiled Binary
- *.DCP - Delphi Compiled Package, contains information about he interface section of the contained units.
Package Types
There are 3 basic types of Packages.
- Designtime only
- Runtime only
- Designtime and runtime
Runtime Packages
When creating a Delphi you have the option to build with runtime packages. This option is found in the project options.
If you build with packages you must distribute the packages (.BPL files) your application uses.
Most Delphi application that I have seen are build without runtime packages. Typically these developers tend to not realize the impact bad package design can cause on application that uses runtime packages.
When building with runtime packages the list of package you must distribute is semi-colon delimited list next to the check box for Build with run time packages in the project options. The only files you need to distribute for applications build with runtime packages is the BPLs. The other key package files do not need to be distributed.
Runtime packages should never contain or require designtime code.
Designtime Packages
Designtime packages are where you place your design time code. This includes
- Property Editors
- Component Editors
- Open Tool Experts
- References to other packages that are design time.
- Component Registration "i.e. the Register method."
Designtime packages should never contain runtime code.
Designtime and Runtime
This is the lazy developer package. I don't want to create and maintain two packages, so I will just use one. This seems easy at first, but if not done carefully it leads to the most common mistake I run into. Then write some code that requires a designtime only package. This in effect makes your package designtime only regardless of your package type selection. It's easy to do any property or component editor will require DesignIDE which is design time package that you can't distribute.
The Rules
The summary version of common mistakes.
- "Runtime" Packages should never contain Design time Code
- "Designtime" Packages should never contain Runtime Code.
- "Designtime and Runtime" Packages should never Require "Designtime" Packages.
- "Runtime" Packages should never Require "Designtime" Packages.
- Avoid "Runtime" Packages that require "Designtime and Runtime" Packages
- Avoid the use of "Designtime and Runtime" Packages.
Why do I care?
If an application builds with runtime packages, and someone screws this up you will find that application requiring deployment of design time packages to work. If you do deploy the runtime package, you may run into a a runtime error "Application is not licensed to use this feature" This is because your using files that you should not be distributing.