<<../_v2_banner.md>>
A component manifest is a file that defines a component by encoding a component declaration. This document gives an overview of the concepts used by component declarations, and presents the syntax for writing component manifest source. Component declarations contain:
This section explains the distinction between component manifests, component manifest sources, and component declarations.
A component manifest is a file that encodes a component declaration, usually distributed as part of a package. The binary format is a persisted FIDL file mapping one-to-one onto the component declaration, typically ending in a .cm
extension.
A fuchsia-pkg URL with a component manifest resource path identifies a component in a package.
A component manifest source is a file that encodes part of a component manifest. Component manifest sources are written in CML (component manifest language), which is the developer-facing source format for component manifests. CML files are JSON5 files that end with a .cml
extension. Descriptions and examples of the CML syntax are contained in this document: see Syntax.
Component manifest sources are compiled to component manifests by the cmc
tool.
The ComponentDecl
FIDL table is a component declaration. Component declarations are used by the component framework APIs to represent components and may be provided to components at runtime.
The component framework doesn't dictate a particular format for programs, but instead requires components to specify which runtime they need by specifying a runner. The component framework provides a built-in ELF runner, while other runtimes are implemented as components within the framework. A component can use any runner available in its environment.
The program
section of a component manifest declares to the runner how the component is run, such as the program location and any arguments. Components using the ELF runner should specify the binary name and arguments, as documented in the ELF runner page. Other runners may have other runner-specific details, documented by that runner.
A component may also have no runtime at all by omitting the program
section. In this case, the component may still route capabilities and host children, but no code will be executed for the component.
See also: ELF Runner, Component Runners
Component manifests provide a syntax for routing capabilities between components. For a detailed walkthrough about what happens during capability routing, see Life of a protocol open
The following capabilities can be routed:
protocol
: A filesystem service node that can be used to open a channel to a FIDL protocol.directory
: A filesystem directory.storage
: A filesystem directory that is isolated to the component using it.runner
: A capability that allows a component to use a particular runner.protocol
, directory
and storage
capabilities are routed to components that use
them. runner
capabilities are routed to environments that include them.
Component manifests declare how capabilities are routed between components. The language of capability routing consists of the following three keywords:
use
: When a component uses
a capability, the capability is installed in the component's namespace. A component may use
any capability that has been offered
to it.offer
: A component may offer
a capability to a target, which is either a child or collection. When a capability is offered to a child, the child instance may use
the capability or offer
it to one of its own targets. Likewise, when a capability is offered to a collection, any instance in the collection may use
the capability or offer
it.expose
: When a component exposes
a capability to its parent, the parent may offer
the capability to one of its other children. A component may expose
any capability that it provides, or that one of its children exposes.When you use these keywords together, they express how a capability is routed from a component instance‘s outgoing directory to another component instance’s namespace:
use
describes the capabilities that populate a component instance's namespace.expose
and offer
describe how capabilities are passed between component instances. Aside from their directionality, there is one significant difference between offer
and expose
. While a component may use
a capability that was offered
to it, a component is not allowed to use
a capability that was exposed
to it by its child. This restriction exists to prevent dependency cycles between parent and child.A framework protocol is a protocol provided by the component framework. Because the component framework itself provides the protocol, any component may use
it without an explicit offer
. Fuchsia supports the following framework protocols:
fuchsia.sys2.Realm
: Allows a component to manage and bind to its children. Scoped to the component's realm.A framework directory is a directory provided by the component framework. Because the component framework itself is the provider of the directory, any component may use
it without an explicit offer
. Fuchsia supports the following framework directories:
hub
: Allows a component to perform runtime introspection of itself and its children.Capabilities are identified by a capability name. A capability name consists of a string containing the characters a
to z
, A
to Z
, 0
to 9
, underscore (_
), hyphen (-
), or the full stop character (.
).
Directory rights define how a directory may be accessed in the component framework. You must specify directory rights on use
declarations and on expose
and offer
declarations from self
. On expose
and offer
declarations not from self
, they are optional.
A rights field can be defined by the combination of any of the following rights tokens:
rights: ["connect", "enumerate", "read_bytes", "write_bytes", "execute_bytes", "update_attributes", "get_attributes", "traverse", "modify_directory"]
See fuchsia.io2.Rights
for the equivalent FIDL definitions.
However rights aliases should be preferred where possible for clarity.
rights: ["r*", "w*", "x*", "rw*", "rx*"]
Except in special circumstances you will almost always want either ["r*"]
or ["rw*"]
. Only one alias can be provided to a rights field and it must not conflict with any longform rights.
Right aliases are simply expanded into their longform counterparts:
"r*" -> ["connect", "enumerate", "traverse", "read_bytes", "get_attributes"] "w*" -> ["connect", "enumerate", "traverse", "write_bytes", "update_attributes", "modify_directory"] "x*" -> ["connect", "enumerate", "traverse", "execute_bytes"]
Merged aliases like rw*
are simply r*
and w*
merged without duplicates.
This example shows usage of a directory use declaration annotated with rights:
use: [ { directory: "test", from: "parent", rights: ["rw*", "admin"], path: "/data/test", }, ],
For an example of how these keywords interact, consider the following component instance tree:
In this example, the echo
component instance provides an fuchsia.Echo
protocol in its outgoing directory. This protocol is routed to the echo_tool
component instance, which uses it. It is necessary for each component instance in the routing path to propagate fuchsia.Echo
to the next component instance.
The routing sequence is:
echo
hosts the fuchsia.Echo
protocol in its outgoing directory. Also, it exposes fuchsia.Echo
from self
so the protocol is visible to its parent, services
.services
exposes fuchsia.Echo
from its child echo
to its parent, shell
.system
offers fuchsia.Echo
from its child services
to its other child tools
.tools
offers fuchsia.Echo
from parent
(i.e., its parent) to its child echo_tool
.echo_tool
uses fuchsia.Echo
. When echo_tool
runs, it will find fuchsia.Echo
in its namespace.A working example of capability routing can be found at //examples/components/routing.
Facets are metadata that is ignored by the component framework itself, but may be interpreted by interested components.
This section describes the syntax for each section of the component manifest, in CML format.
A reference is a string of the form #<reference-name>
, where <reference-name>
is a string of one or more of the following characters: a-z
, 0-9
, _
, .
, -
.
A reference may refer to:
<reference-name>
.<reference-name>
.The optional include
property describes zero or more other component manifest files (or shards) to be merged into this component manifest. For example:
include: [ "src/lib/syslog/client.shard.cml" ]
In the example given above, the component manifest is including contents from a manifest shard provided by the syslog
library, thus ensuring that the component functions correctly at runtime if it attempts to write to syslog. By convention such files end with .shard.cml
.
If working in fuchsia.git, include paths are relative to the source root of the Fuchsia tree.
You can review the outcome of merging any and all includes into a component manifest file by invoking the following command:
fx cmc include {{ "<var>" }}cml_file{{ "</var>" }} --includepath $FUCHSIA_DIR
Includes can be recursive, meaning that shards can have their own includes.
If the component contains executable code, the content of the program
section is determined by the runner the component uses. Some components don't have executable code; the declarations for those components lack a program
section.
If the component uses the ELF runner, program
is an object with the following properties:
binary
: Package-relative path to the executable binaryargs
(optional): List of argumentsprogram: { binary: "bin/hippo", args: [ "Hello", "hippos!" ], }, use: [ { runner: "elf" }, ],
See also: ELF Runner
If a component uses a custom runner, values inside the program
stanza are specific to the runner. The runner receives the arguments as a dictionary of key and value pairs. Refer to the specific runner being used to determine what keys it expects to receive, and how it interprets them.
The children
section declares child component instances as described in Child component instances
children
is an array of objects with the following properties:
name
: The name of the child component instance, which is a string of one or more of the following characters: a-z
, 0-9
, _
, .
, -
.url
: The component URL for the child component instance.startup
(optional): The component instance's startup mode.lazy
(default): Start the component instance only if another component instance binds to it.eager
: (legacy feature) Start the component instance as soon as its parent starts.environment
(optional): If present, the name of the environment to be assigned to the child component instance, one of environments
. If omitted, the child will inherit the same environment assigned to this component.Example:
children: [ { name: "logger", url: "fuchsia-pkg://fuchsia.com/logger#logger.cm", }, { name: "pkg_cache", url: "fuchsia-pkg://fuchsia.com/pkg_cache#meta/pkg_cache.cm", startup: "eager", }, ],
The collections
section declares collections as described in Component collections.
collections
is an array of objects with the following properties:
name
: The name of the component collection, which is a string of one or more of the following characters: a-z
, 0-9
, _
, .
, -
.durability
: The duration of child component instances in the collection.transient
: The instance exists until its parent is stopped or it is explicitly destroyed.persistent
: The instance exists until it is explicitly destroyed. This mode is not yet supported.environment
(optional): If present, the environment that will be assigned to instances in this collection, one of environments
. If omitted, instances in this collection will inherit the same environment assigned to this component.Example:
collections: [ { name: "tests", durability: "transient", }, ],
The environments
section declares environments as described in Environments.
environments
is an array of objects with the following properties:
name
: The name of the environment, which is a string of one or more of the following characters: a-z
, 0-9
, _
, .
, -
.extend
: How the environment should extend this realm's environment.realm
: Inherit all properties from this realm's environment.none
: Start with an empty environment, do not inherit anything.runners
: The runners registered in the environment. An array of objects with the following properties:runner
: The name of a runner capability, whose source is specified in from
.from
: The source of the runner capability, one of:parent
: The component's parent.self
: This component.#<child-name>
: A reference to a child component instance.as
(option): An explicit name for the runner as it will be known in this environment. If omitted, defaults to runner
.Example:
environments: [ { name: "test-env", extend: "realm", runners: [ { runner: "gtest-runner", from: "#gtest", }, ], }, ],
The capabilities
section defines capabilities that are provided by this component. Capabilities that are offered or exposed from self
must be declared here.
capabilities
is an array of objects of any of the following types:
A definition of a protocol capability.
protocol
: The name for this protocol capability, or an array of names to define multiple protocols.path
(optional): The path in the component's outgoing directory from which this protocol is served. Only supported when protocol
is a single name. Defaults to /svc/${protocol}
.A definition of a directory capability.
protocol
: The name for this directory capability.path
: The path in the component's outgoing directory from which this directory is served.rights
: The maximum directory rights that may be set when using this directory.A definition of a storage capability.
storage
: The name for this storage capability.from
: The source of the directory capability backing the new storage capabilities, one of:parent
: The component's parent.self
: This component.#<child-name>
: A reference to a child component instance.backing_dir
: The name of the directory backing the storage.subdir
: Users are given isolated access to this sub-directory that is inside of the backing_dir
directory.A definition of a runner capability.
runner
: The name for this runner capability.path
: The path in the component's outgoing directory from which the fuchsia.sys2.ComponentRunner
protocol is served.from
: Must be set, but ignored (fxb/52195).The use
section declares the capabilities that the component can use at runtime, as explained in Routing terminology.
use
is an array of objects with the following properties:
path
(optional): The path at which to install the capability in the component's namespace. For protocols, defaults to /svc/${protocol}
. Required for directory
and storage
. This protocol cannot be used:protocol
is an array of multiple items.Example:
use: [ { protocol: [ "fuchsia.ui.scenic.Scenic", "fuchsia.accessibility.Manager", ] }, { directory: "themes", path: "/data/themes", rights: [ "r*" ], }, { storage: "persistent", path: "/data", }, { runner: "web", }, ],
The expose
section declares the capabilities exposed by this component, as explained in Routing terminology.
expose
is an array of objects with the following properties:
from
: The source of the capability, one of:self
: This component. Requires a corresponding capability
declaration.#<child-name>
: A reference to a child component instance.to
(optional): The capability target. Either parent
or framework
. Defaults to parent
.as
(optional): The name for the capability as it will be known by the target. If omitted, defaults to the original name. This property cannot be used when protocol
is an array of multiple items.Example:
expose: [ { directory: "themes", from: "self", }, { protocol: "pkg.Cache", from: "#pkg_cache", as: "fuchsia.pkg.PackageCache", }, { protocol: [ "fuchsia.ui.app.ViewProvider", "fuchsia.fonts.Provider", ], from: "self", }, { runner: "web-chromium", from: "#web_runner", as: "web", }, ],
The offer
section declares the capabilities offered by this component, as explained in Routing terminology.
offer
is an array of objects with the following properties:
from
: The source of the capability, one of:parent
: The component's parent. This source can be used for all capability types.self
: This component. Requires a corresponding capability
declaration.#<child-name>
: A reference to a child component instance. This source can only be used when offering protocol, directory, or runner capabilities.to
: An array of capability targets, each of which is a reference to the child or collection to which the capability is being offered, of the form #<target-name>
.as
(optional): An explicit name for the capability as it will be known by the target. If omitted, defaults to the original name. as
cannot be used when protocol
is an array of multiple items.dependency
(optional): The type of dependency between the source and targets, one of:strong
: a strong dependency, which is used to determine shutdown ordering. Component manager is guaranteed to stop the target before the source. This is the default.weak_for_migration
: a weak dependency, which is ignored during shutdown. When component manager stops the parent realm, the source may stop before the clients. Clients of weak dependencies must be able to handle these dependencies becoming unavailable. This type exists to keep track of weak dependencies that resulted from migrations into v2 components.Example:
offer: [ { protocol: "fuchsia.logger.LogSink", from: "#logger", to: [ "#fshost", "#pkg_cache" ], dependency: "weak_for_migration", }, { protocol: [ "fuchsia.ui.app.ViewProvider", "fuchsia.fonts.Provider", ], from: "#session", to: [ "#ui_shell" ], dependency: "strong", }, { directory: "blobfs", from: "self", to: [ "#pkg_cache" ], }, { directory: "fshost-config", from: "parent", to: [ "#fshost" ], directory: "config", }, { storage: "cache", from: "parent", to: [ "#logger" ], }, { runner: "web", from: "parent", to: [ "#user-shell" ], }, ],
The facets
section is a JSON object containing facets, chunks of metadata which components may interpret for their own purposes. The component framework enforces no schema for this section, but third parties may expect their facets to adhere to a particular schema.
This section may be omitted.