Caution: Structured configuration is an experimental, allowlisted feature. Its behavior and APIs are subject to change. The allowlist will be removed when the feature does not require active guidance from the Component Framework team. Follow this bug for updates. If you encounter bugs, please file them against our Monorail component!
Structured configuration allows C++/Rust components to declare configuration schemas directly in their manifest. Benefits of using structured configuration include:
ffx
tooling.To use structured configuration in your component, you must update build rules, declare a schema, define values, and generate a client library.
To prevent cyclic dependencies when generating client libraries, define a fuchsia_component_manifest
rule that compiles the component manifest. Add structured_config
as a restricted feature for this manifest. Pass this compiled manifest GN label into the fuchsia_component
rule.
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/BUILD.gn" region_tag="component" adjust_indentation="auto" %}
Because structured config is an experimental feature, these GN build rules must be added to the allowlist in //tools/cmc/build/restricted_features/BUILD.gn
You must declare a configuration schema in a component's manifest. Structured config supports booleans, integers, strings and vectors of these types. The CML reference doc describes the complete syntax for a config schema.
{ ... {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/meta/config_example.cml" region_tag="config" %} }
You must define configuration values for a component's schema. The fuchsia_structured_config_values
GN template validates the defined values against the config schema and compiles them into a .cvf
file that must be packaged with your component.
There are two ways to define config values: in a JSON5 file or inline in GN.
You can write a component's configuration values in a JSON5 file. Because JSON5 is a strict superset of JSON, existing JSON configuration files can also be reused for structured config.
Each key in the JSON object must correspond to a config key in the schema and the value must be of a compatible JSON type:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/config_example_default_values.json5" adjust_indentation="auto" %}
Provide the path to the JSON5 file in a fuchsia_structured_config_values
rule.
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/BUILD.gn" region_tag="config_values_json" adjust_indentation="auto" %}
The fuchsia_structured_config_values
template also supports defining configuration values inline:
{C++}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/BUILD.gn" region_tag="args_declare" adjust_indentation="auto" %} {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/BUILD.gn" region_tag="config_values_gn" adjust_indentation="auto" %}
{Rust}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/BUILD.gn" region_tag="args_declare" adjust_indentation="auto" %} {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/BUILD.gn" region_tag="config_values_gn" adjust_indentation="auto" %}
By using declare_args
, you can change configuration values on the command line at build time:
{C++}
$ fx set core.qemu-x64 \ --with //examples/components/config \ --args='config_example_cpp_greeting="C++ CLI Override"'
{Rust}
$ fx set core.qemu-x64 \ --with //examples/components/config \ --args='config_example_rust_greeting="Rust CLI Override"'
To package a component and a set of values together, add the fuchsia_component
and fuchsia_structured_config_values
rules as dependencies of a fuchsia_package
.
{C++}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/BUILD.gn" region_tag="package" adjust_indentation="auto" %}
{Rust}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/BUILD.gn" region_tag="package" adjust_indentation="auto" %}
The build system verifies your component's configuration schema and value file. A component with a faulty configuration (for example: field mismatch, bad constraints, missing value file) will fail to build.
Component manager validates a component's configuration when the component is resolved.
Use ffx component show
to print out a components configuration key-value pairs. The component does not have to be running for this to work.
$ ffx component show config_example Moniker: /core/ffx-laboratory:config_example Component State: Resolved ... Configuration: greeting -> "World" ...
Components read their resolved configuration values with a generated library. Generate a library using the following build templates:
{C++}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/BUILD.gn" region_tag="binary" adjust_indentation="auto" %} {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/BUILD.gn" region_tag="library" adjust_indentation="auto" %}
{Rust}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/BUILD.gn" region_tag="binary" adjust_indentation="auto" %} {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/BUILD.gn" region_tag="library" adjust_indentation="auto" %}
Use the following functions from the library to read configuration values:
{C++}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/main.cc" region_tag="imports" adjust_indentation="auto" %} ... {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/main.cc" region_tag="get_config" adjust_indentation="auto" %}
{Rust}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/src/main.rs" region_tag="imports" adjust_indentation="auto" %} ... {% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/src/main.rs" region_tag="get_config" adjust_indentation="auto" %}
You can export a components configuration to Inspect so that it is available in crash reports. The client libraries have functions to export a component's configuration to an Inspect tree:
{C++}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/cpp/main.cc" region_tag="inspect" adjust_indentation="auto" %}
{Rust}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/rust/src/main.rs" region_tag="inspect" adjust_indentation="auto" %}
Use ffx inspect show
to print out the component's exported configuration:
$ ffx inspect show core/ffx-laboratory\*config_example core/ffx-laboratory\:config_example: ... payload: root: config: greeting = World
You can use Realm Builder to dynamically replace the configuration values of a component.
{C++}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/integration_test/cpp/test.cc" region_tag="config_replace" adjust_indentation="auto" %}
{Rust}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/components/config/integration_test/rust/lib.rs" region_tag="config_replace" adjust_indentation="auto" %}
Realm Builder validates the replaced value against the component's configuration schema.