RAD Studio (Common)
ContentsIndex
PreviousUpNext
Packages

The following topics describe packages and various issues involved in creating and compiling them.

  • Package declarations and source files
  • Naming packages
  • The requires clause
  • Avoiding circular package references
  • Duplicate package references
  • The contains clause
  • Avoiding redundant source code uses
  • Compiling packages
  • Generated files
  • Package-specific compiler directives
  • Package-specific command-line compiler switches

A package is a specially compiled library used by applications, the IDE, or both. Packages allow you to rearrange where code resides without affecting the source code. This is sometimes referred to as application partitioning

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 referencing runtime packages in their requires clauses. 

On Win32, package files end with the .bpl (Borland package library) extension. On the .NET platform, packages are .NET assemblies, and end with an extension of .dll 

Ordinarily, packages are loaded statically when an applications starts. But you can use the LoadPackage and UnloadPackage routines (in the SysUtils unit) to load packages dynamically.

Note: When an application utilizes packages, the name of each packaged unit still must appear in the uses
clause of any source file that references it.

Each package is declared in a separate source file, which should be saved with the .dpk extension to avoid confusion with other files containing Delphi code. A package source file does not contain type, data, procedure, or function declarations. Instead, it contains:

  • a name for the package.
  • a list of other packages required by the new package. These are packages to which the new package is linked.
  • a list of unit files contained by, or bound into, the package when it is compiled. The package is essentially a wrapper for these source-code units, which provide the functionality of the compiled package.
A package declaration has the form 

packagepackageName; 

requiresClause; 

containsClause; 

end

where packageName is any valid identifier. The requiresClause and containsClause are both optional. For example, the following code declares the DATAX package.

package DATAX;
  requires
  rtl,
  contains Db, DBLocal, DBXpress, ... ;
end.

The requires clause lists other, external packages used by the package being declared. It consists of the directive requires, followed by a comma-delimited list of package names, followed by a semicolon. If a package does not reference other packages, it does not need a requires clause. 

The contains clause identifies the unit files to be compiled and bound into the package. It consists of the directive contains, followed by a comma-delimited list of unit names, followed by a semicolon. Any unit name may be followed by the reserved word in and the name of a source file, with or without a directory path, in single quotation marks; directory paths can be absolute or relative. For example,

contains MyUnit in 'C:\MyProject\MyUnit.pas';

Note: Thread-local variables (declared with threadvar
) in a packaged unit cannot be accessed from clients that use the package.

Naming packages

A compiled package involves several generated files. For example, the source file for the package called DATAX is DATAX.DPK, from which the compiler generates an executable and a binary image called 

DATAX.BPL (Win32) or DATAX.DLL (.NET), and DATAX.DCP (Win32) or DATAX.DCPIL (.NET) 

DATAX is used to refer to the package in the requires clauses of other packages, or when using the package in an application. Package names must be unique within a project. 

The requires clause

The requires clause lists other, external packages that are used by the current package. It functions like the uses clause in a unit file. An external package listed 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 a package make references to other packaged units, the other packages should be included in the first package's requires clause. If the other packages are omitted from the requires clause, the compiler loads the referenced units from their .dcu or .dcuil files.

Avoiding circular package references

Packages cannot contain circular references in their requires clauses. This means that

  • A package cannot reference itself in its own requires clause.
  • A chain of references must terminate without rereferencing any package in the chain. If package A requires package B, then package B cannot require package A; if package A requires package B and package B requires package C, then package C cannot require package A.
 

Duplicate package references

The compiler ignores duplicate references in a package's requires clause. For programming clarity and readability, however, duplicate references should be removed.

The contains clause

The contains clause identifies the unit files to be bound into the package. Do not include file-name extensions in the contains clause.

Avoiding redundant source code uses

A package cannot be listed in the contains clause of another package or the uses clause of a unit. 

All units included directly in a package's contains clause, or indirectly in the uses clauses of those units, are bound into the package at compile time. The units contained (directly or indirectly) in a package cannot be contained in any other packages referenced in requires clause of that package. 

A unit cannot be contained (directly or indirectly) in more than one package used by the same application.

Packages are ordinarily compiled from the IDE using .dpk files generated by the Project Manager. You can also compile .dpk files directly from the command line. When you build a project that contains a package, the package is implicitly recompiled, if necessary.

Generated Files

The following table lists the files produced by the successful compilation of a package.  

Compiled package files  

File extension  
Contents  
DCP (Win32) or DCPIL (.NET)  
A binary image containing a package header and the concatenation of all .dcu (Win32) or .dcuil (.NET) files in the package. A single .dcp or .dcpil file is created for each package. The base name for the file is the base name of the .dpk source file.  
BPL (Win32) or DLL (.NET)  
The runtime package. This file is a DLL on Win32 with special Borland-specific features. The base name for the package is the base name of the dpk source file.  

 

Package-Specific Compiler Directives

The following table lists package-specific compiler directives that can be inserted into source code.  

Package-specific compiler directives  

Directive  
Purpose  
{$IMPLICITBUILD OFF}  
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.  
{$G-} or {$IMPORTEDDATA OFF}  
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.  
{$WEAKPACKAGEUNIT ON}  
Packages unit weakly.  
{$DENYPACKAGEUNIT ON}  
Prevents unit from being placed in a package.  
{$DESIGNONLY ON}  
Compiles the package for installation in the IDE. (Put in .dpk file.)  
{$RUNONLY ON}  
Compiles the package as runtime only. (Put in .dpk file.)  

Including {$DENYPACKAGEUNIT ON} in 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. 

Other compiler directives may be included, if appropriate, in package source code.

Package-Specific Command-Line Compiler Switches

The following package-specific switches are available for the command-line compiler.  

Package-specific command-line compiler switches  

Switch  
Purpose  
-$G-  
Disables creation of imported data references. Using this switch increases memory-access efficiency, but prevents packages compiled with it from referencing variables in other packages.  
LE path  
Specifies the directory where the compiled package file will be placed.  
LN path  
Specifies the directory where the package dcp or dcpil file will be placed.  
LUpackageName [;packageName2;...]  
Specifies additional runtime packages to use in an application. Used when compiling a project.  
Z  
Prevents a package from being implicitly recompiled later. Use when compiling packages that provide low-level functionality, that change infrequently between builds, or whose source code will not be distributed.  

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.

Note: When using the -LU
switch on the .NET platform, you can refer to the package with or without the .dll extension. If you omit the .dll extension, the compiler will look for the package on the unit search path, and on the package search path. However, if the package specification contains a drive letter or the path separator character, then the compiler will assume the package name is the full file name (including the .dll extension). In the latter case, if you specify a full or relative path, but omit the .dll extension, the compiler will not be able to locate the package.

Copyright(C) 2008 CodeGear(TM). All Rights Reserved.
What do you think about this topic? Send feedback!