ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Ubuntu下编译RustDesk客户端:环境搭建与踩坑全记录

Ubuntu下编译RustDesk客户端:环境搭建与踩坑全记录 做远程控制这么多年工具换了一茬又一茬最后留在手边的反而还是开源方案。RustDesk 是我最近折腾得比较多的一个项目核心逻辑用 Rust 编写客户端覆盖 Windows、Linux、macOS、Android、iOS源码开放你可以自己编译、自己打包、自己改 logo、改包名、指定连接自己的服务端。这篇文章我就把自己在 Ubuntu 上编译 RustDesk 客户端Ubuntu 桌面版和 Android APK的完整过程整理出来包括环境搭建、依赖配置、编译命令以及我踩过的坑给想自己动手编译的朋友一份可以直接抄作业的参考。这篇文章适合谁如果你不想依赖公共服务器需要在公司内网或者自己可控的环境下跑远程协助或者你想给客户交付一个定制化的远程控制客户端又或者你只是想通过 RUST Flutter 的跨平台编译流程练练手这套流程都很值得走一遍。编译本身并不玄乎关键是把工具链装齐、把镜像配好、把常见报错提前看懂。1. 编译 RustDesk 前需要理顺的两件事1.1 RustDesk 编译的整体逻辑先分清客户端、服务端和 UI 层RustDesk 整个项目拆开看其实分两块一块是客户端就是我们日常装在电脑和手机上的那个图形程序另一块是服务端负责两台设备之间的信令交换和数据通路。本文主要讲客户端编译服务端编译是另外一套流程后面有条件再单独写。客户端的代码仓库是 rustdesk/rustdesk这里有个很关键的架构变化需要先说明。RustDesk 在 1.3.x 之前桌面端的界面引擎用的是 Sciter移动端用的是 Flutter所以编译老版本桌面版的时候你需要提前准备 Sciter 的动态库很多人在这一步被劝退。从 2024 年后全面迁移到 Flutter 之后整个 UI 层统一走 FlutterRust 只负责核心逻辑比如音频编解码、屏幕采集、网络通信这些重活。所以编译当前版本你本质上是在做两件事第一用 Rust 工具链把核心库编出来第二用 Flutter SDK 把界面部分和 Rust 库打包成一个完整的应用。这也是为什么后面环境准备阶段Rust 和 Flutter 两个都要装缺一不可。用一句话概括RustDesk 的“编译原理”不是单命令cargo build而是 Rust 核心库 Flutter 壳工程一起构建最终产出一个带界面的可执行文件或 APK。很多新手拿到源码后直接cargo build结果报一堆找不到依赖就是因为没有意识到当前版本已经切到 Flutter 入口了。看仓库根目录下有没有flutter文件夹有就说明这是新版 Flutter 架构没有的话才是老版 Sciter 架构可以走cargo build路线。我下面主要按新版 Flutter 架构来讲老版本的分支我会在对应位置单独标注。1.2 需要准备的软硬件清单缺一样都编不过编译这种事最怕的就是装到一半发现某个基础工具没装。我把整个依赖清单列出来版本号也标注好你对照着准备就行。工具建议版本用途说明Ubuntu22.04 LTS / 24.04 LTS宿主编译系统其他 Linux 发行版思路类似Rust 工具链1.75 或更高编译 RustDesk 核心逻辑通过 rustup 安装Flutter SDK3.x 稳定版编译桌面端 UI 和 Android APKAndroid SDKplatforms;android-34提供 Android 打包工具aapt、apksigner 等Android NDK25.2.9519653Rust 代码交叉编译到 Android 的 C/C 工具链JDKOpenJDK 17Gradle 编译 Android 工程必须Android Gradle Plugin 8 强行要求CMake3.20 以上构建 RustDesk 依赖的原生 C/C 库ninja-build、nasm、pkg-config等系统最新即可Flutter Linux 桌面端构建和部分系统库检测需要提示一下编译宿主的磁盘空间至少留出 20GB。光源码加子模块就有 2GB 以上Cargo 缓存、Gradle 缓存、Android SDK 加起来很容易超过 10GB如果你已经提前装了 Android Studio那这个数字只会更多。版本这块有个容易踩的坑Android NDK 不是越新越好。RustDesk 在 CI 里长期用的是 r25c也就是 25.2.9519653 这个版本NDK r26 之后的版本在某些依赖库的构建脚本上会有兼容性警告甚至直接报错。我一开始装了最新版 NDK编到一半链接出错换回 r25c 才顺利通过。所以别偷懒版本按表里来。2. Ubuntu 环境下完整搭建编译环境2.1 安装基础工具链把系统包一次装齐我假设你是从一台干净 Ubuntu 开始不管是实体机还是虚拟机都行但建议内存不小于 8GB否则后面 Rust 编译时容易因为内存不足直接被杀进程。先更新软件源然后安装编译所需的基础包sudo apt update sudo apt upgrade -y接着安装工具链和库依赖sudo apt install -y build-essential cmake git curl pkg-config \ ninja-build nasm python3 python3-pip \ libgtk-3-dev libayatana-appindicator3-dev \ libx11-dev libxcb1-dev libxcb-randr0-dev libxcb-shm0-dev \ libxcb-xfixes0-dev libxcb-shape0-dev libxcb-keysyms1-dev \ libxcb-cursor-dev libxss-dev libsecret-1-dev libssl-dev \ liblzo2-dev libvpx-dev libpng-dev \ openjdk-17-jdk这串包名看着长实际上每一类都有明确用途。libgtk-3-dev和libayatana-appindicator3-dev是 Flutter Linux 桌面端的界面和系统托盘必需libxcb-*这一组是 X11 协议相关RustDesk 采集和渲染时要用libssl-dev是网络加密依赖libsecret-1-dev用于存储登录凭据。JDK17 则是 Android 构建的硬性要求提前装好省得后面再回头补。我实测下来在 Ubuntu 24.04 和 22.04 上这组包都能直接装上。如果你用的是 Ubuntu 20.04默认 CMake 版本不够高需要额外用 pip 或者源码方式升级 CMake建议直接装 24.04 或 22.04 LTS省心很多。2.2 安装 Rust 并配置 Cargo 国内镜像Rust 官方推荐方式是用 rustup 安装没什么特殊原因因为它能方便地管理工具链版本和 Android 交叉编译需要的 target。执行下面命令curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh安装过程中会让你选默认工具链直接选默认 stable 就行。注意不要用sudo去执行这个脚本rustup 默认安装到当前用户目录~/.cargo用 sudo 反而会把权限弄乱。装完后让环境变量生效source $HOME/.cargo/env验证一下rustc -V cargo -V如果能看到版本号说明 Rust 主体装好了。但这里有个非常现实的问题Cargo 默认从 crates.io 拉取依赖包在部分网络环境下速度很慢或者下载到一半直接超时。建议把 Cargo 源切换到国内镜像我用的是 rsproxy 的 sparse 协议配置很简单修改~/.cargo/config.tomlmkdir -p ~/.cargo cat ~/.cargo/config.toml EOF [source.crates-io] replace-with rsproxy-sparse [source.rsproxy-sparse] registry sparsehttps://rsproxy.cn/index/ EOF这里用 sparse 协议而不是 git 协议是因为 sparse 方式请求的是单个索引文件下载量小、速度快对 git 协议经常卡死的情况改善非常明显。换完源后再跑一次cargo search如果秒出结果说明网络配置生效了。环境已经装好先别急着编译项目。让我先把 Flutter 和 Android 工具链也讲完因为后面所有编译步骤都依赖这一套环境。2.3 安装 Flutter SDK 并配置镜像仓库Flutter SDK 不需要用 apt 安装直接到官方渠道下载 Linux 版 tar.xz 压缩包就行。下载后我习惯放到/opt/flutter这样服务器上所有用户都能用。当然你放到用户目录下也完全可以。cd /tmp wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.19.6-stable.tar.xz sudo tar -xf flutter_linux_3.19.6-stable.tar.xz -C /opt/把 Flutter 的 bin 目录加入 PATH可以写在~/.bashrc里export PATH/opt/flutter/bin:$PATH source ~/.bashrcFlutter 同样会遇到下载慢的问题尤其在拉取 Dart 包和 Flutter 引擎时会非常折磨。配置两个环境变量指向国内镜像export PUB_HOSTED_URLhttps://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn这两行建议直接写进~/.bashrc持久化否则每次开新终端都得手动 export。配置完后执行flutter doctor它会检查 Flutter 环境是否完整。此时因为 Android SDK 还没装doctor 会报一些警告不用慌下一步装上就干净了。2.4 安装 Android SDK 与 NDK用命令行方式快速搞定Android 工具链安装有两条路装 Android Studio 图形界面或者只用命令行工具。我倾向于第二种因为编译脚本更清晰也方便复制到别的机器。先下载 Android commandline-tools这是官方提供的命令行工具包mkdir -p ~/android-sdk/cmdline-tools cd ~/android-sdk/cmdline-tools wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip unzip commandlinetools-linux-11076708_latest.zip mv cmdline-tools latest注意解压后要把目录重命名为latest这是 sdkmanager 的默认查找规则不这样做后续命令会找不到工具。然后配置环境变量export ANDROID_HOME$HOME/android-sdk export ANDROID_NDK_HOME$ANDROID_HOME/ndk/25.2.9519653 export PATH$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools同样写入~/.bashrc。接着安装具体组件yes | sdkmanager --licenses sdkmanager platform-tools platforms;android-34 build-tools;34.0.0 ndk;25.2.9519653sdkmanager --licenses用来接受所有许可协议首次运行必须做。后面的命令会下载 platform-tools、Android 34 平台包和指定版本的 NDK。这个过程大概要下载 1GB 左右看网络情况等待几分钟到十几分钟不等。NDK 为什么单独指定 25.2.9519653因为新版 Rust 交叉编译到 Android 时NDK 版本的编译参数有一定兼容性。r25c 这一版在 RustDesk 的 CI 流程里验证得最多踩坑最少。装完后检查一下$ANDROID_NDK_HOME目录是否存在路径正确即可。到这里Ubuntu 上的编译环境已经齐了。下面开始进入真正的编译环节先编 Linux 桌面版再编 Android APK这个顺序可以让你先验证环境有没有问题桌面版是相对快的路径。3. 编译 Ubuntu 版 RustDesk3.1 拉取 RustDesk 源码与初始化子模块这一步骤看起来简单但细节比较多。RustDesk 仓库不是单层代码而是通过 git submodule 引用了好几个第三方库比如 Rust 核心库、vcpkg 等。直接 clone 下来不更新子模块编译时会报各种“找不到目录”的错误。cd ~ git clone https://github.com/rustdesk/rustdesk.git cd rustdesk git submodule update --init --recursive--recursive参数必须带上因为子模块内部还有子模块。这个初始化过程会拉取额外的代码整体下来源码目录大概 2GB。如果你在 GitHub 拉取时网络不太稳定可以试试先把仓库导入 Gitee 再拉取或者多执行几次git submodule update --init --recursiveGit 会断点续传。还有个小建议如果你只想要当前最新稳定版可以用git tag查看版本列表然后git checkout到某个稳定 tag比如git checkout v1.3.8避免跟着 main 分支漂移时遇到依赖变化。我用最新 main 分支编过也能通过但稳妥起见还是推荐 tag 版本。3.2 Linux 桌面版编译新版 Flutter 入口与老版 cargo 入口到了这一步先看一眼仓库结构。如果根目录下有flutter文件夹说明你拿到的是新版 Flutter 架构编译 Linux 桌面包要进入flutter目录执行cd ~/rustdesk/flutter flutter build linux --release这个命令会触发整个构建过程先编译 Rust 核心库再用 Flutter 打包 Linux 桌面端期间还会用 CMake 编译若干原生依赖。第一次编译的时间非常长我这边一台 8 核 16G 内存的机器跑了接近半小时主要时间都耗在 Rust 依赖编译和第三方库构建上。耐心等着不要看到终端长时间没输出就以为死机了。编译完成后产物在~/rustdesk/flutter/build/linux/x64/release/bundle/这个 bundle 目录里的rustdesk可执行文件就是完整的 Linux 客户端。在文件管理器里双击运行或者直接在命令行执行./build/linux/x64/release/bundle/rustdesk如果你想先跑起来看看效果也可以直接用flutter run -d linux不过这是 debug 模式性能和稳定性跟 release 版差距较大日常使用还是建议打 release 包。顺便说下老版本的情况。如果你拿到的是 1.2.x 或更早的版本仓库根目录没有 flutter 文件夹构建方式是在根目录执行cargo build --release同时需要提前处理 Sciter 动态库。Sciter 这个库比较折腾现在已经不是主流路线了所以我建议直接用新版源码别折腾旧分支。3.3 编译产物怎么用自定义服务器和定制化思路很多朋友编译客户端最终目的是不让软件默认连官方公共服务器而是连自己部署的服务端。这个需求不一定需要改代码重新编译因为 RustDesk 客户端在设置项里可以直接填写服务器的地址填完重启应用就生效。真正需要重新编译的场景是你要改应用名称、图标、包名或者你需要在源码层面把服务器地址写死让终端用户无需配置直接连你的服务。改名称和图标这种事在 Flutter 工程里改起来非常容易。Linux 桌面版的应用名称跟 Flutter 工程里的linux/runner/my_application.cc相关图标在linux/runner/resources目录下面。Android 版的名称和图标分别在AndroidManifest.xml和android/app/src/main/res目录。改完再执行一次flutter build linux --release或flutter build apk --release就会打出属于你自己的客户端。需要特别提醒的是编译产物默认是未签名或 debug 签名的状态Linux 版无所谓但 Android 版如果要分发给别人安装必须做正式的 release 签名否则有的手机默认会拦截安装。签名这部分我放到下一节细说。4. 编译 Android 版 RustDesk4.1 让 Flutter 正确识别 Android 工具链Android 版编译的底层原理和 Linux 版基本一致区别在于 Flutter 需要调用 Android SDK、NDK 和 Gradle把 Rust 核心代码交叉编译成 Android 能识别的.so动态库再打进 APK。开始之前先确认 Flutter 能识别我们已经装好的 Android 工具链。执行flutter doctor -v重点看Android toolchain那一行的状态。如果报错说找不到 SDK多半是ANDROID_HOME环境变量没有正确设置重新source ~/.bashrc或者检查路径。如果提示许可证未接受执行flutter doctor --android-licenses一路输y即可。这个命令会接受所有 Android SDK 许可证跟之前sdkmanager --licenses的作用类似但 Flutter 有自己独立的检测机制两个都执行过最稳妥。检查无误后就可以进入flutter目录执行构建了。如果flutter doctor里还有别的警告比如未安装 Chrome 之类的不影响 Android 构建可以暂时忽略。4.2 生成 release 签名并构建 APKAPK 的 release 构建过程比 Linux 版多一个签名步骤。为啥一定要签名Android 系统要求所有安装包必须有签名证书否则系统拒绝安装。debug 模式会自动用一个调试证书签名但 debug 证书只在开发机上有效分发给别人安装时可能会出现签名不一致的问题而且第三方渠道也普遍不接受 debug 签名包。所以我们要先生成一个自己的密钥库。用 JDK 自带的keytool工具keytool -genkey -v -keystore ~/rustdesk-release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias rustdesk执行过程中会让你输入密钥库密码、姓名、组织等信息这些信息会写入证书。密码一定记住后面签名要用。接下来在 Android 工程的key.properties中配置签名信息。文件位置在android/key.properties如果不存在就自己创建storePassword你的密码 keyPassword你的密码 keyAliasrustdesk storeFile/home/你的用户名/rustdesk-release.jks这里注意storeFile要写绝对路径不要写~Gradle 不会自动展开波浪号。配置完成后执行构建命令cd ~/rustdesk/flutter flutter build apk --release这个过程比 Linux 版更漫长。第一次构建要下载 Gradle 本身以及一堆 Maven 依赖加上 Rust 交叉编译三个 ABI 的.so库我机器上大概花了四十分钟。如果你网络拉 Gradle 很慢可以在android/gradle/wrapper/gradle-wrapper.properties里把distributionUrl换成国内镜像地址但这步是可选的多数情况下默认链接能跑通。构建成功的提示会在最后显示 APK 输出路径。默认产物路径是build/app/outputs/flutter-apk/app-release.apk这个 APK 包含所有平台的二进制体积相对较大。如果只想在真机上用可以拆分成按 ABI 单独打包flutter build apk --release --split-per-abi拆分后的产物会变成三个文件app-arm64-v8a-release.apk适用绝大多数 64 位手机app-armeabi-v7a-release.apk适用老旧 32 位手机app-x86_64-release.apk适用模拟器或某些平板实测下来拆分后的 arm64 包会比不分架构的通用包小很多安装也更快。发给自己用建议直接选 arm64 包。4.3 安装到手机验证编译结果APK 编出来后验证方式很简单。先用 USB 连接手机开启开发者选项和 USB 调试然后执行adb install -r app-arm64-v8a-release.apk如果没有 adb你在前面已经通过 SDK platform-tools 装好了直接执行即可。-r参数表示覆盖安装方便反复测试。安装完成后打开应用手机授权的界面会让你授予屏幕录制、辅助功能等权限按提示允许即可。我第一次编译成功后在手机上看到自己的自定义客户端那种感觉确实不一样。不过这里有个容易忽略的细节如果你的手机和电脑不在同一个局域网第一次连接外部设备时客户端默认会去连公共服务器走公网转发。这在功能演示时没问题但如果要体验内网直连还是建议连服务端地址后测试那个才是完整的自建链路。5. 编译排错实录我踩过的坑和排查思路5.1 依赖下载慢、超时失败怎么办这应该是编译 RustDesk 时最频繁遇到的问题。Cargo 依赖、Flutter 引擎、Gradle 包每一个环节都有可能在半路卡住。解决方案不是反复重试而是先确认你配好了镜像。Cargo 的镜像配置在前面已经写了rsproxy 是国内目前比较稳的一个 Rust 镜像。Flutter 的镜像设置了PUB_HOSTED_URL和FLUTTER_STORAGE_BASE_URL后大部分 Dart 包和引擎文件的下载速度会明显改善。Gradle 如果一直下不动可以在android/gradle/wrapper/gradle-wrapper.properties里修改distributionUrl把默认的 services.gradle.org 换成腾讯镜像。用镜像之后还有超时可以手动重建缓存。我的经验是别只看报错信息的最后一行往上翻找到卡住的 URL再用浏览器访问这个 URL 试试连通性。如果能访问问题多半是连接被意外断开多执行一次构建命令让它断点续传即可如果不能访问果断换镜像源。5.2 NDK、CMake 版本不匹配导致的编译失败这类问题在编译过程中的表现非常典型Rust 核心库编译到 Android 时调用 NDK 的 clang 编译器但 Flutter/Gradle 里的 CMake 版本和 NDK 版本如果不兼容会提示找不到编译器工具链或者报unsupported NDK version。我第一次用 NDK r26 的时候就遇到过。解决办法分两步第一步把 NDK 换成 25.2.9519653前面强调过很多次这是 RustDesk CI 验证最充分的版本第二步确保系统 CMake 至少 3.20Ubuntu 22.04 自带的 CMake 版本符合要求Ubuntu 20.04 需要升级。如果flutter doctor显示的 CMake 版本太低可以用 pip 装新版 CMake或者直接在项目里指定 Android SDK 自带的 CMakesdkmanager cmake;3.22.1然后在flutter目录下创建local.properties写入sdk.dir/home/你的用户名/android-sdk ndk.dir/home/你的用户名/android-sdk/ndk/25.2.9519653 cmake.dir/home/你的用户名/android-sdk/cmake/3.22.1注意路径不要写错写完重新构建即可。5.3 内存不足导致的编译进程被杀Rust 编译的 debug 和 release 模式内存占用差别很大。默认 release 编译会启用大量优化链接阶段尤其吃内存8GB 内存的机器在链接 RustDesk 核心库时可能会出现Killed字样这就是系统内存不足进程被 Linux 内核收走了。解决思路有两个。一是减少并行编译数量在~/.cargo/config.toml里加[build] jobs 2这样会把 Rust 编译并行度降到 2能显著降低峰值内存但编译时间会变长。二是给系统增加 Swap 空间兜底sudo dd if/dev/zero of/swapfile bs1G count4 sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile这两招可以组合用。如果机器长期吃紧建议升级内存毕竟编译这东西内存就是效率。5.4 补充一份常见错误速查表排查过程中我把能想到的典型报错整理成了表格方便你遇到问题时快速对照。报错现象原因解决办法error: linker cc not found缺少系统编译工具链sudo apt install build-essentialNo such file or directory且指向 submodule子模块未初始化git submodule update --init --recursiveCould not resolve host github.com网络拉取失败配置镜像或稍后重试不要强行中断CMake was unable to find a build program缺少 ninja 或 cmakesudo apt install ninja-build cmakeExecution failed for task :app:processReleaseResourcesJDK 版本不符换成 OpenJDK 17并检查JAVA_HOMENDK not configured环境变量或 local.properties 写错确认ANDROID_NDK_HOME路径删除缓存后重试undefined reference to ...依赖库版本冲突清理 target 目录重新编译确认 NDK 为 r25c最后一类问题最坑因为它表面上是代码错误实际上可能是之前用了其他版本的 NDK 或 CMake产生了脏缓存。遇到不明所以的链接错误先执行cargo clean cd flutter flutter clean flutter pub get然后重新构建。别嫌麻烦我实测很多“诡异错误”都是缓存导致的清除后一次性通过。写在最后我自己第一次编译 RustDesk 的时候从环境准备到最终打出 APK断断续续花了一整个下午中途经历了不少报错和镜像问题。等真正跑通了再回头复盘发现难点并不在代码本身而是工具链之间的兼容性。现在这套流程我已经在好几台机器上走过了只要按顺序来基本不会卡壳。给你一个实用建议第一次尝试不要直接选 Android先编译 Linux 桌面版验证整个环境没问题再进入 Android 构建流程。这样可以把问题范围缩小不至于一上来就被 Gradle 和 NDK 的报错吓到。编译这个东西不怕报错就怕不看日志就盲目重试。你按这篇文章走一遍一定能在自己机器上得到一个真正属于你的 RustDesk 客户端。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进