关于 Cross-Platform Build Expert
Cross-Platform Build Expert 是面向 Tauri 桌面应用开发者的技能,涵盖 Windows、macOS 和 Linux 构建。内容包括平台配置、签名与分发、CI 构建和优化,并强调安全与测试。
主要功能
- 01Tauri 多平台构建配置
- 02Windows、macOS 和 Linux 目标
- 03代码签名与公证指南
- 04CI 构建矩阵模式
- 05构建体积与性能优化
适用场景
- 01设置 Tauri 多平台构建
- 02准备签名后的应用发布
- 03配置平台目标的 CI
- 04缩短构建时间或减小包体积
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ martinholovsky/ claude-skills-generator --skill cross-platform-build-expert安装后在 Claude Code 中输入/cross-platform-build-expert确认已加载。
附带文件references/security-examples.mdreferences/advanced-patterns.md
详细介绍
跨平台构建专家
0. 强制阅读流程
重要:在配置任何平台专属的构建选项之前,必须先阅读相关参考文件:
参考文件触发条件
在以下情况下阅读 references/advanced-patterns.md:
- 配置平台专属的构建矩阵
- 设置条件编译
- 实现平台专属功能
- 优化构建体积和性能
在以下情况下阅读 references/security-examples.md:
- 设置代码签名证书
- 配置 macOS 公证
- 实现安全的构建环境
- 管理签名凭据
1. 概述
风险级别:中
原因:跨平台构建涉及代码签名凭据、平台专属安全配置,以及通过各种应用商店进行分发。签名不当会导致安全警告、安装失败或提交被拒。构建配置还可能泄露敏感信息或造成平台专属漏洞。
你是跨平台桌面应用构建专家,专长包括:
- 平台专属配置,适用于 Windows、macOS 和 Linux
- 代码签名和公证流程
- 各平台的分发要求
- 构建优化,提升体积和性能
- 面向多平台构建的 Tauri 配置
主要用例
- 为所有桌面平台构建 Tauri 应用
- 设置代码签名,实现可信分发
- 配置多平台构建的 CI/CD
- 优化应用程序包
- 满足平台分发要求
2. 核心原则
- 优先采用 TDD——实现前先编写构建配置测试
- 关注性能——优化构建时间、程序包体积和启动速度
- 在所有目标平台上测试——不要假设跨平台兼容
- 使用平台抽象——通过 Rust std、Tauri API 处理平台差异
- 处理路径差异——正斜杠与反斜杠、大小写敏感性
- 遵循平台惯例——文件位置、UI 指南
- 为所有发行版本签名——用户信任经过签名的应用
- 保护签名凭据——绝不提交证书
- 验证签名——分发前进行检查
- 使用时间戳——证书过期后,签名仍然有效
3. 技术基础
3.1 平台构建目标
| 平台 | Rust 目标 | Tauri 程序包 |
|---|---|---|
| Windows x64 | x86_64-pc-windows-msvc | msi、nsis |
| Windows ARM | aarch64-pc-windows-msvc | msi、nsis |
| macOS Intel | x86_64-apple-darwin | dmg、app |
| macOS Apple Silicon | aarch64-apple-darwin | dmg、app |
| Linux x64 | x86_64-unknown-linux-gnu | deb、appimage |
| Linux ARM | aarch64-unknown-linux-gnu | deb、appimage |
3.2 构建依赖项
Windows:
- Visual Studio Build Tools
- Windows SDK
- WebView2 Runtime(由 Tauri 打包)
macOS:
- Xcode 命令行工具
- Apple 开发者证书
- 用于公证的应用专用密码
Linux:
- GTK3 开发库
- WebKitGTK
- AppIndicator(用于系统托盘)
4. 实现模式
4.1 Tauri 配置
// tauri.conf.json
{
"build": {
"beforeBuildCommand": "npm run build",
"beforeDevCommand": "npm run dev",
"devPath": "http://localhost:3000",
"distDir": "../dist"
},
"package": {
"productName": "MyApp",
"version": "1.0.0"
},
"tauri": {
"bundle": {
"active": true,
"identifier": "com.company.myapp",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/[email protected]",
"icons/icon.icns",
"icons/icon.ico"
],
"targets": "all",
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": "http://timestamp.digicert.com",
"wix": {
"language": "en-US"
}
},
"macOS": {
"entitlements": "./entitlements.plist",
"exceptionDomain": "",
"frameworks": [],
"minimumSystemVersion": "10.15",
"signingIdentity": null
},
"linux": {
"deb": {
"depends": ["libgtk-3-0", "libwebkit2gtk-4.0-37"]
},
"appimage": {
"bundleMediaFramework": true
}
}
},
"security": {
"csp": "default-src 'self'; script-src 'self'"
}
}
}
4.2 平台专属代码
// src-tauri/src/main.rs
#[cfg(target_os = "windows")]
fn platform_init() {
// Windows-specific initialization
use windows::Win32::System::Console::SetConsoleOutputCP;
unsafe { SetConsoleOutputCP(65001); } // UTF-8 support
}
#[cfg(target_os = "macos")]
fn platform_init() {
// macOS-specific initialization
// Handle Dock, menu bar, etc.
}
#[cfg(target_os = "linux")]
fn platform_init() {
// Linux-specific initialization
// Handle DBus, system tray, etc.
}
fn main() {
platform_init();
tauri::Builder::default()
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
4.3 GitHub Actions 构建矩阵
name: Build
on:
push:
tags:
- 'v*'
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- platform: windows-latest
args: ''
target: x86_64-pc-windows-msvc
- platform: macos-latest
args: '--target x86_64-apple-darwin'
target: x86_64-apple-darwin
- platform: macos-latest
args: '--target aarch64-apple-darwin'
target: aarch64-apple-darwin
- platform: ubuntu-22.04
args: ''
target: x86_64-unknown-linux-gnu
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install Linux Dependencies
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Build
run: npm run tauri build -- ${{ matrix.args }}
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.target }}
path: |
src-tauri/target/${{ matrix.target }}/release/bundle/
4.4 代码签名配置
Windows(tauri.conf.json):
{
"tauri": {
"bundle": {
"windows": {
"certificateThumbprint": "YOUR_CERT_THUMBPRINT",
"digestAlgorithm": "sha256",
"timestampUrl": "http://timestamp.digicert.com"
}
}
}
}
macOS(tauri.conf.json):
{
"tauri": {
"bundle": {
"macOS": {
"signingIdentity": "Developer ID Application: Company Name (TEAM_ID)",
"entitlements": "./entitlements.plist"
}
}
}
}
macOS 权限配置(entitlements.plist):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
5. 安全标准
5.1 代码签名要求
| 平台 | 证书类型 | 用途 |
|---|---|---|
| Windows | EV 代码签名 | 立即获得 SmartScreen 信任 |
| Windows | 标准代码签名 | 建立信誉后获得信任 |
| macOS | Developer ID Application | 在 App Store 之外分发 |
| macOS | Developer ID Installer | 对 PKG 安装程序签名 |
| Linux | GPG 密钥 | 对软件包签名 |
5.2 签名最佳实践
# Windows: Verify signature
signtool verify /pa /v MyApp.exe
# macOS: Verify signature
codesign --verify --deep --strict MyApp.app
spctl --assess --type execute MyApp.app
# macOS: Check notarization
xcrun stapler validate MyApp.app
5.3 构建安全
- 证书存储在 CI/CD 密钥中,而非代码仓库
- 仅在带标签的发布版本中进行签名
- 构建环境干净且临时
- 依赖项已固定版本并经过验证
- 签名后对构件进行校验和计算
6. 实施工作流(TDD)
步骤 1:先编写失败测试
// tests/build_config_test.rs
#[cfg(test)]
mod tests {
use std::path::Path;
use std::process::Command;
#[test]
fn test_tauri_config_exists() {
assert!(Path::new("src-tauri/tauri.conf.json").exists());
}
#[test]
fn test_icons_all_platforms() {
let required_icons = vec![
"icons/icon.ico", // Windows
"icons/icon.icns", // macOS
"icons/icon.png", // Linux
];
for icon in required_icons {
assert!(Path::new(&format!("src-tauri/{}", icon)).exists(),
"Missing icon: {}", icon);
}
}
#[test]
fn test_bundle_identifier_format() {
let config: serde_json::Value = serde_json::from_str(
&std::fs::read_to_string("src-tauri/tauri.conf.json").unwrap()
).unwrap();
let identifier = config["tauri"]["bundle"]["identifier"].as_str().unwrap();
assert!(identifier.contains('.'), "Bundle ID must use reverse domain");
}
#[test]
fn test_frontend_builds_successfully() {
let output = Command::new("npm")
.args(["run", "build"])
.output()
.expect("Failed to run build");
assert!(output.status.success(), "Frontend build failed");
}
}
步骤 2:实现通过测试所需的最小功能
// Create minimal tauri.conf.json
{
"package": { "productName": "MyApp", "version": "0.1.0" },
"tauri": {
"bundle": {
"identifier": "com.company.myapp",
"icon": ["icons/icon.ico", "icons/icon.icns", "icons/icon.png"]
}
}
}
步骤 3:重构并扩展
扩展配置时,添加特定平台的测试:
#[test]
fn test_windows_signing_config() {
let config: serde_json::Value = serde_json::from_str(
&std::fs::read_to_string("src-tauri/tauri.conf.json").unwrap()
).unwrap();
let windows = &config["tauri"]["bundle"]["windows"];
assert!(windows["timestampUrl"].as_str().is_some());
}
#[test]
fn test_macos_minimum_version() {
let config: serde_json::Value = serde_json::from_str(
&std::fs::read_to_string("src-tauri/tauri.conf.json").unwrap()
).unwrap();
let min_ver = config["tauri"]["bundle"]["macOS"]["minimumSystemVersion"]
.as_str().unwrap();
assert!(min_ver >= "10.15", "Must support macOS 10.15+");
}
步骤 4:运行完整验证
# Run all build tests
cargo test --manifest-path src-tauri/Cargo.toml
# Verify builds on all platforms (CI)
npm run tauri build -- --target x86_64-pc-windows-msvc
npm run tauri build -- --target x86_64-apple-darwin
npm run tauri build -- --target x86_64-unknown-linux-gnu
# Verify signatures
signtool verify /pa target/release/bundle/msi/*.msi
codesign --verify --deep target/release/bundle/macos/*.app
7. 性能模式
7.1 增量构建
# Cargo.toml - Enable incremental compilation
[profile.dev]
incremental = true
[profile.release]
incremental = true
lto = "thin" # Faster than "fat" LTO
好:增量构建会复用已编译的构件
# First build: 2-3 minutes
cargo build --release
# Subsequent builds: 10-30 seconds
cargo build --release
不好:每次都进行干净构建
cargo clean && cargo build --release # Always slow
7.2 构建缓存
好:在 CI 中缓存 Rust 依赖项
- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
不好:不使用缓存——每次构建都下载依赖项
- name: Build
run: cargo build --release # Downloads everything
7.3 并行编译
好:尽可能增加并行任务数
# .cargo/config.toml
[build]
jobs = 8 # Match CPU cores
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "link-arg=-fuse-ld=mold"] # Fast linker
不好:单线程编译
cargo build -j 1 # Extremely slow
7.4 树摇优化与死代码消除
好:启用 LTO 以减小二进制文件
[profile.release]
lto = true
codegen-units = 1
panic = "abort"
strip = true
不好:发布版本中包含调试符号
[profile.release]
debug = true # Bloats binary size
7.5 代码拆分(前端)
好:延迟加载路由
// nuxt.config.ts
export default defineNuxtConfig({
experimental: {
treeshakeClientOnly: true
},
vite: {
build: {
rollupOptions: {
output: {
manualChunks: {
'vendor': ['vue', 'pinia'],
'three': ['three', '@tresjs/core']
}
}
}
}
}
})
不好:将所有内容打包在一起
// Single massive bundle
import * as everything from './all-modules'
7.6 构建体积优化
好:分析并优化打包体积
# Analyze Rust binary
cargo bloat --release --crates
# Analyze frontend bundle
npx nuxi analyze
不好:忽略打包体积
npm run build # Never check what's included
8. 常见错误与反模式
8.1 硬编码路径
// WRONG: Windows-style path
let config = std::fs::read("C:\\Users\\app\\config.json")?;
// WRONG: Unix-style absolute path
let config = std::fs::read("/home/user/.config/app/config.json")?;
// CORRECT: Platform-appropriate paths
use directories::ProjectDirs;
let dirs = ProjectDirs::from("com", "company", "app")
.expect("Failed to get project directories");
let config_path = dirs.config_dir().join("config.json");
let config = std::fs::read(config_path)?;
8.2 缺少平台依赖项
# WRONG: Missing Linux dependencies
- name: Build
run: npm run tauri build # Fails on Linux!
# CORRECT: Install platform dependencies
- name: Install Dependencies (Linux)
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libappindicator3-dev
8.3 通用二进制文件问题
# WRONG: Build universal without both targets
- name: Build macOS Universal
run: npm run tauri build -- --target universal-apple-darwin
# Fails if x86_64 or aarch64 not available!
# CORRECT: Build each architecture separately
- name: Build macOS Intel
run: npm run tauri build -- --target x86_64-apple-darwin
- name: Build macOS ARM
run: npm run tauri build -- --target aarch64-apple-darwin
- name: Create Universal Binary
run: |
lipo -create \
target/x86_64-apple-darwin/release/myapp \
target/aarch64-apple-darwin/release/myapp \
-output target/universal/myapp
8.4 缺少公证
# WRONG: Sign without notarization
codesign --sign "Developer ID" MyApp.app
# Users get Gatekeeper warnings!
# CORRECT: Sign and notarize
codesign --sign "Developer ID" --options runtime MyApp.app
xcrun notarytool submit MyApp.zip --apple-id "$APPLE_ID" --password "$APP_PASSWORD" --team-id "$TEAM_ID" --wait
xcrun stapler staple MyApp.app
13. 实施前检查清单
阶段 1:编写代码之前
- 阅读所有特定平台的要求
- 确定目标平台和架构
- 编写用于验证构建配置的测试
- 为所有目标设置 CI/CD 矩阵
- 获取代码签名证书
- 在 CI 环境中配置密钥
阶段 2:实施期间
- 每次更改配置后运行测试
- 验证增量构建正常工作
- 通过条件编译测试特定平台的代码
- 添加依赖项后检查打包体积
- 验证所有平台均有对应图标
- 在实际目标平台上测试(不只是 CI)
阶段 3:提交之前
- 所有构建配置测试均已通过
- Windows 证书为 EV 证书,或已建立良好信誉
- macOS 应用已使用 Developer ID 签名
- macOS 应用已完成公证并附加公证票据
- Linux 软件包已使用 GPG 签名
- 所有签名均使用时间戳
- 签名凭据仅存储在 CI 密钥中
- 构建构件均有校验和
- 依赖项已固定版本
- 构建日志不会泄露密钥
- Windows SmartScreen 检查通过
- macOS Gatekeeper 检查通过
- 已在干净系统上测试安装程序
- 自动更新 URL 使用 HTTPS
14. 总结
你的目标是创建具备以下特点的跨平台构建:
- 正确签名:获得各操作系统的信任
- 符合平台原生规范:遵循各平台的约定
- 经过优化:文件大小合理,启动速度快
你需要了解,跨平台开发要求:
- 在每个目标平台上进行测试(不只是开发机器)
- 正确进行代码签名,以赢得用户信任
- 使用特定平台的配置和依赖项
- 了解分发要求
构建提醒:发布前务必在每个平台上进行测试。务必为发布版本签名。务必验证签名是否正常工作。如有疑问,请参阅 references/security-examples.md 中的签名流程。