Advanced Plugin Internals

This page is intended for developers who want to understand FFX's plugin system better. FFX is built on top of the argh crate. This crate imposes the Google standard for CLI parameters. The structure that argh expects to define the CLI parameters is required at compile time. Therefore, this rules out any runtime plugin systems as Rust structs cannot be edited after compile time.

It also means that any dynamic ability to add plugins must come before compile time. To accomplish this, FFX uses GN build rules to generate the final argh structure from the supplied plugin dependencies. You can see that code here.

Internal libraries to FFX require access to top level CLI flags and parameters. For example, the config library needs access to the “--config” flag:

$fx ffx --config "config-test=runtime" config get --name config-test

These internal libraries are available for use in the plugins. For example, the config library supplies configuration management for plugins. More about that can be read on the config page.

This means that the final argh structure generated needs to be supplied to these internal libraries. And in turn, the config libraries need to be supplied to the plugins.

This is why there are two libraries generated by the ffx_plugin template.

The Rust attributes that developers decorate their code with generates some code at compile time as well.

The “ffx_command” attribute just creates the following code in the “_args” library:

pub type FfxPluginCommand = <Your Command>;

This provides a known entry point into this library that can used by FFX while allowing the developer to name their command whatever they want.

The “ffx_plugin” attribute does something similar.

pub async fn ffx_plugin_impl(<Your methods inputs>) -> Result<(), Error> {
    <Your method name>(<Your parameter names>).await
}

The ffx_plugin template requires enough dependencies to allow for the code generated via the Rust attributes to compile. Therefore the ffx_plugin template gets the following dependencies for free:

  • //sdk/fidl/fuchsia.developer.remotecontrol:fuchsia.developer.remotecontrol-rustc
  • //src/connectivity/overnet/lib/hoist
  • //src/developer/ffx/core:lib
  • //src/developer/ffx:command_lib
  • //src/developer/ffx/config:lib
  • //src/lib/fidl/rust/fidl
  • //third_party/rust_crates:anyhow
  • "//third_party/rust_crates:argh
  • "//third_party/rust_crates:futures
  • "//third_party/rust_crates:log