Sessions are regular components that the session_manager can launch at
startup. This means that creating a session component follows all of the same
steps as creating any other component. This document discusses creating an
example session that launches at startup and prints "Hello World!" to the system
log.
Create the directory structure
Components require a specific directory structure. The fx tool provides a
generator that creates this structure for you. It takes the name of the
component and the language you want to use as arguments. For example, this
component is called hello-world-session and is written in Rust.
Run the following command to create the directory structure for this example:
fx create component --path hello-world-session --lang rustThis command creates the following directory structure with a template for a component offering a service:
hello-world-session
|- meta
| |- hello-world-session.cml
|
|- src
| |- main.rs
|
|- BUILD.gn
Create a component manifest
The component manifest file (hello-world-session.cml) declares the component
to Fuchsia. For this example, the default manifest is sufficient but take a
moment to explore the following lines of code from hello-world-session.cml:
The file starts by including other cml files if needed.
include: [ "inspect/client.shard.cml", "syslog/client.shard.cml", ],This
includekey lets the session component use thefuchsia.logger.LogSinkcapability so that it can print to the system log.Next is the
programblock.// Information about the program to run. program: { // Use the built-in ELF runner to run native binaries. runner: "elf", // The binary to run for this component. binary: "bin/hello-world-session", },The
programblock tells thecomponent_managerwhere the binary for the session component can be found. Therunnerkey tells thecomponent_managerthat is should run the component binary using the ELF runner.Finally the component manifest describes additional capabilities that the component can
use,offer, orexpose.// Capabilities used by this component. use: [ // List your component's dependencies here, ex: // { protocol: "fuchsia.net.name.Lookup" } ], expose: [ // session_manager uses this protocol to start the session. { protocol: "fuchsia.component.Binder", from: "framework", }, ],
Writing a session in Rust
Now you can write the implementation for the session component. Inside the
src/main.rs file that was generated there is a lot of code that isn't needed
for this example.
Replace the contents of src/main.rs with the following code:
use anyhow::Error;
/// Creates a simple session that just prints "Hello World" to the syslog.
#[fuchsia::main(logging = true)]
async fn main() -> Result<(), Error> {
log::info!("Hello World!");
Ok(())
}
This code initializes the system log and then prints "Hello World!".
log::info! is a macro that prints to the log with a level of info.
There are similar macros for error and warn.
Writing the BUILD.gn
The last file to modify is the BUILD.gn. This tells the compiler how to build
the session component.
Rust binary
The next section describes the actual Rust binary. It tells the compiler what the name of the binary should be, that it includes unit tests, what dependencies it has, and where its source is located. For this example, the default set of dependencies are sufficient:
rustc_binary("bin") {
edition = "2021"
output_name = "hello-world-session"
# Generates a GN target for unit-tests with the label `bin_test`, and
# a binary named `hello_world_session_bin_test`.
with_unit_tests = true
deps = [
"//src/lib/fuchsia",
"//third_party/rust_crates:anyhow",
"//third_party/rust_crates:log",
]
sources = [ "src/main.rs" ]
}
The fuchsia_component() and fuchsia_package() templates tell Fuchsia more
about the component including what it is called, where to find the manifest,
and what dependencies the package and component have:
fuchsia_component("component") {
component_name = "hello-world-session"
manifest = "meta/hello-world-session.cml"
deps = [ ":bin" ]
}
fuchsia_package("hello-world-session") {
deps = [ ":component" ]
}
Identify the session URL
session_manager needs to know to which session component to launch at startup,
and is configured by providing the component URL of the session.
Component URLs follow the format:
fuchsia-pkg://fuchsia.com/package_name#meta/component_name.cmNotice that the path points to a .cm file. .cm files are compiled versions
of .cml files that are generated when fx build is run. So, in this case, the
component URL is:
fuchsia-pkg://fuchsia.com/hello-world-session#meta/hello-world-session.cm
Building the session
To build the session //local/BUILD.gn must first be used to override
assembly configuration values so that session_manager, your session
component, and the session config are included in the base package set.
This is done using the assembly_developer_overrides template.
import("//build/assembly/developer_overrides.gni")
assembly_developer_overrides("custom_session") {
base_packages = [
"//path/to/your/session"
]
platform = {
session = {
enabled = true
}
}
product = {
session = {
url = "fuchsia-pkg://fuchsia.com/pkg-name#meta/your_session.cm"
}
}
}
The fx set command must then be used to include the custom session
configurations in the build.
fx set minimal.x64 --assembly-override=//local:<var>custom_session</var>If you are using the example project from the //src/session/examples directory,
the assembly_developer_overrides would be:
assembly_developer_overrides("hello-world-session") {
platform = {
session = {
enabled = true
}
}
product = {
session = {
url = "fuchsia-pkg://fuchsia.com/hello-world-session#meta/hello-world-session.cm"
}
}
}
And include the build target in your fx set arguments:
fx set minimal.x64 --assembly-override=//local:hello-world-session
Once that's done and built session_manager should automatically start your
session on boot. You should see the "Hello" message in the system log.
$ ffx log --filter hello
[session_manager] INFO: Launching session: fuchsia-pkg://fuchsia.com/hello-world-session#meta/hello-world-session.cm
[hello_world_session] INFO: Hello World!