Comprehensive improvements across all guide documents
definitive-guide.md: - Add missing AsyncReadExt import in streaming example - Fix v1/v2 WindowUrl table entry (v1 used WindowUrl not WebviewUrl) - Rename 3-Step Pattern to 4-Step Pattern for plugins agent-prompts.md: - Add new Section 15: Prompt for debugging build/compile errors error-resolution-guide.md: - Improve A3 lib naming convention explanation - Clarify G3 multiple definition root cause - Add actionable WebView2 install commands to H1 - Add O9-O11 mobile build errors (Android SDK, macOS, CocoaPods) cheatsheet.md: - Add deep linking subsection with plugin example - Add gen/schemas/ to file hierarchy - Fix tokio::spawn -> tauri::async_runtime::spawn in WS example - Bump tokio-tungstenite 0.21 -> 0.24 ws_server_client_inject_guide.md: - Add WebSocket.OPEN guard to sendToAllWindows() tauri2-links.md: - Expand from 6 to 16 official documentation links
This commit is contained in:
parent
e01e542d65
commit
5972c96ff9
@ -27,6 +27,8 @@ my-app/
|
|||||||
├── src-tauri/ # Backend environment
|
├── src-tauri/ # Backend environment
|
||||||
│ ├── capabilities/ # NEW: Security capability JSON/TOML files
|
│ ├── capabilities/ # NEW: Security capability JSON/TOML files
|
||||||
│ │ └── default.json # Maps app windows to permissions
|
│ │ └── default.json # Maps app windows to permissions
|
||||||
|
│ ├── gen/
|
||||||
|
│ │ └── schemas/ # Generated JSON schemas (referenced by $schema in capabilities)
|
||||||
│ ├── src/
|
│ ├── src/
|
||||||
│ │ ├── main.rs # Minimal platform entry-point
|
│ │ ├── main.rs # Minimal platform entry-point
|
||||||
│ │ └── lib.rs # Core Application setup & commands
|
│ │ └── lib.rs # Core Application setup & commands
|
||||||
@ -130,7 +132,7 @@ If you want your Tauri application to **act as a WebSocket Server** (e.g., expos
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "2.0", features = [] }
|
tauri = { version = "2.0", features = [] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
tokio-tungstenite = "0.21" # Industry standard high-performance WS crate
|
tokio-tungstenite = "0.24" # Industry standard high-performance WS crate
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -147,7 +149,7 @@ async fn start_ws_server(port: &str) {
|
|||||||
.expect("Failed to bind port");
|
.expect("Failed to bind port");
|
||||||
|
|
||||||
while let Ok((stream, _)) = listener.accept().await {
|
while let Ok((stream, _)) = listener.accept().await {
|
||||||
tokio::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
if let Ok(mut ws_stream) = accept_async(stream).await {
|
if let Ok(mut ws_stream) = accept_async(stream).await {
|
||||||
println!("New connection established to Tauri WS Server!");
|
println!("New connection established to Tauri WS Server!");
|
||||||
while let Some(Ok(msg)) = ws_stream.next().await {
|
while let Some(Ok(msg)) = ws_stream.next().await {
|
||||||
@ -165,8 +167,8 @@ async fn start_ws_server(port: &str) {
|
|||||||
pub fn run() {
|
pub fn run() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
// Spin up native server safely in an isolated async tokio environment
|
// Spin up native server safely using Tauri's async runtime (NOT tokio::spawn directly)
|
||||||
tokio::spawn(start_ws_server("8080"));
|
tauri::async_runtime::spawn(start_ws_server("8080"));
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
@ -263,10 +265,13 @@ fn create_extra_window(app: &tauri::AppHandle) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Single Instance Lock & Deep Linking
|
### Single Instance Lock
|
||||||
Ensures only one instance runs, piping external application schemas (e.g. `my-app://open?token=xyz`) into the active runtime.
|
Ensures only one instance runs, focusing the existing window when a second launch is attempted.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
// src-tauri/Cargo.toml: tauri-plugin-single-instance = "2"
|
||||||
|
// src-tauri/capabilities/default.json: add "single-instance:default" to permissions
|
||||||
|
|
||||||
// src-tauri/src/lib.rs
|
// src-tauri/src/lib.rs
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
@ -282,3 +287,67 @@ pub fn run() {
|
|||||||
.expect("failed execution");
|
.expect("failed execution");
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Deep Linking with `tauri-plugin-deep-link`
|
||||||
|
Registers a custom URL scheme (e.g., `my-app://open?token=xyz`) so the OS routes external links into your running app.
|
||||||
|
|
||||||
|
#### 1. Setup
|
||||||
|
```toml
|
||||||
|
# src-tauri/Cargo.toml
|
||||||
|
[dependencies]
|
||||||
|
tauri-plugin-deep-link = "2"
|
||||||
|
```
|
||||||
|
```json
|
||||||
|
// src-tauri/capabilities/default.json — add permission
|
||||||
|
{
|
||||||
|
"permissions": ["deep-link:default"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```json
|
||||||
|
// src-tauri/tauri.conf.json — register the scheme
|
||||||
|
{
|
||||||
|
"app": {
|
||||||
|
"deepLink": {
|
||||||
|
"desktop": {
|
||||||
|
"schemes": ["my-app"]
|
||||||
|
},
|
||||||
|
"mobile": {
|
||||||
|
"scheme": "myapp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Rust Handler
|
||||||
|
```rust
|
||||||
|
// src-tauri/src/lib.rs
|
||||||
|
use tauri_plugin_deep_link::DeepLinkExt;
|
||||||
|
|
||||||
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
|
pub fn run() {
|
||||||
|
tauri::Builder::default()
|
||||||
|
.plugin(tauri_plugin_deep_link::init())
|
||||||
|
.setup(|app| {
|
||||||
|
// macOS / Linux / Windows desktop handler
|
||||||
|
#[cfg(desktop)]
|
||||||
|
app.deep_link().on_open_url(|url| {
|
||||||
|
println!("Deep link opened: {}", url);
|
||||||
|
// Parse URL and route to the appropriate handler
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("failed execution");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Frontend Listener (optional)
|
||||||
|
```typescript
|
||||||
|
import { listen } from '@tauri-apps/api/event';
|
||||||
|
|
||||||
|
// The deep-link plugin emits 'deep-link://new-url' events
|
||||||
|
await listen('deep-link://new-url', (event) => {
|
||||||
|
console.log('Received deep link:', event.payload);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|||||||
@ -13,5 +13,35 @@
|
|||||||
* Tauri 2.0 Official Configuration Files Layout Schema (`tauri.conf.json`):
|
* Tauri 2.0 Official Configuration Files Layout Schema (`tauri.conf.json`):
|
||||||
https://v2.tauri.app/develop/configuration-files/
|
https://v2.tauri.app/develop/configuration-files/
|
||||||
|
|
||||||
* Tauri 2.0 Rust API Documentation Engine (Official `tauri` Crate Source Docs):
|
* Tauri 2.0 Rust Crate API Documentation (Official `tauri` Crate Source Docs):
|
||||||
https://docs.rs
|
https://docs.rs/tauri/latest/tauri/
|
||||||
|
|
||||||
|
* Tauri 2.0 Plugin Index (All Official Plugins):
|
||||||
|
https://v2.tauri.app/plugin/
|
||||||
|
|
||||||
|
* Tauri 2.0 JavaScript API Reference:
|
||||||
|
https://v2.tauri.app/references/javascript/
|
||||||
|
|
||||||
|
* Tauri 2.0 Calling Rust from Frontend (`invoke` Commands):
|
||||||
|
https://v2.tauri.app/develop/calling-rust/
|
||||||
|
|
||||||
|
* Tauri 2.0 Calling Frontend from Rust (Events & Channels):
|
||||||
|
https://v2.tauri.app/develop/calling-frontend/
|
||||||
|
|
||||||
|
* Tauri 2.0 Architecture Overview:
|
||||||
|
https://v2.tauri.app/develop/architecture/
|
||||||
|
|
||||||
|
* Tauri 2.0 Security Overview:
|
||||||
|
https://v2.tauri.app/security/
|
||||||
|
|
||||||
|
* Tauri 2.0 Window Customization:
|
||||||
|
https://v2.tauri.app/develop/window-customization/
|
||||||
|
|
||||||
|
* Tauri 2.0 System Tray Guide:
|
||||||
|
https://v2.tauri.app/develop/tray/
|
||||||
|
|
||||||
|
* Tauri 2.0 Frontend Frameworks (Vite Integration):
|
||||||
|
https://v2.tauri.app/start/frontend/
|
||||||
|
|
||||||
|
* Tauri 2.0 Build Configuration:
|
||||||
|
https://v2.tauri.app/develop/building/
|
||||||
|
|||||||
@ -235,7 +235,11 @@ mainSocket.onerror = (err) => {
|
|||||||
|
|
||||||
// Sending data to other connected windows
|
// Sending data to other connected windows
|
||||||
function sendToAllWindows(payload) {
|
function sendToAllWindows(payload) {
|
||||||
|
if (mainSocket.readyState === WebSocket.OPEN) {
|
||||||
mainSocket.send(JSON.stringify(payload));
|
mainSocket.send(JSON.stringify(payload));
|
||||||
|
} else {
|
||||||
|
console.warn('WebSocket not open — cannot send. readyState:', mainSocket.readyState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: button click sends data
|
// Example: button click sends data
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
12. [Prompt: Full App Build (End-to-End)](#12-prompt-full-app-build-end-to-end)
|
12. [Prompt: Full App Build (End-to-End)](#12-prompt-full-app-build-end-to-end)
|
||||||
13. [Verification Checklist for Agents](#13-verification-checklist-for-agents)
|
13. [Verification Checklist for Agents](#13-verification-checklist-for-agents)
|
||||||
14. [Quick Reference: v1 vs v2 API Map](#14-quick-reference-v1-vs-v2-api-map)
|
14. [Quick Reference: v1 vs v2 API Map](#14-quick-reference-v1-vs-v2-api-map)
|
||||||
|
15. [Prompt: Debug a Tauri 2.0 Build/Compile Error](#15-prompt-debug-a-tauri-20-buildcompile-error)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -507,3 +508,68 @@ Do NOT skip any file. Generate complete, production-ready code.
|
|||||||
| `tauri.updater` | `plugins.updater` |
|
| `tauri.updater` | `plugins.updater` |
|
||||||
| `tauri.systemTray` | `app.trayIcon` |
|
| `tauri.systemTray` | `app.trayIcon` |
|
||||||
| `tauri.cli` | `plugins.cli` |
|
| `tauri.cli` | `plugins.cli` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. Prompt: Debug a Tauri 2.0 Build/Compile Error
|
||||||
|
|
||||||
|
```
|
||||||
|
Diagnose the following Tauri 2.0 build or compile error.
|
||||||
|
|
||||||
|
[PASTE FULL ERROR OUTPUT HERE]
|
||||||
|
|
||||||
|
Follow this structured diagnosis process:
|
||||||
|
|
||||||
|
1. READ THE ERROR MESSAGE CAREFULLY
|
||||||
|
- Identify the exact error code (e.g., E0432, E0599, E0757, E0277, E0255)
|
||||||
|
- Note which file and line number the error originates from
|
||||||
|
- Capture any "note" or "help" lines the compiler provides
|
||||||
|
|
||||||
|
2. CROSS-REFERENCE AGAINST ERROR CATEGORIES
|
||||||
|
Consult the `error-resolution-guide.md` categories and match the error:
|
||||||
|
|
||||||
|
- Category A (Rust Compilation Errors): Version mismatches, missing [lib], windres, strip failures
|
||||||
|
- Category B (v1→v2 Migration): tauri::api removals, Window→WebviewWindow, JS import paths
|
||||||
|
- Category C (Async & Thread Safety): Borrowed refs in async, Mutex not Send, Rc/RefCell in async
|
||||||
|
- Category D (Config Errors): V1 config keys, allowlist, tauri→app section, devUrl/frontendDist
|
||||||
|
- Category E (Capabilities & Permissions): Plugin not allowed, event permissions, path scope
|
||||||
|
- Category F (Plugin Integration): Plugin not registered in Builder, wrong plugin API usage
|
||||||
|
- Category G (IPC / Command Errors): Command not found, multiple invoke_handler, pub in lib.rs
|
||||||
|
- Category H (Webview & Window): WebView2 errors, blank screens, GDK main thread
|
||||||
|
- Category I (Event System): Events not received, emit vs emit_to confusion
|
||||||
|
- Category J (CSP Errors): IPC connection refused, inline styles blocked
|
||||||
|
- Category K (Frontend Integration): Vite port mismatch, Next.js static export, SvelteKit adapter
|
||||||
|
- Category L (WebSocket): Broken pipe, unstable connections
|
||||||
|
- Category M (Path & Asset): 403 on asset:// protocol
|
||||||
|
- Category O (Mobile Build): iOS/Android specific failures
|
||||||
|
|
||||||
|
3. CHECK FOR COMMON PATTERNS
|
||||||
|
- [ ] v1 imports still present (tauri::api::*, @tauri-apps/api/tauri, @tauri-apps/api/window)
|
||||||
|
- [ ] Missing `pub` on commands in separate modules (or extra `pub` on commands in lib.rs)
|
||||||
|
- [ ] tauri/tauri-build version mismatch (one is "1" and the other is "2")
|
||||||
|
- [ ] Async command uses borrowed references (&str, &Path) without Result wrapping
|
||||||
|
- [ ] std::sync::Mutex held across .await (should be tokio::sync::Mutex)
|
||||||
|
- [ ] Plugin in Cargo.toml but not registered with .plugin() in Builder
|
||||||
|
- [ ] Missing capability permission for the plugin/command being used
|
||||||
|
- [ ] Multiple .invoke_handler() calls (only last one takes effect)
|
||||||
|
- [ ] tokio::spawn used instead of tauri::async_runtime::spawn inside setup()
|
||||||
|
- [ ] Window creation in async context without run_on_main_thread()
|
||||||
|
|
||||||
|
4. OUTPUT STRUCTURED DIAGNOSIS
|
||||||
|
Format your response exactly as:
|
||||||
|
|
||||||
|
## Error Diagnosis
|
||||||
|
|
||||||
|
**Error Category:** [Category letter + name from error-resolution-guide.md]
|
||||||
|
**Error Code:** [Rust error code if applicable, e.g., E0432]
|
||||||
|
**Root Cause:** [1-3 sentence explanation of WHY this error occurs]
|
||||||
|
**Fix Steps:**
|
||||||
|
1. [Specific file to edit]
|
||||||
|
- [Exact change to make, with before/after code if applicable]
|
||||||
|
2. [Additional files if needed]
|
||||||
|
- [Changes]
|
||||||
|
**Verification:** [How to confirm the fix works — what should the output look like after]
|
||||||
|
**Cross-Reference:** [Relevant section in error-resolution-guide.md]
|
||||||
|
|
||||||
|
If the error doesn't match any known category, say so explicitly and provide your best analysis based on the error message, Rust compiler output, and Tauri 2.0 API knowledge.
|
||||||
|
```
|
||||||
|
|||||||
@ -693,6 +693,7 @@ For streaming large amounts of data to the frontend:
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
use tauri::ipc::Channel;
|
use tauri::ipc::Channel;
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn stream_file(path: std::path::PathBuf, on_chunk: Channel<Vec<u8>>) {
|
async fn stream_file(path: std::path::PathBuf, on_chunk: Channel<Vec<u8>>) {
|
||||||
@ -1048,7 +1049,7 @@ await newWindow.once('tauri://error', (e) => {
|
|||||||
| `tauri::WindowBuilder` | `tauri::WebviewWindowBuilder` |
|
| `tauri::WindowBuilder` | `tauri::WebviewWindowBuilder` |
|
||||||
| `tauri::WindowUrl` | `tauri::WebviewUrl` |
|
| `tauri::WindowUrl` | `tauri::WebviewUrl` |
|
||||||
| `app.get_window("main")` | `app.get_webview_window("main")` |
|
| `app.get_window("main")` | `app.get_webview_window("main")` |
|
||||||
| `WebviewUrl::App(path)` | `WebviewUrl::App(path.into())` |
|
| `tauri::WindowUrl::App(path)` | `tauri::WebviewUrl::App(path.into())` |
|
||||||
| `WebviewUrl::External(url)` | `WebviewUrl::External(url)` |
|
| `WebviewUrl::External(url)` | `WebviewUrl::External(url)` |
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1092,9 +1093,9 @@ await newWindow.once('tauri://error', (e) => {
|
|||||||
| Window State | `tauri-plugin-window-state` | `@tauri-apps/plugin-window-state` | Win, Lin, Mac, Android, iOS |
|
| Window State | `tauri-plugin-window-state` | `@tauri-apps/plugin-window-state` | Win, Lin, Mac, Android, iOS |
|
||||||
| Window Customization | `tauri-plugin-window-customization` | `@tauri-apps/plugin-window-customization` | Win, Lin, Mac |
|
| Window Customization | `tauri-plugin-window-customization` | `@tauri-apps/plugin-window-customization` | Win, Lin, Mac |
|
||||||
|
|
||||||
### Adding a Plugin (3-Step Pattern)
|
### Adding a Plugin (4-Step Pattern)
|
||||||
|
|
||||||
Every plugin follows the same 3-step setup:
|
Every plugin follows the same 4-step setup:
|
||||||
|
|
||||||
**Step 1: Add Rust dependency**
|
**Step 1: Add Rust dependency**
|
||||||
```toml
|
```toml
|
||||||
|
|||||||
@ -88,6 +88,8 @@ crate-type = ["staticlib", "cdylib", "rlib"]
|
|||||||
```
|
```
|
||||||
Create `src-tauri/src/lib.rs` with your core logic in `pub fn run()`, and a minimal `main.rs` that calls `my_app_lib::run()`.
|
Create `src-tauri/src/lib.rs` with your core logic in `pub fn run()`, and a minimal `main.rs` that calls `my_app_lib::run()`.
|
||||||
|
|
||||||
|
> **Naming convention:** The `[lib]` `name` field must match the crate name used in `main.rs`'s function call (`crate_name::run()`). Rust replaces hyphens with underscores in crate identifiers, so a `name = "my-app-lib"` in Cargo.toml becomes `my_app_lib` in code — your `main.rs` must call `my_app_lib::run()`, not `my-app-lib::run()`. Keep this naming consistent across `[lib]`, `main.rs`, and any `mod` re-exports.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### A4. `windres` Not Found (Windows)
|
### A4. `windres` Not Found (Windows)
|
||||||
@ -949,7 +951,7 @@ tauri::Builder::default()
|
|||||||
error[E0255]: the name '__cmd__my_command' is defined multiple times
|
error[E0255]: the name '__cmd__my_command' is defined multiple times
|
||||||
```
|
```
|
||||||
|
|
||||||
**Cause:** Commands in `lib.rs` cannot be `pub` due to glue code generation.
|
**Cause:** The `#[tauri::command]` macro generates a companion item named `__cmd__<function_name>` in the same scope. When a command in `lib.rs` is marked `pub`, the generated `__cmd__` glue item is also `pub` — and since `lib.rs` itself re-exports everything at the crate root, the command's `__cmd__` symbol collides with a second copy that `generate_handler![]` produces internally. This can also happen when the same command function appears in multiple modules (e.g., defined in one module and `pub use`'d into another).
|
||||||
|
|
||||||
**Solution:** Remove `pub` from commands in `lib.rs`, or move them to a separate module where they MUST be `pub`:
|
**Solution:** Remove `pub` from commands in `lib.rs`, or move them to a separate module where they MUST be `pub`:
|
||||||
```rust
|
```rust
|
||||||
@ -1033,7 +1035,10 @@ Or `0x800700AA` ("The requested resource is in use").
|
|||||||
**Cause:** Multiple possible causes: (1) WebView2 runtime not installed/corrupted, (2) Invalid `additional_browser_args`, (3) Another process holding a WebView2 lock, (4) Data folder creation failure.
|
**Cause:** Multiple possible causes: (1) WebView2 runtime not installed/corrupted, (2) Invalid `additional_browser_args`, (3) Another process holding a WebView2 lock, (4) Data folder creation failure.
|
||||||
|
|
||||||
**Solution:**
|
**Solution:**
|
||||||
1. Install/repair WebView2 runtime
|
1. Install/repair WebView2 runtime:
|
||||||
|
- **winget (recommended):** `winget install Microsoft.WebView2Runtime`
|
||||||
|
- **Direct download:** https://developer.microsoft.com/en-us/microsoft-edge/webview2/
|
||||||
|
- **Evergreen Bootstrapper:** Download and run the bootstrapper from the link above to install/update to the latest version
|
||||||
2. Remove custom `additional_browser_args` from config
|
2. Remove custom `additional_browser_args` from config
|
||||||
3. Kill old Tauri dev instances: `taskkill /f /im <your-app>.exe`
|
3. Kill old Tauri dev instances: `taskkill /f /im <your-app>.exe`
|
||||||
4. For multi-webview support, ensure `features = ["unstable"]` in Cargo.toml
|
4. For multi-webview support, ensure `features = ["unstable"]` in Cargo.toml
|
||||||
@ -1574,6 +1579,79 @@ No code signing certificates found. You must add one and set the certificate dev
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### O9. Android SDK Not Found
|
||||||
|
|
||||||
|
**Error:**
|
||||||
|
```
|
||||||
|
Android SDK not found at ANDROID_HOME. Please set the ANDROID_HOME environment variable.
|
||||||
|
```
|
||||||
|
Or Gradle fails with `SDK location not found`.
|
||||||
|
|
||||||
|
**Cause:** The `ANDROID_HOME` (or `ANDROID_SDK_ROOT`) environment variable is not set, or points to a nonexistent directory. Tauri's Android build requires the Android SDK to be available.
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
1. Install Android Studio, which bundles the SDK
|
||||||
|
2. Set the environment variable:
|
||||||
|
```bash
|
||||||
|
# macOS/Linux — add to ~/.zshrc or ~/.bashrc
|
||||||
|
export ANDROID_HOME="$HOME/Android/Sdk"
|
||||||
|
export PATH="$ANDROID_HOME/platform-tools:$PATH"
|
||||||
|
|
||||||
|
# Windows — set via System Properties → Environment Variables
|
||||||
|
ANDROID_HOME=C:\Users\<you>\AppData\Local\Android\Sdk
|
||||||
|
```
|
||||||
|
3. Verify: `echo $ANDROID_HOME` and `adb version`
|
||||||
|
4. Re-run `npx tauri android init`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### O10. iOS Development Requires macOS
|
||||||
|
|
||||||
|
**Error:**
|
||||||
|
```
|
||||||
|
iOS is not supported on this platform
|
||||||
|
```
|
||||||
|
Or `xcodebuild: command not found` when running on Linux or Windows.
|
||||||
|
|
||||||
|
**Cause:** iOS builds require Xcode and the Apple toolchain, which are only available on macOS. Cross-compilation to iOS from Linux or Windows is not supported by Tauri.
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
1. Use a Mac (physical or CI runner like GitHub Actions `macos-latest`)
|
||||||
|
2. Install Xcode from the Mac App Store
|
||||||
|
3. Accept the Xcode license: `sudo xcodebuild -license accept`
|
||||||
|
4. Install CocoaPods: `sudo gem install cocoapods` (or `brew install cocoapods`)
|
||||||
|
5. For CI, use GitHub Actions with `macos-latest` runner
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### O11. `pod install` Failed (iOS)
|
||||||
|
|
||||||
|
**Error:**
|
||||||
|
```
|
||||||
|
Pod installation failed. CocoaPods could not find compatible versions for pod "TauriDriver"
|
||||||
|
```
|
||||||
|
Or `pod: command not found`.
|
||||||
|
|
||||||
|
**Cause:** CocoaPods is not installed, outdated, or the Podfile.lock is stale and conflicts with updated dependencies.
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
1. Ensure CocoaPods is installed:
|
||||||
|
```bash
|
||||||
|
sudo gem install cocoapods
|
||||||
|
# Or via Homebrew:
|
||||||
|
brew install cocoapods
|
||||||
|
```
|
||||||
|
2. Clean and reinstall pods:
|
||||||
|
```bash
|
||||||
|
cd src-tauri/gen/apple
|
||||||
|
rm -rf Podfile.lock Pods
|
||||||
|
pod install --repo-update
|
||||||
|
```
|
||||||
|
3. If version conflicts persist, update CocoaPods to the latest version: `sudo gem install cocoapods --pre`
|
||||||
|
4. Ensure your Xcode Command Line Tools are up to date: `xcode-select --install`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Category P: Platform-Specific Build Errors
|
## Category P: Platform-Specific Build Errors
|
||||||
|
|
||||||
### P1. Linux — Missing System Dependencies
|
### P1. Linux — Missing System Dependencies
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user