本頁說明為 ffx
建立外掛程式的基本步驟。
外掛程式系統會搭配使用 GN 建構規則和 Rust 屬性,將外掛程式程式碼與 ffx
內部元件分離。
GN 建立規則
使用專案 BUILD.gn
檔案中的 ffx_plugin()
建構規則範本,為外掛程式建立建構目標。
您的 BUILD.gn
檔案應類似以下範例:
import("//src/developer/ffx/build/ffx_plugin.gni")
ffx_plugin("ffx_example") {
version = "0.1.0"
edition = "2021"
with_unit_tests = true
deps = []
args_sources = [
"src/args.rs",
]
sources = [
"src/lib.rs",
]
}
在 src/
目錄中,專案應包含兩個來源檔案:
src/args.rs
:定義外掛程式的 CLI 參數。src/lib.rs
:包含主要外掛程式的原始碼實作。
引數
建立包含外掛程式支援引數的檔案 src/args.rs
:
use {argh::FromArgs, ffx_core::ffx_command};
#[ffx_command()]
#[derive(FromArgs, Debug, PartialEq)]
#[argh(subcommand, name = "example", description = "an example")]
pub struct ExampleCommand {}
這會使用 argh Crate,這裡提供了更多說明文件。這個結構是透過 ffx_command
屬性裝飾,表示當使用者輸入下列指令時,外掛程式應執行:
fx ffx example
如要為外掛程式新增更多參數,請將參數新增至此結構。
範例參數看起來會像這樣:
use {argh::FromArgs, ffx_core::ffx_command};
#[ffx_command()]
#[derive(FromArgs, Debug, PartialEq)]
#[argh(subcommand, name = "example", description = "an example")]
pub struct ExampleCommand {
#[argh(positional)]
/// example optional positional string parameter
pub example: Option<String>,
}
查看更多說明文件: - Argh
外掛程式
建立包含外掛程式實作的檔案 src/lib.rs
:
use {
anyhow::Result,
ffx_core::ffx_plugin,
ffx_example_args::ExampleCommand,
};
#[ffx_plugin()]
pub async fn example(_cmd: ExampleCommand) -> Result<()> {
println!("Hello from the example plugin :)");
Ok(())
}
外掛程式方法必須接受在 src/args.rs
檔案中建立的 argh 指令做為參數,即使這些指令並未使用亦然。
整合
將外掛程式程式庫新增為 ffx
的依附元件,將其納入建構作業中。編輯 ffx
建構目標中的 plugin_deps
陣列,將 ffx_plugin()
目標新增至頂層:
plugin_deps = [
"//path/to/your/plugin/dir:ffx_example",
...
]
如要建構及測試外掛程式,請建構 ffx
:
fx build ffx
現在執行範例指令時,應該會看到輸出內容:
$ fx ffx example
Hello from the example plugin :)
單元測試
如要對外掛程式進行單元測試,只要按照在主機上測試 rust 程式碼的標準方法操作即可。當 with_unit_tests
參數設為 true
時,ffx_plugin()
GN 範本會為單元測試產生 <target_name>_lib_test
程式庫目標。
如果您的 lib.rs
包含測試,則可使用 fx test
叫用:
fx test ffx_example_lib_test
如果 fx 測試找不到您的測試,請檢查產品設定是否包含測試內容。您可以使用下列指令納入所有 ffx 測試:
fx set ... --with=//src/developer/ffx:tests
FIDL 通訊協定
FFX 外掛程式可以透過 Overnet 使用 FIDL 通訊協定與目標裝置進行通訊。如要從外掛程式存取 FIDL 通訊協定,請按照本節的說明操作。
將 FIDL Rust 繫結新增為外掛程式
BUILD.gn
檔案的依附元件。以下範例會為fuchsia.device
FIDL 程式庫新增繫結:import("//src/developer/ffx/build/ffx_plugin.gni") ffx_plugin("ffx_example") { version = "0.1.0" edition = "2021" with_unit_tests = true deps = [ "//sdk/fidl/fuchsia.device:fuchsia.device_rust", ] args_sources = [ "src/args.rs", ] sources = [ "src/lib.rs", ] }
在外掛程式實作中匯入必要的繫結。以下範例會從
fuchsia.device
匯入NameProviderProxy
:use { anyhow::Result, ffx_core::ffx_plugin, ffx_example_args::ExampleCommand, fidl_fuchsia_device::NameProviderProxy, };
您可以在外掛程式實作中使用 FIDL Proxy。外掛程式可接受參數清單中的 Proxy:
pub async fn example( name_proxy: NameProviderProxy, _cmd: ExampleCommand, ) -> Result<()> { }
將 Proxy 類型對應至元件選取器,這個元件代表在
ffx_plugin()
註解中提供 FIDL 通訊協定的元件:#[ffx_plugin( NameProviderProxy = "bootstrap/device_name_provider:out:fuchsia.device.NameProvider" )]
src/lib.rs
中的外掛程式實作範例現在應如下所示:
use {
anyhow::Result,
ffx_core::ffx_plugin,
ffx_example_args::ExampleCommand,
fidl_fuchsia_device::NameProviderProxy,
};
#[ffx_plugin(
NameProviderProxy = "bootstrap/device_name_provider:out:fuchsia.device.NameProvider"
)]
pub async fn example(
name_proxy: NameProviderProxy,
_cmd: ExampleCommand,
) -> Result<()> {
if let Ok(name) = name_proxy.get_device_name().await? {
println!("Hello, {}", name);
}
Ok(())
}
如要將其他 FIDL Proxy 加入 ffx
外掛程式,請重複上述步驟。
下列 FIDL Proxy 內建於 ffx
,不需要其他依附元件或對應:
只要將上述 Proxy 新增至外掛程式的參數清單,即可在實作中存取這些 Proxy。
Proxy 路徑名稱地圖
如果路徑名稱代表特定 FIDL Proxy 變更,ffx
和遠端控制服務 (RCS) 提供了一種機制,用於維持與 ffx
外掛程式所用現有項目的相容性。例如:
- FIDL Proxy 是由新元件提供
- FIDL 通訊協定名稱已變更
- 不同產品版本的代言詞
RCS 支援使用單複數形式地圖,覆寫 ffx
外掛程式來源中定義的警告器,並將其對應至其他值。如要覆寫特定路徑名稱,請以下列格式在 //src/developer/remote-control/data/moniker-map.json
中新增項目:
{
...
"original/moniker:out:fuchsia.MyService": "some/new/moniker:expose:fuchsia.MyOtherService"
}
這個範例可讓 RCS 覆寫 ffx
外掛程式中 original/moniker:out:fuchsia.MyService
的參照,並將參照轉送至任何包含對應項目的建構中的 some/new/moniker:expose:fuchsia.MyOtherService
。