Dependencies are one of pub’s core concepts. A dependency is another package that your package needs in order to work. Dependencies are specified in your pubspec. You only list immediate dependencies—the software that your package uses directly. Pub handles transitive dependencies for you.
For each dependency, you specify the name of the package you depend on. For library packages, you specify the range of versions of that package that you allow. You may also specify the source which tells pub how the package can be located, and any additional description that the source needs to find the package.
Based on what data you want to provide, you can specify dependencies in two ways. The shortest way is to just specify a name:
This creates a dependency on
transmogrify that allows any version, and looks
it up using the default source, which is pub.dartlang.org. To limit the
dependency to a range of versions, you can provide a version constraint:
dependencies: transmogrify: '>=1.0.0 <2.0.0'
This creates a dependency on
transmogrify using the default source and
allowing any version from
2.0.0 (but not including
Version constraints for details on the version
If you want to specify a source, the syntax looks a bit different:
dependencies: transmogrify: hosted: name: transmogrify url: http://some-package-server.com
This depends on the
transmogrify package using the
Everything under the source key (here, just a map with a
url: key) is the
description that gets passed to the source. Each source has its own description
format, detailed below.
You can also provide a version constraint:
dependencies: transmogrify: hosted: name: transmogrify url: http://some-package-server.com version: '>=1.0.0 <2.0.0'
This long form is used when you don’t use the default source or when you have a complex description you need to specify. But in most cases, you’ll just use the simple “name: version” form.
Here are the different sources pub can use to locate packages, and the descriptions they allow:
A hosted package is one that can be downloaded from pub.dartlang.org (or another HTTP server that speaks the same API). Most of your dependencies will be of this form, as shown in the following example:
dependencies: transmogrify: '>=0.4.0 <1.0.0'
This specifies that your package depends on a hosted package named “transmogrify” and will work with any version from 0.4.0 to 1.0.0 (but not 1.0.0 itself).
If you want to use your own package server, you can use a description that specifies its URL:
dependencies: transmogrify: hosted: name: transmogrify url: http://your-package-server.com version: '>=0.4.0 <1.0.0'
Sometimes you live on the bleeding edge and you need to use packages that haven’t been formally released yet. Maybe your package itself is still in development and is using other packages that are being developed at the same time. To make that easier, you can depend directly on a package stored in a Git repository.
dependencies: kittens: git: git://github.com/munificent/kittens.git
git here says this package is found using Git, and the URL after that is
the Git URL that can be used to clone the package. Pub assumes that the package
is in the root of the git repository.
If you want to depend on a specific commit, branch, or tag, you can also
dependencies: kittens: git: url: git://github.com/munificent/kittens.git ref: some-branch
The ref can be anything that Git allows to identify a commit.
Sometimes you find yourself working on multiple related packages at the same time. Maybe you are creating a framework while building an app that uses it. In those cases, during development you really want to depend on the “live” version of that package on your local file system. That way changes in one package are instantly picked up by the one that depends on it.
To handle that, pub supports path dependencies.
dependencies: transmogrify: path: /Users/me/transmogrify
This says the root directory for
For this dependency, pub generates a symlink directly to the
of the referenced package directory. Any changes you make to the dependent
package are seen immediately. You don’t need to run pub every time you
change the dependent package.
Relative paths are allowed and are considered relative to the directory containing your pubspec.
Path dependencies are useful for local development, but do not work when sharing code with the outside world—not everyone can get to your file system. Because of this, you cannot upload a package to pub.dartlang.org if it has any path dependencies in its pubspec.
Instead, the typical workflow is:
If your package is an application, you don’t usually need to specify version constraints for your dependencies. You typically want to use the latest versions of the dependencies when you first create your app. Then you’ll create and check in a lockfile that pins your dependencies to those specific versions. Specifying version constraints in your pubspec then is usually redundant (though you can do it if you want).
For a library package that you want users to reuse, though, it is important to specify version constraints. That lets people using your package know which versions of its dependencies they can rely on to be compatible with your library. Your goal is to allow a range of versions as wide as possible to give your users flexibility. But it should be narrow enough to exclude versions that you know don’t work or haven’t been tested.
The Dart community uses semantic versioning1, which helps you know which versions should work.
If you know that your package works fine with
1.2.3 of some dependency, then
semantic versioning tells you that it should work (at least) up to
A version constraint is a series of:
You can specify version parts as you want, and their ranges are intersected
together. For example,
>=1.2.3 <2.0.0 allows any version from
Pub supports two flavors of dependencies: regular dependencies and dev dependencies. Dev dependencies differ from regular dependencies in that dev dependencies of packages you depend on are ignored. Here’s an example:
transmogrify package uses the
unittest package in its tests and only
in its tests. If someone just wants to use
libraries—it doesn’t actually need
unittest. In this case, it specifies
unittest as a dev dependency. Its pubspec will have something like:
dev_dependencies: unittest: '>=0.5.0'
Pub gets every package that your package depends on, and everything those
packages depend on, transitively. It also gets your package’s dev dependencies,
but it ignores the dev dependencies of any dependent packages. Pub only gets
your package’s dev dependencies. So when your package depends on
transmogrify it will get
transmogrify but not
The rule for deciding between a regular or dev dependency is simple: If
the dependency is imported from something in your
lib directory, it needs to
be a regular dependency. If it’s only imported from
example, etc. it
can and should be a dev dependency.
Using dev dependencies makes dependency graphs smaller. That makes
faster, and makes it easier to find a set of package versions that satisfies all
You can use
dependency_overrides to temporarily override all references
to a dependency.
For example, perhaps you are updating a local copy of transmogrify, a published library package. Transmogrify is used by other packages in your dependency graph, but you don’t want to clone each package locally and change each pubspec to test your local copy of transmogrify.
In this situation, you can override the dependency using
dependency_overrides to specify the directory holding the local
copy of the package.
The pubspec would look something like the following:
name: my_app dependencies: transmogrify: '>= 1.2.0 <2.0.0' dependency_overrides: transmogrify: path: ../transmogrify_patch/
When you run
pub get, the pubspec’s lockfile is updated to reflect the
new path to your dependency and, whereever transmogrify is used, pub
uses the local version instead.
You can also use
dependency_overrides to specify a particular
version of a package:
name: my_app dependencies: transmogrify: '>= 1.2.0 <2.0.0' dependency_overrides: transmogrify: '3.2.1'
Caution: Using a dependency override involves some risk. For example, using an override to specify a version outside the range that the package claims to support, or using an override to specify a local copy of a package that has unexpected behaviors, may break your application.
2.0.0-rc.1of the semantic versioning spec, because that version allows packages to use build identifiers (e.g.
+12345) to differentiate versions. ↩