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.

Plugins have access to the entire argh structure. For example, the config plugin needs access to the "--config" flag which is part of the ffx_args library:

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

This means that the final argh structure generated needs to be supplied to these plugins. This is why there are two libraries generated by the ffx_plugin template:

  • <target_name>_args: Contains the parsed arguments provided to the CLI.
  • <target_name>_args_test: Contains any unit tests generated by the _args library when args_with_unit_tests is set to true.

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 <target_name>_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<()> {
    <Your method name>(<Your parameter names>).await
}