# Packages
A package is the unit of installation on a Fuchsia system. This document describes
various workflows for building and installng a package.
Note: The majority of these workflows rely on the `ffx` tool or the legacy `pm`
tool, which are available in `//tools`.
The workflows are:
* [Build a package](#build-package)
* [Publish a package](#publish-package)
* [Install a package](#install-package)
* [Run a component from an installed package](#run-component)
Additionally, the following legacy workflows are supported:
* [Build a package using the legacy pm tool](#build-package-legacy-pm)
* [Publish a package using the legacy pm tool](#publish-package-legacy-pm)
* [Install a package using the legacy pm tool](#install-package-legacy-pm)
For more details, see the help messages from `ffx package build help`,
`ffx repository publish help`, or `pm`.
## Build a package {#build-package}
To build a package:
1. Create a `meta` directory:
```posix-terminal
mkdir -p {{ '' }}PACKAGE_DIR{{ '' }}/meta
```
Replace PACKAGE_DIR with the staging directory where the package
is built.
1. Set the `$META_PACKAGE_FILE` environment variable:
```posix-terminal
export META_PACKAGE_FILE={{ '' }}PACKAGE_DIR{{ '' }}/meta/package
```
1. Open a text editor and create the `$META_PACKAGE_FILE` file with
the following content:
```none
{
"name": "",
"version": "0"
}
```
The version number is required to be `0`.
1. Save the file and close the text editor.
1. Create a [package build manifest file][build-manifest-file] (`$BUILD_MANIFEST_FILE`),
which provides the paths to all the package content files.
Each line of a manifest file maps to a file contained in the package and
is in the form of `destination=source` where:
* `destination` is the path to the file in the final package.
* `source` is the path to the file on the host machine.
The manifest file must include at least one line for the package ID file,
for example:
```none {:.devsite-disable-click-to-copy}
meta/package=
```
1. Go to the PACKAGE_DIR directory:
```posix-terminal
cd {{ '' }}PACKAGE_DIR{{ '' }}
```
1. Generate a package manifest file, which creates the package metadata archive
at PACKAGE_DIR`/meta.far`:
```posix-terminal
ffx package build $BUILD_MANIFEST_FILE
```
This command creates the package manifest file implicitly as
{{ '' }}PACKAGE_DIR{{ '' }}`/package_manifest.json`.
1. Set the `$PACKAGE_MANIFEST_FILE` environment variable:
```posix-terminal
export PACKAGE_MANIFEST_FILE="{{ '' }}PACKAGE_DIR{{ '' }}/package_manifest.json"
```
If the contents of the package change, you need to re-run the
`ffx package build $BUILD_MANIFEST_FILE` command.
1. Create a package archive, which gathers all the package contents into
a single distributable file:
```posix-terminal
ffx package archive create -o "{{ '' }}PACKAGE_NAME{{ '' }}.far" "$PACKAGE_MANIFEST_FILE"
```
Replace PACKAGE_NAME with the name of the package.
This command creates the package archive as PACKAGE_NAME`.far`.
1. Set the`$PACKAGE_ARCHIVE` environment variable:
```posix-terminal
export PACKAGE_ARCHIVE={{ '' }}PACKAGE_DIR{{ '' }}/{{ '' }}PACKAGE_NAME{{ '' }}.far
```
If the contents of the package change, you need to re-run the
`ffx package build` and `ffx package archive create` commands.
You have successfully built a package. Now you are ready to publish the package.
## Publish a package {#publish-package}
Note: The workflow in this section uses the environment variables set in
the previous [Build a package](#build-package) section.
To publish a package:
1. Initialize a directory that serves as a packages repository:
```posix-terminal
pm newrepo -repo {{ '' }}REPO{{ '' }}
```
This creates a directory structure named REPO that is ready for
publishing packages.
1. Publish package manifests to the repository:
```posix-terminal
ffx repository publish --package-manifest $PACKAGE_MANIFEST_FILE {{ '' }}REPO{{ '' }}
```
`ffx repository publish` parses `$PACKAGE_MANIFEST_FILE` and publishes the
package in the provided REPO directory.
The `--package-manifest` argument can be repeated. If you run this command
multiple times with different package manifests, each instance will be
published to the same repository. New versions of the same packages can be
published using the same command.
1. (Optional) Publish package archives to the repository:
```posix-terminal
ffx repository publish --package-archive $PACKAGE_ARCHIVE {{ '' }}REPO{{ '' }}
```
`ffx repository publish` parses `$PACKAGE_ARCHIVE` and publishes the
package in the provided REPO directory.
The `--package-archive` argument can be repeated. If you run this command
multiple times with different package archives, each instance will be
published to the same repository. New versions of the same packages can be
published using the same command.
You have successfully published a package. You are now ready to install a
package.
## Install a package {#install-package}
To install a package:
1. Start the package server:
```posix-terminal
ffx repository server start
```
By default, this starts an amber server on the host machine at port `8083`.
2. Add the repository:
```posix-terminal
ffx repository add-from-pm --name "" "{{ '' }}REPO{{ '' }}"
```
This introduces the repository (with the `pm` directory format) to the
`ffx repository server`. The `--name ""` is optional, but helpful.
3. Add the new repository as an update source:
```posix-terminal
ffx target repository register
```
Providing a short name for the repository using `-n ` is optional,
but helpful.
3. (On the target device) Download the package:
```
pkgctl resolve fuchsia-pkg://{{ '' }}REPO{{ '' }}/{{ '' }}PACKAGE_NAME{{ '' }}
```
If the component is not already present on the system, `pkgctl` downloads the
package and places the blobs in the blobFS in the process of resolving. If
the package already exists, the updates will be downloaded.
You have successfully installed or updated the package. You are now ready to
run a component from the installed package.
## Run a component from an installed package {#run-component}
(On the target device) run the component in a package:
```
run {{ '' }}COMPONENT_URI{{ '' }}
```
Replace COMPONENT_URI with a package URL in the form of
`fuchsia-pkg:///#meta/.cmx`.
You have successfully run a component from the installed package.
## Build a package using the legacy pm tool {#build-package-legacy-pm}
To build a package:
1. Create the package ID file:
Note: `$PACKAGE_DIR` is a staging directory where the package
is built.
```posix-terminal
pm -o $PACKAGE_DIR -n $PACKAGE_NAME init
```
This generates the package ID file implicitly as
`$PACKAGE_DIR/meta/package`. Set `$PACKAGE_ID_FILE` accordingly
for use in subsequent steps:
```posix-terminal
export PACKAGE_ID_FILE=${PACKAGE_DIR}/meta/package
```
`$PACKAGE_ID_FILE` will contain the following data:
```
{
"name": "",
"version": ""
}
```
2. Create the manifest file, `$MANIFEST_FILE`, that provides the path to
the package ID file. Each line of a manifest file maps a single file that
is contained in the package and is in the form of `destination=source` where:
* `destination` is the path to the file in the final package
* `source` is the path to the file on the host machine
The manifest file must include at least one line for the package ID file like
this:
```
meta/package=
```
3. Generate the package metadata archive:
```posix-terminal
pm -o $PACKAGE_DIR -m $MANIFEST_FILE build
```
This creates the metadata archive at `$PACKAGE_DIR/meta.far`.
4. (Optional) Create the package archive `$PACKAGE_ARCHIVE`:
```posix-terminal
pm -o $PACKAGE_DIR -m $MANIFEST_FILE archive
```
This command creates the package archive implicitly as
`$PACKAGE_DIR/$PACKAGE_NAME-0.far`. Set `$PACKAGE_ARCHIVE` accordingly
for use in subsequent steps:
```posix-terminal
export PACKAGE_ARCHIVE=${PACKAGE_DIR}/${PACKAGE_NAME}-0.far
```
If the contents of the package change, you need to re-run the
`pm -o $PACKAGE_DIR -m $MANIFEST_FILE archive` command.
You have successfully built a package. You are now ready to publish the package.
## Publish a package using the legacy pm tool {#publish-package-legacy-pm}
To publish a package:
1. Initialize a directory, `$REPO`, that serves as a packages repository:
```posix-terminal
pm newrepo -repo $REPO
```
This creates a directory structure named `$REPO` that is ready for
publishing packages.
2. Publish packages to the repository `$REPO`:
```posix-terminal
pm publish -a -r $REPO -f $PACKAGE_ARCHIVE
```
`pm publish` parses `$PACKAGE_ARCHIVE` and publishes the package in the
provided `$REPO` directory. If you run this command multiple times with
different package archives, `pm publish` publishes the packages to the same
repository. New versions of a same package can be published using the same
command.
You have successfully published a package. You are now ready to install a
package.
## Install a package using the legacy pm tool {#install-package-legacy-pm}
To install a package:
1. Start the package server:
```posix-terminal
pm serve -repo $REPO
```
By default, this starts an amber server on the host machine at port `8083`.
2. (On the target device) Add the new repository as an update source with
`pkgctl`:
```
pkgctl repo add url -f 1 -n $REPO http://$HOST_ADDRESS:8083/config.json
```
The option `-f 1` must be set if `pm` is serving a component v1 config.json
configuration file. (This is currently the case, but will change to serving
component v2 configuration files in the future. Once this change has
happened, the `-f 1` can be omitted.)
Providing a short name for the repository using `-n $REPO` is optional, but
helpful. If this short name is not provided, `pkgctl` will derive it from
the provided config URL.
3. (On the target device) Get the package:
```
pkgctl resolve fuchsia-pkg://$REPO/$PACKAGE_NAME
```
If the component is not already present on the system, `pkgctl` downloads the
package and places the blobs in the blobfs in the process of resolving. If
the package already exists, the updates will be downloaded.
You have successfully installed or updated the package. You are now ready to
run a component from the installed package.
[build-manifest-file]: /docs/development/build/build_system/internals/manifest_formats.md