Skip to content

About

A cross-language GUI application template: SwiftCrossUI(GTK4) calls Rust functions via swift-bridge for FFI glue code, with Buck2 as the unified build system.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

SwiftCrossUI-RustBackend-Template — Swift × Rust via swift-bridge + Buck2

跨语言 GUI 应用模板:Swift(SwiftCrossUI / GTK4)调用 Rust 函数,通过 swift-bridge 生成 FFI 胶水代码,Buck2 统一构建。

项目结构

SwiftCrossUI-RustBackend-Template/
├── consts.bzl                      # 集中配置(项目名、路径、构建常量)
├── .buckconfig / .buckroot         # Buck2 项目配置
├── BUCK                            # Buck2 根构建文件
├── toolchains/BUCK                 # Buck2 工具链
├── build.sh                        # 一键构建+运行
├── cleanbuild.sh / cleanall.sh     # 清理脚本
│
├── Package.swift / Package.resolved  # SPM 清单(Buck2 genrule 内部使用)
├── Bundler.toml                    # Swift Bundler 配置(备选运行方式)
│
├── Sources/
│   ├── SwiftCrossUI-RustBackend-Template/                 # Swift 应用源码(目录名由 consts.bzl 派生)
│   │   ├── SwiftCrossUI-RustBackend-TemplateApp.swift     # 主入口,调用 hello_from_rust() 等
│   │   └── Generated/              # swift-bridge 生成的 Swift 文件(构建时填充)
│   └── CRustBridge/                # C 桥接层(SPM systemLibrary)
│       ├── module.modulemap
│       └── shim.h                  # 包含生成的 C 头文件
│
└── RustBackend/                    # Rust 子项目
    ├── Cargo.toml                  # staticlib + swift-bridge 依赖
    ├── build.rs                    # swift-bridge 代码生成器
    ├── src/lib.rs                  # #[swift_bridge::bridge] 标注 + Rust 实现
    └── BUCK                        # Buck2 Rust 构建 genrule

前置条件

工具 最低版本 用途
Swift 6.0+ 编译 Swift 源码
Rust 1.70+ 编译 Rust 静态库
Buck2 任意 主构建系统
GTK4 开发库 — Linux GUI 运行时(libgtk-4-dev)
# Ubuntu/Debian
sudo apt install libgtk-4-dev

# Fedora
sudo dnf install gtk4-devel

# Arch
sudo pacman -S gtk4

SwiftCrossUI 要点

本项目使用 SwiftCrossUI 作为跨平台 UI 框架。关键概念:

Backend 系统

SwiftCrossUI 通过多种 backend 适配不同平台。使用 DefaultBackend 即可自动选择:

平台 DefaultBackend 映射 说明
macOS AppKitBackend 原生 macOS 渲染
Linux GtkBackend GTK4 渲染(推荐)
Windows WinUIBackend 原生 Windows 渲染
iOS / tvOS UIKitBackend 原生 iOS 渲染

可用 backend 还包括 Gtk3Backend(老旧 Linux 发行版,功能较少)。强制指定 backend:

import GtkBackend  // 替代 DefaultBackend,固定 GTK4

或在编译时通过环境变量覆盖:SCUI_DEFAULT_BACKEND=GtkBackend swift build。

两种运行方式

方式 命令 适用场景
Swift Bundler(推荐) swift-bundler run 跨平台分发、资源加载、iOS/tvOS 设备
SPM 直接运行 swift run 快速开发测试(资源加载可能异常)

本项目默认用 Buck2 构建,内部调用 swift build(SPM 模式)。备选 ./build.sh bundler 提供 Swift Bundler 方式。

Swift Bundler 安装(可选)

Swift Bundler 是 SwiftCrossUI 官方推荐的构建运行工具,支持跨平台分发和 iOS/tvOS 设备。仅在使用 ./build.sh bundler 时需要安装。

# 1. 安装 Mint(Swift 包管理器)
# macOS
brew install mint
# Linux
git clone https://github.com/yonaskolb/Mint.git
cd Mint && swift build -c release
sudo cp .build/release/mint /usr/local/bin/

# 2. 通过 Mint 安装 Swift Bundler
mint install stackotter/swift-bundler@main

# 3. 验证
swift-bundler --help

手动安装方式详见 Swift Bundler 文档。

最小示例

import SwiftCrossUI
import DefaultBackend

@main
struct CounterApp: App {
    @State var count = 0
    var body: some Scene {
        WindowGroup("Counter") {
            HStack {
                Button("-") { count -= 1 }
                Text("Count: \(count)")
                Button("+") { count += 1 }
            }.padding()
        }
    }
}

快速开始

git clone <repo-url> && cd <repo>
./build.sh

默认使用 Buck2 构建。窗口打开后可以看到 Swift 调用 Rust 的 Fibonacci 计算、加法/乘法等功能。

构建命令

Buck2(推荐)

buck2 build :SwiftCrossUI-RustBackend-Template    # 仅编译
buck2 run :run             # 编译 + 运行
buck2 targets :            # 查看所有构建目标

备选方式

./build.sh spm              # SPM 直接构建
./build.sh bundler          # Swift Bundler 构建

清理

命令 清除范围
./cleanbuild.sh 构建产物(保留 GitHub 上 fetch 的依赖,下次编译快)
./cleanall.sh 一切(含 SPM checkouts / Cargo registry,相当于 fresh clone)
buck2 clean 仅 Buck2 的buck-out/

配置集中化

所有项目名和路径定义在 consts.bzl 一个文件中:

PROJECT_NAME = "SwiftCrossUI-RustBackend-Template"
RUST_CRATE_NAME = "rust-backend"
RUST_DIR = "RustBackend"
SWIFT_SRC_DIR = "Sources/SwiftCrossUI-RustBackend-Template"     # 由 PROJECT_NAME 自动派生

BUCK 文件全部通过 load("//:consts.bzl", "PROJECT_NAME", ...) 引用,没有硬编码。

修改项目名

假设将项目从 SwiftCrossUI-RustBackend-Template 改名为 A,需要改以下位置。粗体是必须改的,其余由 Buck2 自动派生。

步骤

# 1. 修改集中配置(唯一需要改的 Buck2 文件)
#    编辑 consts.bzl → PROJECT_NAME = "A"
vim consts.bzl
#    PROJECT_NAME = "A"

# 2. 重命名源码目录
mv Sources/SwiftCrossUI-RustBackend-Template/ Sources/A/

# 3. 更新 Swift 包清单
#    编辑 Package.swift,将 3 处 "SwiftCrossUI-RustBackend-Template" 替换为 "A":
#      · package name:   name: "A"
#      · target name:    name: "A"
#      · target path:    自动在 Sources/A/ 下,无需显式指定

# 4. 更新 Bundler.toml(备选运行方式)
#    编辑 Bundler.toml,将 3 处替换:
#      · [apps.A]
#      · identifier = 'com.example.A'
#      · product = 'A'

受影响的文件清单

文件 改动内容 是否必须
consts.bzl PROJECT_NAME = "A" 必须
Sources/SwiftCrossUI-RustBackend-Template/ 重命名为Sources/A/ 必须
Package.swift name: (2处)、path: SPM 模式时必须
Bundler.toml [apps.A]、product、identifier Bundler 模式时必须
Sources/A/SwiftCrossUI-RustBackend-TemplateApp.swift 结构体名可保留SwiftCrossUI-RustBackend-TemplateApp 不必
build.sh (SPM/Bundler fallback) 路径Sources/SwiftCrossUI-RustBackend-Template/ → Sources/A/ SPM/Bundler 模式时必须

无需改动的文件

以下 Buck2 构建文件通过 consts.bzl 动态派生所有路径,不需要任何改动:

BUCK                ← name = PROJECT_NAME, glob(SWIFT_SRC_DIR), ...
RustBackend/BUCK     ← RUST_CRATE_NAME, RUST_LIB_NAME 从 consts
.buckconfig          ← alias run = root//:run(与项目名无关)
toolchains/BUCK      ← 通用工具链
cleanbuild.sh        ← 清理脚本
cleanall.sh          ← 清理脚本
.gitignore           ← 通配符模式

验证

./cleanbuild.sh
./build.sh
# Buck2 的 target 名称自动变为 A:
buck2 targets :     # 输出 root//:A, root//:run
buck2 run :run      # 构建并运行

架构

┌─────────────────┐    import CRustBridge    ┌──────────────────┐
│ SwiftCrossUI-RustBackend-Template      │ ◄─────────────────────── │ Swift Bridge     │
│ App.swift       │                          │ (Generated .swift)│
└───────┬─────────┘                          └────────┬─────────┘
        │ Swift calls                                │ calls C symbols
        │ hello_from_rust()                          │ __swift_bridge__$*
        │ performCalc()                              │
        │ compute_fibonacci()                        │
        ▼                                            ▼
┌──────────────────────────────────────────────────────────────┐
│                    CRustBridge (C module)                     │
│                  exposes __swift_bridge__$*                   │
└────────────────────────────┬─────────────────────────────────┘
                             │ links
                             ▼
┌──────────────────────────────────────────────────────────────┐
│                 librust_backend.a (Rust)                     │
│          hello_from_rust(), fibonacci(), ...                 │
└──────────────────────────────────────────────────────────────┘

Buck2 构建流程:

RustBackend/BUCK         根 BUCK
──────────────           ───────
 genrule                  genrule
 ┌────────────┐          ┌──────────────────────────────┐
 │ cargo build│          │ cp → SPM 期望的路径           │
 │ → .a       │──dep──►  │ swift build --product        │
 │ → .h/.swift│          │ → SwiftCrossUI-RustBackend-Template 二进制           │
 └────────────┘          └───────────┬──────────────────┘
                                     │
                           command_alias("run")
                           ┌─────────┴──────────┐
                           │ buck2 run :run     │
                           └────────────────────┘

如何添加新的 Rust 函数

  1. 在 RustBackend/src/lib.rs 的 #[swift_bridge::bridge] 块中声明:
extern "Rust" {
    fn my_new_function(input: u32) -> String;
}

fn my_new_function(input: u32) -> String {
    format!("Result: {}", input * 2)
}
  1. 在 Sources/SwiftCrossUI-RustBackend-Template/SwiftCrossUI-RustBackend-TemplateApp.swift 中调用:
let result = my_new_function(42)
Text(result.toString())
  1. 重新构建:./build.sh

技术依赖

库 版本 用途
swift-bridge / swift-bridge-build 0.1 Rust ↔ Swift FFI
swift-cross-ui 0.5.1 跨平台 SwiftUI 框架
Buck2 2026-05-03 构建系统
GTK4 4.x Linux 渲染后端

许可证

MIT


English

A cross-language GUI application template: Swift (SwiftCrossUI / GTK4) calls Rust functions via swift-bridge for FFI glue code, with Buck2 as the unified build system.

Project Structure

SwiftCrossUI-RustBackend-Template/
├── consts.bzl                      # Centralized config (name, paths, constants)
├── .buckconfig / .buckroot         # Buck2 project config
├── BUCK                            # Buck2 root build file
├── toolchains/BUCK                 # Buck2 toolchain
├── build.sh                        # One-click build & run
├── cleanbuild.sh / cleanall.sh     # Clean scripts
│
├── Package.swift / Package.resolved  # SPM manifest (used internally by Buck2 genrule)
├── Bundler.toml                    # Swift Bundler config (alternative runner)
│
├── Sources/
│   ├── SwiftCrossUI-RustBackend-Template/                 # Swift app sources (dir name derived from consts.bzl)
│   │   ├── SwiftCrossUI-RustBackend-TemplateApp.swift     # Entry point, calls hello_from_rust() etc.
│   │   └── Generated/              # swift-bridge generated Swift files (populated at build)
│   └── CRustBridge/                # C bridge layer (SPM systemLibrary)
│       ├── module.modulemap
│       └── shim.h                  # Includes generated C headers
│
└── RustBackend/                    # Rust sub-project
    ├── Cargo.toml                  # staticlib + swift-bridge deps
    ├── build.rs                    # swift-bridge code generator
    ├── src/lib.rs                  # #[swift_bridge::bridge] annotations + impl
    └── BUCK                        # Buck2 Rust build genrule

Prerequisites

Tool Min Version Purpose
Swift 6.0+ Compile Swift sources
Rust 1.70+ Compile Rust static library
Buck2 Any Primary build system
GTK4 dev libraries — Linux GUI runtime (libgtk-4-dev)
# Ubuntu/Debian
sudo apt install libgtk-4-dev

# Fedora
sudo dnf install gtk4-devel

# Arch
sudo pacman -S gtk4

SwiftCrossUI Essentials

This project uses SwiftCrossUI as the cross-platform UI framework.

Backend System

SwiftCrossUI adapts to different platforms via backends. Use DefaultBackend for automatic selection:

Platform DefaultBackend maps to Notes
macOS AppKitBackend Native macOS rendering
Linux GtkBackend GTK4 rendering (recommended)
Windows WinUIBackend Native Windows rendering
iOS / tvOS UIKitBackend Native iOS rendering

Gtk3Backend is also available for older Linux distros (fewer features). Force a specific backend:

import GtkBackend  // Replace DefaultBackend, fix GTK4

Or override at compile time: SCUI_DEFAULT_BACKEND=GtkBackend swift build.

Running Options

Method Command Use Case
Swift Bundler (recommended) swift-bundler run Cross-platform distribution, resources, iOS/tvOS
SPM direct swift run Quick dev testing (resources may not load correctly)

This project defaults to Buck2 builds, which invoke swift build internally (SPM mode). Use ./build.sh bundler for Swift Bundler.

Swift Bundler Install (optional)

Swift Bundler is the official recommended build tool for SwiftCrossUI. Only needed for ./build.sh bundler.

# 1. Install Mint (Swift package manager)
# macOS
brew install mint
# Linux
git clone https://github.com/yonaskolb/Mint.git
cd Mint && swift build -c release
sudo cp .build/release/mint /usr/local/bin/

# 2. Install Swift Bundler via Mint
mint install stackotter/swift-bundler@main

# 3. Verify
swift-bundler --help

See Swift Bundler docs for manual installation.

Minimal Example

import SwiftCrossUI
import DefaultBackend

@main
struct CounterApp: App {
    @State var count = 0
    var body: some Scene {
        WindowGroup("Counter") {
            HStack {
                Button("-") { count -= 1 }
                Text("Count: \(count)")
                Button("+") { count += 1 }
            }.padding()
        }
    }
}

Quick Start

git clone <repo-url> && cd <repo>
./build.sh

Defaults to Buck2. The app window shows Swift calling Rust for Fibonacci, arithmetic, etc.

Build Commands

Buck2 (recommended)

buck2 build :SwiftCrossUI-RustBackend-Template    # Build only
buck2 run :run             # Build + run
buck2 targets :            # List all targets

Alternatives

./build.sh spm              # Direct SPM build
./build.sh bundler          # Swift Bundler build

Cleaning

Command What it removes
./cleanbuild.sh Build artifacts (keeps fetched dependencies, faster rebuilds)
./cleanall.sh Everything (incl. SPM checkouts / Cargo registry, like fresh clone)
buck2 clean Buck2'sbuck-out/ only

Centralized Configuration

All project names and paths are defined in a single file, consts.bzl:

PROJECT_NAME = "SwiftCrossUI-RustBackend-Template"
RUST_CRATE_NAME = "rust-backend"
RUST_DIR = "RustBackend"
SWIFT_SRC_DIR = "Sources/SwiftCrossUI-RustBackend-Template"     # auto-derived from PROJECT_NAME

All BUCK files reference these via load("//:consts.bzl", "PROJECT_NAME", ...) — no hardcoded strings.

Renaming the Project

To rename from SwiftCrossUI-RustBackend-Template to A. Bold = mandatory.

Steps

# 1. Edit centralized config (the only Buck2 file to change)
#    consts.bzl → PROJECT_NAME = "A"
vim consts.bzl
#    PROJECT_NAME = "A"

# 2. Rename source directory
mv Sources/SwiftCrossUI-RustBackend-Template/ Sources/A/

# 3. Update Swift package manifest
#    Edit Package.swift, replace "SwiftCrossUI-RustBackend-Template" with "A" (3 occurrences):
#      · package name:   name: "A"
#      · target name:    name: "A"
#      · target path:    auto-resolves under Sources/A/

# 4. Update Bundler.toml (alternative runner)
#    Edit Bundler.toml, replace 3 occurrences:
#      · [apps.A]
#      · identifier = 'com.example.A'
#      · product = 'A'

Affected Files

File Change Mandatory?
consts.bzl PROJECT_NAME = "A" Yes
Sources/SwiftCrossUI-RustBackend-Template/ Rename toSources/A/ Yes
Package.swift name: (2 places), path: For SPM mode
Bundler.toml [apps.A], product, identifier For Bundler mode
Sources/A/SwiftCrossUI-RustBackend-TemplateApp.swift Struct name can staySwiftCrossUI-RustBackend-TemplateApp No
build.sh (SPM/Bundler fallback) PathSources/SwiftCrossUI-RustBackend-Template/ → Sources/A/ For SPM/Bundler mode

Files That Need NO Changes

These Buck2 files derive all paths from consts.bzl dynamically:

BUCK                ← name = PROJECT_NAME, glob(SWIFT_SRC_DIR), ...
RustBackend/BUCK     ← RUST_CRATE_NAME, RUST_LIB_NAME from consts
.buckconfig          ← alias run = root//:run (name-agnostic)
toolchains/BUCK      ← generic toolchain
cleanbuild.sh        ← clean script
cleanall.sh          ← clean script
.gitignore           ← glob patterns

Verification

./cleanbuild.sh
./build.sh
# Buck2 targets auto-update to the new name:
buck2 targets :     # outputs root//:A, root//:run
buck2 run :run      # build & run

Architecture

┌─────────────────┐    import CRustBridge    ┌──────────────────┐
│ SwiftCrossUI-RustBackend-Template      │ ◄─────────────────────── │ Swift Bridge     │
│ App.swift       │                          │ (Generated .swift)│
└───────┬─────────┘                          └────────┬─────────┘
        │ Swift calls                                │ calls C symbols
        │ hello_from_rust()                          │ __swift_bridge__$*
        │ performCalc()                              │
        │ compute_fibonacci()                        │
        ▼                                            ▼
┌──────────────────────────────────────────────────────────────┐
│                    CRustBridge (C module)                     │
│                  exposes __swift_bridge__$*                   │
└────────────────────────────┬─────────────────────────────────┘
                             │ links
                             ▼
┌──────────────────────────────────────────────────────────────┐
│                 librust_backend.a (Rust)                     │
│          hello_from_rust(), fibonacci(), ...                 │
└──────────────────────────────────────────────────────────────┘

Buck2 build flow:

RustBackend/BUCK         Root BUCK
──────────────           ─────────
 genrule                  genrule
 ┌────────────┐          ┌──────────────────────────────┐
 │ cargo build│          │ cp → SPM-expected paths       │
 │ → .a       │──dep──►  │ swift build --product        │
 │ → .h/.swift│          │ → SwiftCrossUI-RustBackend-Template binary           │
 └────────────┘          └───────────┬──────────────────┘
                                     │
                           command_alias("run")
                           ┌─────────┴──────────┐
                           │ buck2 run :run     │
                           └────────────────────┘

Adding New Rust Functions

  1. Declare in RustBackend/src/lib.rs inside the #[swift_bridge::bridge] block:
extern "Rust" {
    fn my_new_function(input: u32) -> String;
}

fn my_new_function(input: u32) -> String {
    format!("Result: {}", input * 2)
}
  1. Call from Sources/SwiftCrossUI-RustBackend-Template/SwiftCrossUI-RustBackend-TemplateApp.swift:
let result = my_new_function(42)
Text(result.toString())
  1. Rebuild: ./build.sh

Tech Stack

Library Version Purpose
swift-bridge / swift-bridge-build 0.1 Rust ↔ Swift FFI
swift-cross-ui 0.5.1 Cross-platform SwiftUI framework
Buck2 2026-05-03 Build system
GTK4 4.x Linux rendering backend

License

MIT

About

A cross-language GUI application template: SwiftCrossUI(GTK4) calls Rust functions via swift-bridge for FFI glue code, with Buck2 as the unified build system.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages