深夜提醒

现在是深夜,建议您注意休息,不要熬夜哦~

🏮 🏮 🏮

新年快乐

祝君万事如意心想事成!

share-image
中
ESC

Tauri Cross-Platform Build Pitfall Guide: A Full Walkthrough from Biome to Rust Linking

English 阅读中文版

Tauri cross-platform build

While developing ClipVault, a cross-platform clipboard manager, I went through the full gauntlet from code-style checks to multi-platform compilation. This article documents the complete solution set, from Biome CI check failures to Rust cross-platform linking errors.

Project Background

  • Tech stack: Tauri 2.0 + React + Rust
  • Target platforms: Windows (x86/x64/ARM64) + macOS (Intel/Apple Silicon) + Linux (x64/ARM64)
  • CI/CD: GitHub Actions

Pitfall One: Biome CI Version Mismatch and Code Style

Symptom

GitHub Actions errors out when running biome ci .:

Notice: The configuration schema version does not match the CLI version 2.4.6
Expected: 2.4.6, Found: 2.2.6

Along with a pile of code-style errors:

  • Error: The properties are not sorted. (CSS properties not sorted)
  • Error: The object properties are not sorted by key. (object keys not sorted)
  • Error: Provide an explicit type attribute for the button element. (button missing a type attribute)

Cause Analysis

  1. Version mismatch: local Biome version (2.2.6) doesn’t match the CI environment (2.4.6)
  2. Strict rules: Biome enables strict rules like useSortedProperties and useSortedKeys by default
  3. dist directory: the build output directory was mistakenly included in the check scope

Solution

1. Unify the version

// biome.json
{
"$schema": "https://biomejs.dev/schemas/2.4.6/schema.json"
}
# Upgrade local Biome
pnpm add -D @biomejs/biome@2.4.6

2. Exclude files that shouldn’t be checked

// biome.json
{
"files": {
"includes": ["**", "!package.json", "!.release-it.ts", "!dist/**", "!scripts/auto-fix.js"]
}
}

3. Auto-fix code style

pnpm biome check --write --unsafe .

Key Config

{
"$schema": "https://biomejs.dev/schemas/2.4.6/schema.json",
"assist": {
"actions": {
"source": {
"organizeImports": "on",
"useSortedAttributes": "on",
"useSortedKeys": "on",
"useSortedProperties": "on"
}
}
},
"files": {
"includes": ["**", "!package.json", "!.release-it.ts", "!dist/**"]
}
}

Pitfall Two: Wrong Rust Cross-Platform Linker Configuration

Symptom

The Linux build errors out:

error: linking with `cc` failed: exit status: 1
rust-lld: error: cannot open /FORCE:MULTIPLE: No such file or directory
collect2: error: ld returned 1 exit status

Cause Analysis

/FORCE:MULTIPLE is a Windows MSVC linker-specific option used to forcibly allow multiple definitions. When that option is mistakenly passed to Linux’s ld linker, the build fails.

Wrong Configuration

# .cargo/config.toml ❌ wrong
[build]
rustflags = ["-C", "link-arg=/FORCE:MULTIPLE", "-C", "prefer-dynamic"]

Solution

Use Cargo’s conditional target configuration to apply the option only under the Windows target:

# .cargo/config.toml ✅ correct

# Windows targets need the /FORCE:MULTIPLE linker option
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "link-arg=/FORCE:MULTIPLE"]

[target.i686-pc-windows-msvc]
rustflags = ["-C", "link-arg=/FORCE:MULTIPLE"]

[target.aarch64-pc-windows-msvc]
rustflags = ["-C", "link-arg=/FORCE:MULTIPLE"]

# Linux ARM target configuration
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"

Pitfall Three: LTO Conflicts with Dynamic Linking

Symptom

macOS and Linux builds error out:

error: cannot prefer dynamic linking when performing LTO
note: only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO

Cause Analysis

prefer-dynamic (preferring dynamic linking) conflicts with lto = true (link-time optimization):

  • Fat LTO (lto = true) requires static linking
  • Dynamic linking produces dynamic library dependencies

Solution

[profile.release]
strip = true
lto = "thin" # changed from true to "thin"
opt-level = 3

Option 2: Fully disable LTO

[profile.release]
strip = true
# lto fully disabled (faster builds, but larger binaries)

Final Configuration

# .cargo/config.toml
[profile.release]
strip = true
lto = "thin"
opt-level = 3

Pitfall Four: apt Source Configuration for Ubuntu ARM64 Cross-Compilation

Symptom

apt installation fails during Linux ARM64 cross-compilation:

E: Failed to fetch https://security.ubuntu.com/ubuntu/dists/jammy/main/binary-arm64/Packages  404  Not Found
E: Failed to fetch https://security.ubuntu.com/ubuntu/dists/jammy-updates/main/binary-arm64/Packages 404 Not Found

Cause Analysis

Ubuntu 22.04’s default sources archive.ubuntu.com and security.ubuntu.com contain only x86_64 architecture packages. ARM64 architecture packages are hosted on ports.ubuntu.com.

Solution

1. Switch the apt sources to ports.ubuntu.com

# .github/workflows/release.yml
- name: Install ARM cross-compile dependencies
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo dpkg --add-architecture arm64
# Key: switch apt sources to ports.ubuntu.com (supports ARM64)
sudo sed -i 's|http://archive.ubuntu.com/ubuntu/|http://ports.ubuntu.com/ubuntu-ports/|g' /etc/apt/sources.list
sudo sed -i 's|http://security.ubuntu.com/ubuntu/|http://ports.ubuntu.com/ubuntu-ports/|g' /etc/apt/sources.list
sudo apt-get update || true
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
sudo apt-get install -y libwebkit2gtk-4.1-dev:arm64 libappindicator3-dev:arm64 librsvg2-dev:arm64 patchelf || true

2. Configure the cross-compilation environment variables

- name: Setup ARM cross-compile env
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV
echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV
echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV

3. Cargo configuration

# .cargo/config.toml
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"

Full Configuration Reference

.github/workflows/release.yml

name: Release CI

on:
push:
tags:
- "v*"

jobs:
build-app:
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: "macos-latest"
target: "aarch64-apple-darwin"
- platform: "macos-latest"
target: "x86_64-apple-darwin"
- platform: "windows-latest"
target: "x86_64-pc-windows-msvc"
- platform: "windows-latest"
target: "i686-pc-windows-msvc"
- platform: "windows-latest"
target: "aarch64-pc-windows-msvc"
- platform: "ubuntu-22.04"
target: "x86_64-unknown-linux-gnu"
- platform: "ubuntu-22.04"
target: "aarch64-unknown-linux-gnu"

runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4

- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20

- uses: pnpm/action-setup@v3
with:
version: latest

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- name: Install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

- name: Install ARM cross-compile dependencies
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo dpkg --add-architecture arm64
# Switch apt sources to ports.ubuntu.com
sudo sed -i 's|http://archive.ubuntu.com/ubuntu/|http://ports.ubuntu.com/ubuntu-ports/|g' /etc/apt/sources.list
sudo sed -i 's|http://security.ubuntu.com/ubuntu/|http://ports.ubuntu.com/ubuntu-ports/|g' /etc/apt/sources.list
sudo apt-get update || true
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
sudo apt-get install -y libwebkit2gtk-4.1-dev:arm64 libappindicator3-dev:arm64 librsvg2-dev:arm64 patchelf || true

- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: src-tauri/target
key: ${{ matrix.target }}

- name: Setup ARM cross-compile env
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV
echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV
echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV

- name: Build the app
uses: tauri-apps/tauri-action@v0
env:
CI: false
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
with:
tagName: ${{ github.ref_name }}
releaseName: "ClipVault ${{ github.ref_name }}"
releaseDraft: false
prerelease: false
args: --target ${{ matrix.target }}

.cargo/config.toml

# Windows targets need the /FORCE:MULTIPLE linker option
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "link-arg=/FORCE:MULTIPLE"]

[target.i686-pc-windows-msvc]
rustflags = ["-C", "link-arg=/FORCE:MULTIPLE"]

[target.aarch64-pc-windows-msvc]
rustflags = ["-C", "link-arg=/FORCE:MULTIPLE"]

# Linux ARM target configuration
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"

# macOS target configuration
[target.aarch64-apple-darwin]
linker = "clang"
rustflags = ["-C", "link-arg=-arch", "-C", "link-arg=arm64"]

[target.x86_64-apple-darwin]
linker = "clang"
rustflags = ["-C", "link-arg=-arch", "-C", "link-arg=x86_64"]

[profile.release]
strip = true
lto = "thin"
opt-level = 3

Build Matrix Summary

Platform Architecture Rust Target Special Config
Windows x86_64 x86_64-pc-windows-msvc /FORCE:MULTIPLE
Windows x86 i686-pc-windows-msvc /FORCE:MULTIPLE
Windows ARM64 aarch64-pc-windows-msvc /FORCE:MULTIPLE
macOS Intel x86_64-apple-darwin clang + arch flag
macOS Apple Silicon aarch64-apple-darwin clang + arch flag
Linux x86_64 x86_64-unknown-linux-gnu default config
Linux ARM64 aarch64-unknown-linux-gnu ports.ubuntu.com + cross toolchain

Summary

The core points of Tauri cross-platform builds:

  1. Code style: keep Biome/Prettier versions consistent and exclude the build output directory
  2. Linker config: use Cargo’s conditional target configuration to avoid applying Windows-only options to other platforms
  3. LTO strategy: use thin LTO to balance build speed and binary optimization
  4. Cross-compilation: Ubuntu ARM64 needs to switch to the ports.ubuntu.com source

For the complete code, see the ClipVault GitHub repository.


This article is based on hands-on experience with Tauri 2.0 + GitHub Actions, and I hope it helps more developers avoid these pitfalls.

文章作者:阿文
文章链接: https://www.awen.me/post/dae346cf.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 阿文的博客!
本文于 2026-03-06 20:00 发布,已超过半年(224天),请注意甄别内容是否已过期。

评论

0 条评论
😀😃😄 😁😅😂 🤣😊😇 🙂🙃😉 😌😍🥰 😘😗😙 😚😋😛 😝😜🤪 🤨🧐🤓 😎🥸🤩 🥳😏😒 😞😔😟 😕🙁☹️ 😣😖😫 😩🥺😢 😭😤😠 😡🤬🤯 😳🥵🥶 😱😨😰 😥😓🤗 🤔🤭🤫 🤥😶😐 😑😬🙄 😯😦😧 😮😲🥱 😴🤤😪 😵🤐🥴 🤢🤮🤧 😷🤒🤕 🤑🤠😈 👿👹👺 🤡💩👻 💀☠️👽 👾🤖🎃 😺😸😹 😻😼😽 🙀😿😾 👍👎👏 🙌👐🤲 🤝🤜🤛 ✌️🤞🤟 🤘👌🤏 👈👉👆 👇☝️✋ 🤚🖐️🖖 👋🤙💪 🦾🖕✍️ 🙏💅🤳 💯💢💥 💫💦💨 🕳️💣💬 👁️‍🗨️🗨️🗯️ 💭💤❤️ 🧡💛💚 💙💜🖤 🤍🤎💔 ❣️💕💞 💓💗💖 💘💝💟 ☮️✝️☪️ 🕉️☸️✡️ 🔯🕎☯️ ☦️🛐⛎ ♈♉♊ ♋♌♍ ♎♏♐ ♑♒♓ 🆔⚛️🉑 ☢️☣️📴 📳🈶🈚 🈸🈺🈷️ ✴️🆚💮 🉐㊙️㊗️ 🈴🈵🈹 🈲🅰️🅱️ 🆎🆑🅾️ 🆘❌⭕ 🛑⛔📛 🚫💯💢 ♨️🚷🚯 🚳🚱🔞 📵🚭❗ ❕❓❔ ‼️⁉️🔅 🔆〽️⚠️ 🚸🔱⚜️ 🔰♻️✅ 🈯💹❇️ ✳️❎🌐 💠Ⓜ️🌀 💤🏧🚾 ♿🅿️🈳 🈂🛂🛃 🛄🛅🛗 🚀🛸🚁 🚉🚆🚅 ✈️🛫🛬 🛩️💺🛰️
加载中...

留言反馈

😀😃😄 😁😅😂 🤣😊😇 🙂🙃😉 😌😍🥰 😘😗😙 😚😋😛 😝😜🤪 🤨🧐🤓 😎🥸🤩 🥳😏😒 😞😔😟 😕🙁☹️ 😣😖😫 😩🥺😢 😭😤😠 😡🤬🤯 😳🥵🥶 😱😨😰 😥😓🤗 🤔🤭🤫 🤥😶😐 😑😬🙄 😯😦😧 😮😲🥱 😴🤤😪 😵🤐🥴 🤢🤮🤧 😷🤒🤕 🤑🤠😈 👿👹👺 🤡💩👻 💀☠️👽 👾🤖🎃 😺😸😹 😻😼😽 🙀😿😾 👍👎👏 🙌👐🤲 🤝🤜🤛 ✌️🤞🤟 🤘👌🤏 👈👉👆 👇☝️✋ 🤚🖐️🖖 👋🤙💪 🦾🖕✍️ 🙏💅🤳 💯💢💥 💫💦💨 🕳️💣💬 👁️‍🗨️🗨️🗯️ 💭💤❤️ 🧡💛💚 💙💜🖤 🤍🤎💔 ❣️💕💞 💓💗💖 💘💝💟 ☮️✝️☪️ 🕉️☸️✡️ 🔯🕎☯️ ☦️🛐⛎ ♈♉♊ ♋♌♍ ♎♏♐ ♑♒♓ 🆔⚛️🉑 ☢️☣️📴 📳🈶🈚 🈸🈺🈷️ ✴️🆚💮 🉐㊙️㊗️ 🈴🈵🈹 🈲🅰️🅱️ 🆎🆑🅾️ 🆘❌⭕ 🛑⛔📛 🚫💯💢 ♨️🚷🚯 🚳🚱🔞 📵🚭❗ ❕❓❔ ‼️⁉️🔅 🔆〽️⚠️ 🚸🔱⚜️ 🔰♻️✅ 🈯💹❇️ ✳️❎🌐 💠Ⓜ️🌀 💤🏧🚾 ♿🅿️🈳 🈂🛂🛃 🛄🛅🛗 🚀🛸🚁 🚉🚆🚅 ✈️🛫🛬 🛩️💺🛰️