Bundled Dependencies
Some libraries ship bundled with the Delphi IDE rather than as DPM packages. The classic example is Indy — every Delphi install already has a copy of Indy on its library path, but there is (currently) no DPM package for it.
This creates a problem for package authors. If your package uses Indy, you would like to declare that dependency so it is visible and documented. But a normal DPM dependency must point at a real package and a version range:
dependencies:
- id: Indy.System
version: "[10.6.2,]" # <-- there is no Indy.System package to satisfy this!
With no Indy.System package on any feed, the resolver fails: it cannot satisfy the dependency, so the install errors out.
Bundled dependencies solve this. You declare the dependency using the special version bundled , and DPM does the right thing:
If no package for that id exists, the dependency is satisfied by the copy that ships with the IDE — no download, nothing added to your
.dprojsearch paths.If a real package for that id is present (because the user installed one, or another package pulled it in), that real package is used automatically — at whatever version it happens to be.
You declare the intent once; DPM picks the best available option at install time.
Declaring a bundled dependency
Use bundled as the version:
dependencies:
- id: Indy.System
version: bundled
That's it. There is no separate "kind" or flag — the version string is the whole signal.
Under the hood
bundledis an alias for the sentinel version999.999.999. You can write either form;bundledis just easier to read.
A worked example: Indy
Imagine the Indy source is eventually published to DPM as three packages that build on each other:
Package |
Purpose |
|---|---|
|
Low-level system units (sockets, streams, globals) |
|
Core components, built on |
|
HTTP / SMTP / FTP etc., built on |
Today none of these exist as DPM packages — Indy comes from the IDE. So a package that needs Indy's protocols declares the whole chain as bundled :
# MyHttpHelper.dspec
metadata:
id: Acme.MyHttpHelper
version: 1.0.0
description: Helpers built on Indy's HTTP client
authors:
- Acme
license: Apache-2.0
targetPlatforms:
- compiler: 12.0
platforms: [Win32, Win64]
template: default
templates:
- name: default
dependencies:
- id: Indy.System
version: bundled
- id: Indy.Core
version: bundled
- id: Indy.Protocols
version: bundled
source:
- src: .\src\*.pas
dest: src
What happens when a user installs Acme.MyHttpHelper
Case 1 — no Indy packages exist (the situation today). The three bundled dependencies resolve to no-ops. Nothing is downloaded for them and no Indy search paths are added — the compiler finds Indy on the IDE's default library path, exactly as it would without DPM. The install succeeds.
Case 2 — the user installs a real Indy package. Later, real Indy packages become available and the user adds one to their project as a top-level package:
dpm install Indy.Protocols
Now Indy.Protocols (and whatever it depends on — Indy.Core , Indy.System ) is a real resolved package. The next time Acme.MyHttpHelper is resolved, its bundled dependencies see the real packages already in the graph and defer to them automatically . The real Indy source is used and its search paths are added — no change needed to Acme.MyHttpHelper .
The author never had to ship two versions of their package or guess at version numbers.
Rules and behaviour
Any real version wins. A
bundleddependency is satisfied by any version of a real package with the same id. DPM does not apply a version range to it — that is the user's choice when they install the real package.DPM never auto-fetches the real package. A
bundleddependency only honours what is already in the dependency graph. It will not reach out to a feed and pull in the latest Indy on its own — the user opts in by installing a real package themselves. This keeps resolution predictable and works offline.Nothing is written to your project. A bundled no-op contributes no
PackageReferenceand no search path to the.dproj. Restores re-evaluate it each time, so there is never a stale999.999.999entry left behind.It is satisfied per id, once. If several of your packages declare
bundledon the same id, they all share a single resolution.
When to use it
Use a bundled dependency when:
The library ships with the Delphi IDE (Indy, and similar built-in libraries), and
You want to declare the dependency so it is documented and ready to be replaced by a real package later.
Do not use it for ordinary libraries that have a normal DPM package — declare those with a real version range (see Version Ranges ).
See also
Creating Packages — the full spec format, including the dependencies section.
Version Range — the dependency version range syntax.