Skip to content

Commit 2da0e2f

Browse files
committed
feat: tinymist を sidecar として同梱 + ARM Linux マトリクス追加
PATH に tinymist がない端末では LSP 起動に失敗していたため、tinymist v0.14.16 を Tauri externalBin で main binary の隣に同梱する。 .deb は 24.5 → 53 MB に増えるが、エンドユーザの追加セットアップを不要に する効果と引き換え。 - tauri.conf.json: bundle.externalBin に binaries/tinymist を追加 - src/lib.rs: tinymist_path() / host_target_triple() ヘルパ追加し、 preview / compile / lsp の 3 箇所の Command::new("tinymist") を 解決済みパス渡しに変更。dev では binaries/tinymist-<host-triple> を 参照し、いずれも見つからない場合は PATH にフォールバック。 - scripts/fetch-tinymist.sh: GitHub Releases からホストの triple 用 バイナリを冪等に DL する shell スクリプト。TINYMIST_TARGET / TINYMIST_VERSION で上書き可。 - .github/workflows/release.yml: マトリクス各行に tinymist DL step を 追加。macOS は universal-apple-darwin 用に x86_64 / aarch64 を両方 DL し lipo で合成。ARM Linux (ubuntu-22.04-arm) も同マトリクスに追加。 - .gitignore: app/src-tauri/binaries/ を ignore(数十 MB バイナリは git に入れない)
1 parent 6970b0e commit 2da0e2f

8 files changed

Lines changed: 245 additions & 9 deletions

File tree

.github/workflows/release.yml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ jobs:
2525
include:
2626
- platform: ubuntu-22.04
2727
args: ""
28+
# ARM Linux(aarch64)対応。Apple Silicon の Linux VM /
29+
# Raspberry Pi / クラウド ARM サーバ向け。GitHub の public リポは
30+
# 無料で arm64 ランナーが使える。
31+
- platform: ubuntu-22.04-arm
32+
args: ""
2833
- platform: windows-latest
2934
args: ""
3035
# macOS は alpha 段階では配布対象外(README 参照)。CI ビルドが
@@ -67,7 +72,7 @@ jobs:
6772
workspaces: app/src-tauri -> target
6873

6974
- name: Install Linux build deps
70-
if: matrix.platform == 'ubuntu-22.04'
75+
if: startsWith(matrix.platform, 'ubuntu-22.04')
7176
run: |
7277
sudo apt-get update
7378
sudo apt-get install -y \
@@ -82,6 +87,41 @@ jobs:
8287
run: pnpm install --frozen-lockfile
8388
working-directory: app
8489

90+
# tinymist sidecar を target triple ごとに DL。tauri-action が
91+
# bundle.externalBin の実体検証をするため、tauri-action 実行前に
92+
# `app/src-tauri/binaries/tinymist-<triple>` を用意しておく必要がある。
93+
- name: Fetch tinymist (Linux x86_64)
94+
if: matrix.platform == 'ubuntu-22.04'
95+
run: ./scripts/fetch-tinymist.sh
96+
env:
97+
TINYMIST_TARGET: x86_64-unknown-linux-gnu
98+
99+
- name: Fetch tinymist (Linux aarch64)
100+
if: matrix.platform == 'ubuntu-22.04-arm'
101+
run: ./scripts/fetch-tinymist.sh
102+
env:
103+
TINYMIST_TARGET: aarch64-unknown-linux-gnu
104+
105+
- name: Fetch tinymist (Windows x86_64)
106+
if: matrix.platform == 'windows-latest'
107+
shell: bash
108+
run: ./scripts/fetch-tinymist.sh
109+
env:
110+
TINYMIST_TARGET: x86_64-pc-windows-msvc
111+
112+
# macOS は universal-apple-darwin で build するので、x86_64 / aarch64 の
113+
# 両方を DL し lipo で universal バイナリを合成する。
114+
- name: Fetch tinymist (macOS universal)
115+
if: matrix.platform == 'macos-latest'
116+
run: |
117+
TINYMIST_TARGET=aarch64-apple-darwin ./scripts/fetch-tinymist.sh
118+
TINYMIST_TARGET=x86_64-apple-darwin ./scripts/fetch-tinymist.sh
119+
lipo -create \
120+
app/src-tauri/binaries/tinymist-x86_64-apple-darwin \
121+
app/src-tauri/binaries/tinymist-aarch64-apple-darwin \
122+
-output app/src-tauri/binaries/tinymist-universal-apple-darwin
123+
chmod +x app/src-tauri/binaries/tinymist-universal-apple-darwin
124+
85125
- name: Build & upload (tauri-action)
86126
# tag push 時のみ Release に upload。手動トリガーや push (tag 以外)
87127
# では tag-name を空にすると tauri-action が build only で抜ける

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ node_modules/
1414
# Tauri (生成物)
1515
/app/src-tauri/gen/
1616

17+
# Tauri sidecar binaries(scripts/fetch-tinymist.sh が DL する)
18+
# ビルド時に fetch するので git には含めない(数十 MB の binary をコミットしない)
19+
/app/src-tauri/binaries/
20+
1721
# Editor / OS
1822
.DS_Store
1923
.vscode/*

PROGRESS.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,3 +687,21 @@ Typstudio fork 路線 vs ゼロスタート路線の判断材料を集め、技
687687
- テンプレ取り込み(`typst init @preview/<name>`)は **UI 未実装**。同梱テンプレ(`app/src/lib/templates/<id>/`)のみ起動ダイアログから選択可能
688688
- **判断**:Universe テンプレ取り込み UI は **Phase 2 で扱う**(Phase 1 Sprint 3 では同梱テンプレのみ)。Phase 2 の「パッケージ管理 UI」項目を Universe 連携 UI として具体化(取り込み / 閲覧 / キャッシュ可視化の 3 機能)
689689
-:Sprint 3 の残タスクに戻る(フォーム型テンプレ簡素版 / ツールバー D&D 編集 UI / キーバインド設定 UI など)
690+
691+
### 2026-05-06: tinymist を sidecar として同梱(PATH 依存解消)
692+
- **発端**(氏報告):GUI 起動の Yuhitsu で「LSP 起動に失敗」エラー。原因は GNOME がアプリを spawn するときの PATH に `~/.local/bin` が含まれず `tinymist` が見つからない為。一般 Linux ユーザは大抵 tinymist 未インストールなので、配布物としても致命的
693+
- **当初の構想**:.deb の Depends:、起動時検出 + GUI 案内、wrapper script、sidecar 同梱の 4 案を比較
694+
- **氏判断**:**sidecar 同梱(Tauri externalBin)を Phase 1 中に対応**。配布の前提条件として外せない。サイズ増(deb で 24.5MB → 53MB、+28MB)は許容
695+
- **設計**:
696+
- tinymist v0.14.16(最新安定)で固定。`tauri.conf.json``bundle.externalBin: ["binaries/tinymist"]` を追加し、Tauri が target triple サフィクスを剥がして main binary の隣に配置するよう設定
697+
- Rust 側に `tinymist_path()` ヘルパを追加(`lib.rs`)。解決順は:(1) 実行ファイルの隣 = リリース配置、(2) `<CARGO_MANIFEST_DIR>/binaries/tinymist-<host-triple>` = dev 配置、(3) PATH = フォールバック。`Command::new("tinymist")` の 3 箇所(preview / compile / lsp)を `Command::new(tinymist_path())` に置換
698+
- `host_target_triple()` は cfg! で静的に決定(クロスコンパイル対応)
699+
- `scripts/fetch-tinymist.sh`:GitHub Releases から host triple のバイナリを DL して `app/src-tauri/binaries/tinymist-<triple>` に配置。冪等。`TINYMIST_TARGET` / `TINYMIST_VERSION` 環境変数で上書き可
700+
- `.gitignore``binaries/` を追加(数十 MB の binary をコミットしない)
701+
- **CI 対応**(`release.yml`):tauri-action の前にマトリクス各行で `fetch-tinymist.sh` を呼ぶ step を追加。Linux x86_64 / Linux aarch64 / Windows は単純呼び出し。macOS は universal-apple-darwin で build するので x86_64 / aarch64 の両方を DL し `lipo` で universal バイナリを合成
702+
- **動作確認**:
703+
- `pnpm tauri build --bundles deb` 通過、生成された .deb 内に `/usr/bin/tinymist` が同梱されることを確認(53MB)
704+
- 段階 1 テスト(release バイナリ直接起動)で LSP / preview / 漢字変換すべて動作 ✓
705+
- 段階 2(.desktop 経由 GUI 起動)と 段階 3(.deb 実機インストール)は氏に確認依頼中
706+
- **README 更新**:「tinymist を PATH に通せ」の前提を撤去、`scripts/fetch-tinymist.sh` の手順を追記(README.md / README.en.md)
707+
- **Phase 1 残:**ARM Linux 含む実機 .deb インストール検証は氏側で実施。CI のサイズ増(macOS universal は ~120MB 程度になる見込み)が無料枠を圧迫しないかは run 後にチェック

README.en.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,26 @@ For more, open the **hamburger → Help → About Yuhitsu** dialog inside the ap
117117

118118
- [Rust](https://www.rust-lang.org/) 1.77+
119119
- [Node.js](https://nodejs.org/) 20+ + [pnpm](https://pnpm.io/) 10+
120-
- [tinymist](https://github.com/Myriad-Dreamin/tinymist) on `PATH`
121120
- Linux: `libwebkit2gtk-4.1-dev`, `libssl-dev`, `libgtk-3-dev`, etc. (Tauri's Linux build deps)
122121
- macOS: Xcode CLT
123122
- Windows: Microsoft C++ Build Tools + WebView2
124123

124+
`tinymist` is bundled as a sidecar binary, so contributors do not need to install it separately. `scripts/fetch-tinymist.sh` downloads the binary for your host target triple.
125+
125126
### Setup
126127

127128
```bash
128129
git clone --recursive https://github.com/barewalker/yuhitsu.git
129-
cd yuhitsu/app
130+
cd yuhitsu
131+
./scripts/fetch-tinymist.sh # fetch the tinymist sidecar
132+
cd app
130133
pnpm install
131134
pnpm tauri dev
132135
```
133136

134137
> ⚠️ **`--recursive` matters**: the bundled Harano Aji fonts are pulled in as a git submodule.
138+
>
139+
> 💡 **`fetch-tinymist.sh`** is idempotent (skips if already present). Override the pinned version with `TINYMIST_VERSION=v0.14.16 ./scripts/fetch-tinymist.sh`.
135140
136141
### Release build
137142

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,26 @@ sudo dpkg -i yuhitsu_*.deb
117117

118118
- [Rust](https://www.rust-lang.org/) 1.77+
119119
- [Node.js](https://nodejs.org/) 20+ + [pnpm](https://pnpm.io/) 10+
120-
- [tinymist](https://github.com/Myriad-Dreamin/tinymist)(`PATH` に通っていること)
121120
- Linux:`libwebkit2gtk-4.1-dev``libssl-dev``libgtk-3-dev` 等(Tauri の Linux ビルド前提)
122121
- macOS:Xcode CLT
123122
- Windows:Microsoft C++ Build Tools + WebView2
124123

124+
`tinymist` は Yuhitsu に sidecar として同梱されるため、開発者が個別にインストールする必要はありません(`scripts/fetch-tinymist.sh``pnpm install` 直後に target triple 用のバイナリを取得します)。
125+
125126
### セットアップ
126127

127128
```bash
128129
git clone --recursive https://github.com/barewalker/yuhitsu.git
129-
cd yuhitsu/app
130+
cd yuhitsu
131+
./scripts/fetch-tinymist.sh # tinymist sidecar を取得
132+
cd app
130133
pnpm install
131134
pnpm tauri dev
132135
```
133136

134137
> ⚠️ **`--recursive`** が重要:Harano Aji フォントを git submodule として取り込んでいるため。
138+
>
139+
> 💡 **`fetch-tinymist.sh`** は冪等(同じ binary がある場合は再 DL しない)。版数を変えたい時は `TINYMIST_VERSION=v0.14.16 ./scripts/fetch-tinymist.sh` のように環境変数で指定。
135140
136141
### リリースビルド
137142

app/src-tauri/src/lib.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::fs;
2-
use std::path::PathBuf;
2+
use std::path::{Path, PathBuf};
33
use std::process::{Child, Command, Stdio};
44
use std::sync::Mutex;
55
use std::time::Duration;
@@ -347,6 +347,68 @@ fn bundled_font_dir(app: &AppHandle) -> Option<PathBuf> {
347347
None
348348
}
349349

350+
// 同梱した tinymist sidecar バイナリの絶対パスを返す。
351+
//
352+
// 解決順:
353+
// 1. リリース: main 実行ファイルと同じディレクトリの `tinymist`(Windows は `.exe`)。
354+
// `tauri.conf.json` の `bundle.externalBin` で Tauri が target triple サフィクスを
355+
// 剥がして配置する位置。.deb なら `/usr/lib/yuhitsu/`、.msi なら exe の隣。
356+
// 2. dev: `<CARGO_MANIFEST_DIR>/binaries/tinymist-<host-triple>` を直接参照
357+
// (`scripts/fetch-tinymist.sh` が DL する)。`pnpm tauri dev` 中はこちらが使われる。
358+
// 3. 上記いずれも見つからない場合は PATH ルックアップにフォールバック。
359+
// バンドル前の旧来動作 / 開発者が手元で `cargo install tinymist` 済の救済用。
360+
fn tinymist_path() -> PathBuf {
361+
let bin_name = if cfg!(windows) { "tinymist.exe" } else { "tinymist" };
362+
363+
// 1. リリース配置
364+
if let Ok(exe) = std::env::current_exe() {
365+
if let Some(dir) = exe.parent() {
366+
let p = dir.join(bin_name);
367+
if p.exists() {
368+
return p;
369+
}
370+
}
371+
}
372+
373+
// 2. dev 配置
374+
let triple = host_target_triple();
375+
let dev_name = if cfg!(windows) {
376+
format!("tinymist-{}.exe", triple)
377+
} else {
378+
format!("tinymist-{}", triple)
379+
};
380+
let dev_path = Path::new(env!("CARGO_MANIFEST_DIR"))
381+
.join("binaries")
382+
.join(&dev_name);
383+
if dev_path.exists() {
384+
return dev_path;
385+
}
386+
387+
// 3. PATH フォールバック
388+
PathBuf::from("tinymist")
389+
}
390+
391+
// Tauri の externalBin が target triple サフィクスで管理しているため、
392+
// dev 時のサイドカー解決にホストのトリプルが必要。cfg! の組み合わせで
393+
// 静的に決定する(クロスコンパイル時もビルド対象側のトリプルになる)。
394+
fn host_target_triple() -> &'static str {
395+
if cfg!(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")) {
396+
"x86_64-unknown-linux-gnu"
397+
} else if cfg!(all(target_arch = "aarch64", target_os = "linux", target_env = "gnu")) {
398+
"aarch64-unknown-linux-gnu"
399+
} else if cfg!(all(target_arch = "x86_64", target_os = "windows", target_env = "msvc")) {
400+
"x86_64-pc-windows-msvc"
401+
} else if cfg!(all(target_arch = "aarch64", target_os = "windows", target_env = "msvc")) {
402+
"aarch64-pc-windows-msvc"
403+
} else if cfg!(all(target_arch = "aarch64", target_os = "macos")) {
404+
"aarch64-apple-darwin"
405+
} else if cfg!(all(target_arch = "x86_64", target_os = "macos")) {
406+
"x86_64-apple-darwin"
407+
} else {
408+
"unknown-target"
409+
}
410+
}
411+
350412
// Typst の `--root` に渡すプロジェクトルート。
351413
// Linux/macOS は `/`、Windows は入力パスのドライブ。tinymist は cwd を
352414
// 起点に root を相対化することがあり、cwd と root が食い違うと "entry
@@ -532,7 +594,7 @@ async fn start_preview(
532594
// ルートを root として渡す(セキュリティモデルは緩むが、ユーザ自身のファイルを
533595
// 自分のエディタで読むだけなので許容)。Windows は入力パスのドライブを起点に。
534596
let root = filesystem_root_for(&path);
535-
let mut cmd = Command::new("tinymist");
597+
let mut cmd = Command::new(tinymist_path());
536598
cmd.current_dir(&root)
537599
.args([
538600
"preview",
@@ -630,7 +692,7 @@ fn export_pdf(app: AppHandle, input: String, output: String) -> Result<(), Strin
630692
// preview と同じく filesystem ルートを `--root` に渡す。文書外の絶対パスを
631693
// 読みたい(例: ホーム配下のスクショ画像)用途に合わせる。
632694
let root = filesystem_root_for(&input);
633-
let mut cmd = Command::new("tinymist");
695+
let mut cmd = Command::new(tinymist_path());
634696
cmd.current_dir(&root)
635697
.args(["compile", "--root", &root]);
636698
if let Some(fonts) = bundled_font_dir(&app) {
@@ -680,7 +742,7 @@ impl LspState {
680742
async fn lsp_start(app: AppHandle, state: State<'_, LspState>) -> Result<(), String> {
681743
state.kill_existing().await;
682744

683-
let mut cmd = TokioCommand::new("tinymist");
745+
let mut cmd = TokioCommand::new(tinymist_path());
684746
cmd.arg("lsp");
685747
if let Some(fonts) = bundled_font_dir(&app) {
686748
cmd.args(["--font-path", &fonts.to_string_lossy()]);

app/src-tauri/tauri.conf.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"icons/icon.icns",
3838
"icons/icon.ico"
3939
],
40+
"externalBin": ["binaries/tinymist"],
4041
"resources": {
4142
"resources/HaranoAjiFonts/HaranoAjiMincho-Regular.otf": "fonts/HaranoAjiMincho-Regular.otf",
4243
"resources/HaranoAjiFonts/HaranoAjiMincho-Bold.otf": "fonts/HaranoAjiMincho-Bold.otf",

scripts/fetch-tinymist.sh

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/bin/sh
2+
# tinymist バイナリを GitHub Releases から取得して
3+
# `app/src-tauri/binaries/tinymist-<host-triple>` に配置する。
4+
#
5+
# 用途:
6+
# - dev:`pnpm tauri dev` する前に手元で 1 度走らせる
7+
# - CI:release.yml の各マトリクスで実行(target を引数 / 環境変数で渡す)
8+
#
9+
# 使い方:
10+
# ./scripts/fetch-tinymist.sh # ホストの triple を自動検出
11+
# TINYMIST_TARGET=aarch64-unknown-linux-gnu ./scripts/fetch-tinymist.sh
12+
# TINYMIST_VERSION=v0.14.16 ./scripts/fetch-tinymist.sh # version 指定
13+
#
14+
# 既に配置済なら何もしない(冪等)。
15+
16+
set -eu
17+
18+
VERSION="${TINYMIST_VERSION:-v0.14.16}"
19+
20+
# 配置先(リポジトリルートからの相対パス)
21+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
22+
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
23+
BIN_DIR="$ROOT/app/src-tauri/binaries"
24+
mkdir -p "$BIN_DIR"
25+
26+
# Target triple の決定
27+
if [ -n "${TINYMIST_TARGET:-}" ]; then
28+
TRIPLE="$TINYMIST_TARGET"
29+
else
30+
KERNEL="$(uname -s)"
31+
MACHINE="$(uname -m)"
32+
case "$KERNEL/$MACHINE" in
33+
Linux/x86_64) TRIPLE="x86_64-unknown-linux-gnu" ;;
34+
Linux/aarch64) TRIPLE="aarch64-unknown-linux-gnu" ;;
35+
Linux/arm64) TRIPLE="aarch64-unknown-linux-gnu" ;;
36+
Darwin/arm64) TRIPLE="aarch64-apple-darwin" ;;
37+
Darwin/x86_64) TRIPLE="x86_64-apple-darwin" ;;
38+
MINGW*/x86_64|MSYS*/x86_64|CYGWIN*/x86_64) TRIPLE="x86_64-pc-windows-msvc" ;;
39+
MINGW*/aarch64|MSYS*/aarch64) TRIPLE="aarch64-pc-windows-msvc" ;;
40+
*)
41+
echo "[fetch-tinymist] Unsupported host: $KERNEL/$MACHINE" >&2
42+
echo " Set TINYMIST_TARGET explicitly." >&2
43+
exit 1
44+
;;
45+
esac
46+
fi
47+
48+
# Windows は .exe / .zip、それ以外は .tar.gz
49+
case "$TRIPLE" in
50+
*windows*) ARCHIVE_EXT="zip"; BIN_EXT=".exe" ;;
51+
*) ARCHIVE_EXT="tar.gz"; BIN_EXT="" ;;
52+
esac
53+
54+
ARCHIVE_NAME="tinymist-$TRIPLE.$ARCHIVE_EXT"
55+
URL="https://github.com/Myriad-Dreamin/tinymist/releases/download/$VERSION/$ARCHIVE_NAME"
56+
TARGET_PATH="$BIN_DIR/tinymist-$TRIPLE$BIN_EXT"
57+
58+
# 既に配置済なら skip
59+
if [ -x "$TARGET_PATH" ]; then
60+
echo "[fetch-tinymist] already at $TARGET_PATH (skip)"
61+
exit 0
62+
fi
63+
64+
echo "[fetch-tinymist] downloading $VERSION for $TRIPLE"
65+
echo "[fetch-tinymist] from $URL"
66+
67+
TMP="$(mktemp -d)"
68+
trap 'rm -rf "$TMP"' EXIT
69+
70+
# DL
71+
if ! curl -fL --retry 3 --retry-delay 2 -o "$TMP/$ARCHIVE_NAME" "$URL"; then
72+
echo "[fetch-tinymist] download failed" >&2
73+
exit 1
74+
fi
75+
76+
# 展開
77+
case "$ARCHIVE_EXT" in
78+
tar.gz)
79+
tar -xzf "$TMP/$ARCHIVE_NAME" -C "$TMP"
80+
;;
81+
zip)
82+
if command -v unzip >/dev/null 2>&1; then
83+
unzip -q "$TMP/$ARCHIVE_NAME" -d "$TMP"
84+
else
85+
# Windows runner だと unzip 無いことがある
86+
pwsh -Command "Expand-Archive -Path '$TMP/$ARCHIVE_NAME' -DestinationPath '$TMP'"
87+
fi
88+
;;
89+
esac
90+
91+
# アーカイブ内のバイナリを探す(tar.gz / zip でディレクトリ階層が違う場合への保険)
92+
EXTRACTED="$(find "$TMP" -type f \( -name 'tinymist' -o -name 'tinymist.exe' \) | head -n 1)"
93+
if [ -z "$EXTRACTED" ]; then
94+
echo "[fetch-tinymist] tinymist binary not found in archive" >&2
95+
ls -R "$TMP" >&2
96+
exit 1
97+
fi
98+
99+
cp "$EXTRACTED" "$TARGET_PATH"
100+
chmod +x "$TARGET_PATH"
101+
echo "[fetch-tinymist] installed: $TARGET_PATH"

0 commit comments

Comments
 (0)