A package is a special dynamic-link library used by Delphi applications, the IDE, or both. Runtime packages provide functionality when a user runs an application. Design-time packages are used to install components in the IDE and to create special property editors for custom components. A single package can function at both design time and runtime, and design-time packages frequently work by calling runtime packages. To distinguish them from other DLLs, package libraries are stored in files that end with the .BPL (Borland package library) extension.
Like other runtime libraries, packages contain code that can be shared among applications. For example, the most frequently used Delphi components reside in a package called VCL50. Each time you create an application, you can specify that it uses VCL50. When you compile an application created this way, the application's executable image contains only the code and data unique to it; the common code is in VCL50.BPL. A computer with several package-enabled applications installed on it needs only a single copy of VCL50.BPL, which is shared by all the applications and the IDE itself.
Delphi ships with several precompiled runtime packages, including VCL50, that encapsulate VCL components. Delphi also uses design-time packages to manipulate components in the IDE.
You can build applications with or without packages. However, if you want to add custom components to the IDE, you must install them as design-time packages.
You can create your own runtime packages to share among applications. If you write Delphi components, you can compile your components into design-time packages before installing them.
Design-time packages simplify the tasks of distributing and installing custom components. Runtime packages, which are optional, offer several advantages over conventional programming. By compiling reused code into a runtime library, you can share it among applications. For example, all of your applications--including Delphi itself--can access standard components through packages. Since the applications don't have separate copies of the component library bound into their executables, the executables are much smaller--saving both system resources and hard disk storage. Moreover, packages allow faster compilation because only code unique to the application is compiled with each build.
Create a package when you want to make a custom component that's available through the IDE. Create a standard DLL when you want to build a library that can be called from any Windows application, regardless of the development tool used to build the application.
The following table lists the file types associated with packages.
Note: Packages share their global data with other modules in an application.
For more information about DLLs and packages, see the Object Pascal Language Guide.
Runtime packages are deployed with Delphi applications. They provide functionality when a user runs the application.
To run an application that uses packages, a computer must have both the application's .EXE file and all the packages (.BPL files) that the application uses. The .BPL files must be on the system path for an application to use them. When you deploy an application, you must make sure that users have correct versions of any required .BPLs.
To use packages in an application,
If you edit the Search Path edit box in the Add Runtime Package dialog, you will be changing Delphi's global Library Path.
You do not need to include file extensions with package names. If you type directly into the Runtime Packages edit box, be sure to separate multiple names with semicolons. For example:
VCL50;VCLDB50;VCLDBX50
Packages listed in the Runtime Packages edit box are automatically linked to your application when you compile. Duplicate package names are ignored, and if the edit box is empty the application is compiled without packages.
Runtime packages are selected for the current project only. To make the current choices into automatic defaults for new projects, select the "Defaults" check box at the bottom of the dialog.
Note: When you create an application with packages, you still need to include the names of the original Delphi units in the uses clause of your source files. For example, the source file for your main form might begin like this:
unit MainForm; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
Each of the units referenced in this example is contained in the VCL50 package. Nonetheless, you must keep these references in the uses clause, even if you use VCL50 in your application, or you will get compiler errors. In generated source files, Delphi adds these units to the uses clause automatically.
To load a package at runtime, call the LoadPackage function. For example, the following code could be executed when a file is chosen in a file-selection dialog.
with OpenDialog1 do if Execute then with PackageList.Items do AddObject(FileName, Pointer(LoadPackage(Filename)));
To unload a package dynamically, call UnloadPackage. Be careful to destroy any instances of classes defined in the package and to unregister classes that were registered by it.
Delphi ships with several precompiled runtime packages, including VCL50, which supply basic language and component support.
The VCL50 package contains the most commonly used components, system functions, and Windows interface elements. It does not include database or Windows 3.1 components, which are available in separate packages. The following table lists some runtime packages shipped with Delphi and the units they contain.
To create a client/server database application that uses packages, you need at least two runtime packages: VCL50 and VCLDB50. If you want to use Outline components in your application, you also need VCLX50. To use these packages, choose Project|Options, select the Packages tab, and enter the following list in the Runtime Packages edit box.
VCL50;VCLDB50;VCLX50
Actually, you don't have to include VCL50, because VCL50 is referenced in the Requires clause of VCLDB50. (See "The Requires clause".) Your application will compile just the same whether or not VCL50 is included in the Runtime Packages edit box.
A custom package is either a BPL you code and compile yourself, or a precompiled package from a third-party vendor. 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. For example, suppose you have a statistical package called STATS.BPL. To use it in an application, the line you enter in the Runtime Packages edit box might look like this:
VCL50;VCLDB50;STATS
If you create your own packages, you can add them to the list as needed.
Design-time packages are used to install components on the IDE's Component palette and to create special property editors for custom components.
Delphi ships with the following design-time component packages preinstalled in the IDE.
These design-time packages work by calling runtime packages, which they reference in their Requires clauses. (See "The Requires clause".) For example, DCLSTD50 references VCL50. DCLSTD50 itself contains additional functionality that makes most of the standard components available on the Component palette.
In addition to preinstalled packages, you can install your own component packages, or component packages from third-party developers, in the IDE. The DCLUSR50 design-time package is provided as a default container for new components.
In Delphi all components are installed in the IDE as packages. If you've written your own components, create and compile a package that contains them. (See "Creating and editing packages".) Your component source code must follow the model described in "Creating custom components".
To install or uninstall your own components, or components from a third-party vendor, follow these steps:
The directory where you store the .DCP file--and the .DCU files, if they are included with the distribution--must be in the Delphi Library Path.
If the package is shipped as a .DPC (package collection) file, only the one file need be copied; the .DPC file contains the other files. (For more information about package collection files, see "Package collection files".)
The components in the package are installed on the Component palette pages specified in the components' RegisterComponents procedure, with the names they were assigned in the same procedure.
New projects are created with all available packages installed, unless you change the default settings. To make the current installation choices into the automatic default for new projects, check the Default check box at the bottom of the dialog box.
To remove components from the Component palette without uninstalling a package, select Component|Configure Palette, or select Tools|Environment Options and click the Palette tab. The Palette options tab lists each installed component along with the name of the Component palette page where it appears. Selecting any component and clicking Hide removes the component from the palette.
Creating a package involves specifying
Package source files, which end with the .DPK extension, are generated by the Package editor.
To create a package, follow the procedure below. Refer to "Understanding the structure of a package" for more information about the steps outlined here.
There are several ways to open an existing package for editing.
To edit a package's description or set usage options, click the Options speed button in the Package editor and select the Description tab.
The Project Options dialog has a Default check box in the lower left corner. If you click OK when this box is checked, the options you've chosen are saved as default settings for new projects. To restore the original defaults, delete or rename the DEFPROJ.DOF file.
Package source files, like project files, are generated by Delphi from information you supply. Like project files, they can also be edited manually. A package source file should be saved with the .DPK (Delphi package) extension to avoid confusion with other files containing Object Pascal source code.
To open a package source file in the Code editor,
For example, the following code declares the VCLDB50 package.
package VCLDB50; requires VCL50; contains Db, Dbcgrids, Dbctrls, Dbgrids, Dbinpreq, Dblogdlg, Dbpwdlg, Dbtables, mycomponent in 'C:\components\mycomponent.pas'; end.
Package names must be unique within a project. If you name a package STATS, the Package editor generates a source file for it called STATS.DPK; the compiler generates an executable and a binary image called STATS.BPL and STATS.DCP, respectively. Use STATS to refer to the package in the requires clause of another package, or when using the package in an application.
The requires clause specifies other, external packages that are used by the current package. An external package included in the requires clause is automatically linked at compile time into any application that uses both the current package and one of the units contained in the external package.
If the unit files contained in your package make references to other packaged units, the other packages should appear in your package's requires clause or you should add them. If the other packages are omitted from the requires clause, the compiler will import them into your package 'implicitly contained units'.
Note: Most packages that you create will require VCL50. Any package that depends on VCL units (including SysUtils) must list VCL50, or another package that requires VCL50, in its requires clause.
Packages cannot contain circular references in their requires clause. This means that
Duplicate references in a package's requires clause--or in the Runtime Packages edit box--are ignored by the compiler. For programming clarity and readability, however, you should catch and remove duplicate package references.
The contains clause identifies the unit files to be bound into the package. If you are writing your own package, put your source code in PAS files and include them in the contains clause.
A package cannot appear in the contains clause of another package.
All units included directly in a package's contains clause, or included indirectly in any of those units, are bound into the package at compile time.
A unit cannot be contained (directly or indirectly) in more than one package used by the same application, including the Delphi IDE. This means that if you create a package that contains one of the units in VCL50, you won't be able to install your package in the IDE. To use an already-packaged unit file in another package, put the first package in the second package's requires clause.
You can compile a package from the IDE or from the command line. To recompile a package by itself from the IDE,
You can insert compiler directives into your package source code. For more information, see "Package-specific compiler directives", below.
If you compile from the command line, several package-specific switches are available. For more information, see "Using the command-line compiler and linker".
The following table lists package-specific compiler directives that you can insert into your source code.
Prevents a package from being implicitly recompiled later. Use in .DPK files when compiling packages that provide low-level functionality, that change infrequently between builds, or whose source code will not be distributed. | |
Disables creation of imported data references. This directive increases memory-access efficiency, but prevents the unit where it occurs from referencing variables in other packages. | |
Packages unit "weakly." See "Weak packaging" below. | |
Compiles the package for installation in the IDE. (Put in .DPK file.) | |
Note: Including {$DENYPACKAGEUNIT ON} in your source code prevents the unit file from being packaged. Including {$G-} or {IMPORTEDDATA OFF} may prevent a package from being used in the same application with other packages. Packages compiled with the {$DESIGNONLY ON} directive should not ordinarily be used in applications, since they contain extra code required by the IDE. Other compiler directives may be included, if appropriate, in package source code. See Compiler directives in the online help for information on compiler directives not discussed here.
The $WEAKPACKAGEUNIT directive affects the way a .DCU file is stored in a package's .DCP and .BPL files. (For information about files generated by the compiler, see "Package files created by a successful compilation".) If {$WEAKPACKAGEUNIT ON} appears in a unit file, the compiler omits the unit from BPLs when possible, and creates a non-packaged local copy of the unit when it is required by another application or package. A unit compiled with this directive is said to be "weakly packaged."
For example, suppose you've created a package called PACK that contains only one unit, UNIT1. Suppose UNIT1 does not use any further units, but it makes calls to RARE.DLL. If you put {$WEAKPACKAGEUNIT ON} in UNIT1.PAS when you compile your package, UNIT1 will not be included in PACK.BPL; you will not have to distribute copies of RARE.DLL with PACK. However, UNIT1 will still be included in PACK.DCP. If UNIT1 is referenced by another package or application that uses PACK, it will be copied from PACK.DCP and compiled directly into the project.
Now suppose you add a second unit, UNIT2, to PACK. Suppose that UNIT2 uses UNIT1. This time, even if you compile PACK with {$WEAKPACKAGEUNIT ON} in UNIT1.PAS, the compiler will include UNIT1 in PACK.BPL. But other packages or applications that reference UNIT1 will use the (non-packaged) copy taken from PACK.DCP.
Note: Unit files containing the {$WEAKPACKAGEUNIT ON} directive must not have global variables, initialization sections, or finalization sections.
The $WEAKPACKAGEUNIT directive is an advanced feature intended for developers who distribute their BPLs to other Delphi programmers. It can help you to avoid distribution of infrequently used DLLs, and to eliminate conflicts among packages that may depend on the same external library.
For example, Delphi's PenWin unit references PENWIN.DLL. Most projects don't use PenWin, and most computers don't have PENWIN.DLL installed on them. For this reason, the PenWin unit is weakly packaged in VCL50. When you compile a project that uses PenWin and the VCL50 package, PenWin is copied from VCL50.DCP and bound directly into your project; the resulting executable is statically linked to PENWIN.DLL.
If PenWin were not weakly packaged, two problems would arise. First, VCL50 itself would be statically linked to PENWIN.DLL, and so you could not load it on any computer which didn't have PENWIN.DLL installed. Second, if you tried to create a package that contained PenWin, a compiler error would result because the PenWin unit would be contained in both VCL50 and your package. Thus, without weak packaging, PenWin could not be included in standard distributions of VCL50.
When you compile from the command line, you can use the package-specific switches listed in the following table.
Note: Using the -$G- switch may prevent a package from being used in the same application with other packages. Other command-line options may be used, if appropriate, when compiling packages. See "The Command-line compiler" in the online help for information on command-line options not discussed here.
To create a package, you compile a source file that has a .DPK extension. The base name of the .DPK file becomes the base name of the files generated by the compiler. For example, if you compile a package source file called TRAYPAK.DPK, the compiler creates a package called TRAYPAK.BPL.
The following table lists the files produced by the successful compilation of a package.
When distributing an application that uses runtime packages, make sure that your users have the application's .EXE file as well as all the library (.BPL or .DLL) files that the application calls. If the library files are in a different directory from the .EXE file, they must be accessible through the user's Path. You may want to follow the convention of putting library files in the Windows\System directory. If you use InstallShield Express, your installation script can check the user's system for any packages it requires before blindly reinstalling them.
If you distribute runtime or design-time packages to other Delphi developers, be sure to supply both .DCP and .BPL files. You will probably want to include .DCU files as well.
Package collections (.DPC files) offer a convenient way to distribute packages to other developers. Each package collection contains one or more packages, including BPLs and any additional files you want to distribute with them. When a package collection is selected for IDE installation, its constituent files are automatically extracted from their .PCE container; the Installation dialog box offers a choice of installing all packages in the collection or installing packages selectively.
To create a package collection,
Source as a Directory Name with C:\MyPackage\Source as the Suggested Path. The Installation dialog box will display C:\MyPackage\Source as the suggested path for the directory.
To edit or recompile an existing .PCE file, select File|Open in the Package Collection editor.
pubsweb@inprise.com
Copyright © 1999, Inprise Corporation. All rights reserved.