This section provides guidance on migrating components that use other common capabilities or features.
Resolvers
If your component is not part of the base
package set for your product, you
must route the full-resolver
resolver to it. Resolvers are routed to components
using environments, and core.cml
has a shared environment named
core-env
for components outside of base
.
Use the list-packages
command to report the package sets where your component
package is included.
fx list-packages --verbose my-package
If the package is not listed with the base
tag, follow the remaining
instructions in this section.
When adding your component, assign the shared
core-env
as your component's environment
.
// core.cml / component.core_shard.cml
{
children: [
...
{
name: "my_component",
url: "fuchsia-pkg://fuchsia.com/my-pkg#meta/my_component.cm",
environment: "#core-env",
},
],
}
Start on boot
If your component appears in a sysmgr config startup_services
or apps
block
you should make your component an eager
component in its parent's manifest.
// parent.cml
{
children: [
...
{
name: "font_provider",
url: "fuchsia-pkg://fuchsia.com/fonts#meta/fonts.cm",
startup: "eager",
},
],
}
Additionally you need to ensure that all your component's ancestors up to
/core
are eager
components. If your component is present on all products
that derive from the core
you can add it to core directly,
otherwise you need to use core realm variability to allow
products without your component to continue to boot.
The eager
component should be in the base package set; eager
is generally
incompatible with being outside the base package set.
For more details on how eager
impacts component startup see,
lifecycle and component manifests.
Lifecycle
If your component serves the fuchsia.process.lifecycle.Lifecycle
protocol,
follow these instructions to migrate to the lifecycle handle provided by the
ELF runner in Components v2.
Remove your component's entry in the
appmgr
allowlist:// Remove this entry. lifecycle_allowlist.insert(component::Moniker{ .url = "fuchsia-pkg://fuchsia.com/my_package#meta/my_component.cmx", .realm_path = {"app", "sys"}});
When migrating your component manifest, add the lifecycle stop event:
// my_component.cml { include: [ "syslog/client.shard.cml", ], program: { runner: "elf", binary: "bin/my_binary", lifecycle: { stop_event: "notify" }, }, ... }
Get the
fuchsia.process.lifecycle.Lifecycle
channel provided by the ELF runner:Rust
use fidl_fuchsia_process_lifecycle::{LifecycleRequest, LifecycleRequestStream}; // ... #[fuchsia::main(logging_tags = ["lifecycle", "example"])] async fn main() { // Take the lifecycle handle provided by the runner match fuchsia_runtime::take_startup_handle(HandleInfo::new(HandleType::Lifecycle, 0)) { Some(lifecycle_handle) => { info!("Lifecycle channel received."); // Begin listening for lifecycle requests on this channel let x: fuchsia_zircon::Channel = lifecycle_handle.into(); let async_x = AsyncChannel::from( fuchsia_async::Channel::from_channel(x).expect("Async channel conversion failed."), ); let mut req_stream = LifecycleRequestStream::from_channel(async_x); info!("Awaiting request to close..."); while let Some(request) = req_stream.try_next().await.expect("Failure receiving lifecycle FIDL message") { match request { LifecycleRequest::Stop { control_handle: c } => { info!("Received request to stop. Shutting down."); c.shutdown(); process::exit(0); } } } // We only arrive here if the lifecycle channel closed without // first sending the shutdown event, which is unexpected. process::abort(); } None => { // We did not receive a lifecycle channel, exit abnormally. error!("No lifecycle channel received, exiting."); process::abort(); } } }
C++
#include <fuchsia/process/lifecycle/cpp/fidl.h> // ... // Implementation of the fuchsia.process.lifecycle FIDL protocol class LifecycleHandler : public fuchsia::process::lifecycle::Lifecycle { public: explicit LifecycleHandler(async::Loop* loop) : loop_(loop) { // Get the PA_LIFECYCLE handle, and instantiate the channel with it zx::channel channel = zx::channel(zx_take_startup_handle(PA_LIFECYCLE)); // Bind to the channel and start listening for events bindings_.AddBinding( this, fidl::InterfaceRequest<fuchsia::process::lifecycle::Lifecycle>(std::move(channel)), loop_->dispatcher()); FX_LOGS(INFO) << "Lifecycle channel received."; } // This is the Stop event we must override - see the pure virtual function we // need to override at the declaration of fuchsia::process::lifecycle::Lifecycle void Stop() override { FX_LOGS(INFO) << "Received request to stop. Shutting down."; // Shut down our loop - it's important to call Shutdown() here vs. Quit() loop_->Shutdown(); // Close the binding bindings_.CloseAll(); } private: async::Loop* loop_; fidl::BindingSet<fuchsia::process::lifecycle::Lifecycle> bindings_; };
More information about the Lifecycle protocol is available in the ELF runner documentation.
Developer tools plugins
Many ffx
plugins depend on FIDL protocols provided by
components. This dependency is expressed by declaring a
component selector in the plugin's ffx_plugin
macro,
such as core/appmgr:out:fuchsia.update.channelcontrol.ChannelControl
.
Selectors are dependent on the component's [moniker][moniker], which describes
its place in the
component instance tree
.
If there are ffx
plugins that depend on capabilities provided by your component,
you need to migrate those selectors using Remote Control Service (RCS)
proxy selector maps.
To migrate the ffx
plugin selectors for your component, do the following:
Add an entry to //src/developer/remote-control/data/selector-maps.json
mapping
the v1 component's moniker under appmgr
to the new v2 component's moniker:
{
...
"core/appmgr:out:fuchsia.fonts.Provider": "core/font_provider:expose:fuchsia.fonts.Provider"
}
This mapping overrides the code written in the ffx_plugin
macro declarations,
and it should only remain in place long enough to verify that the component
migration has successfully landed. Otherwise, it may cause confusion for future
contributors.
Once the migration is complete and the v1 component is no longer present in any
release branches, consider removing the mapping from RCS, and updating the
ffx
plugin selectors to reference the v2 component directly.
What's next
Explore the following sections for additional migration guidance on specific features your components may support: