Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18n(zh-cn): Translate develop/sidecar.mdx #2458

Merged
merged 11 commits into from
Aug 2, 2024
199 changes: 199 additions & 0 deletions src/content/docs/zh-cn/develop/sidecar.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
---
title: 嵌入外部二进制文件
sidebar:
order: 1
i18nReady: true
---

您可能需要嵌入外部二进制文件来为应用程序添加额外的功能,或者防止用户安装其他依赖项(例如 Node.js 或 Python)。我们将这个二进制文件称为 `sidecar`。

二进制文件是用任何编程语言编写的可执行文件。常见的用例是使用 `pyinstaller` 捆绑的 Python CLI 应用程序或 API 服务器。

要捆绑您选择的二进制文件,您可以在 `tauri.conf.json` 中的 `tauri > bundle` 对象中添加 `externalBin` 属性。
`externalBin` 期望一个字符串列表,用于定位具有绝对或相对路径的二进制文件。

下面是一个示例来说明配置。这不是一个完整的 `tauri.conf.json` 文件。

```json title="src-tauri/tauri.conf.json"
{
"bundle": {
"externalBin": [
"/absolute/path/to/sidecar",
"relative/path/to/binary",
"binaries/my-sidecar"
]
}
}
```

:::note
相对路径是相对于 `tauri.conf.json` 文件的,该文件位于 `src-tauri` 目录中。因此,`binaries/my-sidecar` 表示的是 `<项目根目录>/src-tauri/binaries/my-sidecar`。
:::

为了使外部二进制文件在每个支持的架构上工作,指定路径上必须存在一个具有相同名称和 `-$TARGET_TRIPLE` 后缀的二进制文件。例如,"externalBin": ["binaries/my-sidecar"] 需要在Linux上有一个名为 `src-tauri/binaries/my-sidecar-x86_64-unknown-linux-gnu` 的可执行文件,或者在 Mac OS with Apple Silicon 上有一个名为 `src-tauri/binaries/my-sidecar-aarch64-apple-darwin` 的可执行文件。

你可以通过查看 `rustc -Vv` 命令报告的 `host:` 属性来找到当前平台的 `-$TARGET_TRIPLE` 后缀。

如果大多数 Unix 系统都有 `grep` 和 `cut` 命令,则可以使用以下命令直接提取 `$TARGET_TRIPLE`。

```shell
rustc -Vv | grep host | cut -f2 -d' '
```

在 Windows 上,你可以使用 PowerShell 代替。

```powershell
rustc -Vv | Select-String "host:" | ForEach-Object {$_.Line.split(" ")[1]}
```

下面是一个将 `$TARGET_TRIPLE` 追加到二进制文件的 Node.js 脚本:

```javascript
const execa = require('execa');
const fs = require('fs');

let extension = '';
if (process.platform === 'win32') {
extension = '.exe';
}

async function main() {
const rustInfo = (await execa('rustc', ['-vV'])).stdout;
const targetTriple = /host: (\S+)/g.exec(rustInfo)[1];
if (!targetTriple) {
console.error('Failed to determine platform target triple');
}
fs.renameSync(
`src-tauri/binaries/sidecar${extension}`,
`src-tauri/binaries/sidecar-${targetTriple}${extension}`
);
}

main().catch((e) => {
throw e;
});
```

注意,如果编译的体系结构与运行的体系结构不同,这个脚本将无法工作。

## 从 Rust 运行

在 Rust 端, 导入 `tauri_plugin_shell::ShellExt` 特征 并在AppHandle上调用 `shell().sidecar()` 函数。

```rust
use tauri_plugin_shell::ShellExt;
use tauri_plugin_shell::process::CommandEvent;

// `sidecar()` 只需要文件名, 不像 JavaScript 中的整个路径
let sidecar_command = app.shell().sidecar("my-sidecar").unwrap();
let (mut rx, mut _child) = sidecar_command
.spawn()
.expect("Failed to spawn sidecar");

tauri::async_runtime::spawn(async move {
// 读取诸如stdout之类的事件
while let Some(event) = rx.recv().await {
if let CommandEvent::Stdout(line) = event {
window
.emit("message", Some(format!("'{}'", line)))
.expect("failed to emit event");
// 写入标准输入
child.write("message from Rust\n".as_bytes()).unwrap();
}
}
});
```

您可以将此代码放在 Tauri 命令中,以便轻松传递 AppHandle,或者您可以在构建脚本中存储对 AppHandle 的引用,以便在应用程序的其他位置访问它。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
您可以将此代码放在 Tauri 命令中,以便轻松传递 AppHandle,或者您可以在构建脚本中存储对 AppHandle 的引用,以便在应用程序的其他位置访问它。
您可以将此代码放在 Tauri 命令中,以便轻松传递 `AppHandle`,或者您可以在构建脚本中存储对 `AppHandle` 的引用,以便在应用程序的其他位置访问它。

Missing backquote.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
The original text has no backquote.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be consistent with the original text? @Embers-of-the-Fire


## 从 JavaScript 运行

在 JavaScript 代码中,从 `@tauri-apps/plugin-shell` 模块中导入 `Command` 类,并使用其静态方法 `sidecar`。

```javascript
import { Command } from '@tauri-apps/plugin-shell';
// `binaries/my-sidecar` 是在 `tauri.conf.json > tauri > bundle > externalBin` 指定的确切值。
const sidecar_command = Command.sidecar('binaries/my-sidecar');
const output = await sidecar_command.execute();
```

## 传递参数

你可以像运行普通的 `Command` 一样向 Sidecar 命令传递参数。

参数可以是**静态的**(例如 `-o` 或 `serve`)或者**动态的**(例如 `<file_path>` 或者 `localhost:<PORT>`)。
你按照调用它们的确切顺序来定义这些参数。静态参数保持不变,而动态参数可以使用正则表达式来定义。

首先,在 `src-tauri/capabilities/main.json` 中定义需要传递给 sidecar 命令的参数。

```json title="src-tauri/capabilities/main.json" ins={14-31}
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"path:default",
"event:default",
"window:default",
"app:default",
"resources:default",
"menu:default",
"tray:default",
{
"identifier": "shell:allow-execute",
"allow": [
{
"args": [
"arg1",
"-a",
"--arg2",
{
"validator": "\\S+"
}
],
"cmd": "",
"name": "binaries/my-sidecar",
"sidecar": true
}
]
},
"shell:allow-open"
]
}
```

:::note
如果你正在从 Tauri v1 迁移,Tauri v2 CLI 中的 `migrate` 命令应该会为你处理这个问题。阅读[自动迁移](/start/migrate/from-tauri-1/#automated-migration)了解更多信息。
:::

然后,要调用 sidecar 命令,只需将**所有**参数作为数组传入即可。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
然后,要调用 sidecar 命令,只需将**所有**参数作为数组传入即可。
然后,要调用 `sidecar` 命令,只需将**所有**参数作为数组传入即可。

Missing backquote.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original text has no backquote.
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be consistent with the original text? @Embers-of-the-Fire

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's okay with or without, let's be in sync for now and then change it when the source material updates.


在 Rust 中:

```rust
use tauri_plugin_shell::ShellExt;
#[tauri::command]
async fn call_my_sidecar(app: tauri::AppHandle) {
let sidecar_command = app.shell()
.sidecar("my-sidecar")
.unwrap()
.args(["arg1", "-a", "--arg2", "any-string-that-matches-the-validator"]);
let (mut _rx, mut _child) = sidecar_command.spawn().unwrap();
}
```

在 JavaScript 中:

```javascript
import { Command } from '@tauri-apps/plugin-shell';
// `binaries/my-sidecar` 是在 `tauri.conf.json > tauri > bundle > externalBin` 指定的确切值。
// 请注意 args 数组需要与 `tauri.conf.json` 中指定的需完全匹配
const command = Command.sidecar('binaries/my-sidecar', [
'arg1',
'-a',
'--arg2',
'any-string-that-matches-the-validator',
]);
const output = await command.execute();
```
Loading