使用 Doom Emacs 构建 iOS 应用
速览
本文探讨了使用 Doom Emacs 作为主要开发环境来构建 iOS 应用的可行性与优势。通过整合 Emacs 的强大编辑功能与 iOS 开发工具链,开发者可以获得更流畅、高效的编码体验。
AI 深度解读
在 Doom Emacs 中构建 iOS 应用:脱离 Xcode 的完整工作流
背景
长期以来,iOS 开发被视为 Xcode 的专属领域。对于习惯使用 Vim 或 Emacs 等高级文本编辑器的开发者而言,Xcode 往往被视为一个庞大、沉重且封闭的“黑盒”。作者分享了他如何完全脱离 Xcode 图形界面,仅通过命令行工具和 Doom Emacs 配置,完成从编写 Swift 代码、构建、模拟器调试到日志监控的完整 iOS 应用开发闭环。
这一实践的核心驱动力源于作者对 Emacs 工作流的深度依赖。作为一名拥有四年 Doom Emacs 使用经验的开发者,他已在 Rust、Elixir、Kotlin/Android 和 Web 开发中建立了统一的高效配置。然而,回到 iOS 开发时,Xcode 的隔离感让他感到不适。为了实现多语言开发体验的一致性,他决定深入研究 Apple 提供的底层命令行工具,并将其整合进 Emacs 生态中。
核心内容
1. 核心理念:Xcode 只是命令行工具的包装层
Apple 提供了一整套强大的命令行工具,但大多数 iOS 开发者从未直接接触过它们。Xcode 本质上是一个集成了这些工具的图形化封装器。如果开发者愿意自行编排这些工具,任何支持运行 Shell 命令并读取进程输出的编辑器(如 Doom Emacs)都可以构建出完整的 iOS 工作流。
作者为此编写了一个约 1000 行的 modules/ios.el 模块,实现了以下核心功能:
- 构建:
SPC i b触发构建。 - 安装与运行:
SPC i s在选定的模拟器上安装并启动应用。 - 日志监控:
SPC i l流式传输过滤后的日志。 - 项目脚手架:
SPC i n快速生成新的 SwiftUI 项目。
2. 关键命令行工具解析
要脱离 Xcode,必须掌握以下核心工具:
xcodebuild:编译.xcodeproj或.xcworkspace的核心工具。它接受 Scheme、SDK、Destination 以及build、clean、test等操作参数。当你点击 Xcode 的 Run 按钮时,背后调用的正是它。xcrun simctl:控制 iOS 模拟器的工具。支持启动、安装、卸载、启动应用、终止进程、截图以及覆盖状态栏等操作。模拟器 App 中能做的所有点击操作,均可通过此命令实现。xcrun swift-format:Apple 官方的 Swift 代码格式化工具,支持标准输入/输出流。sourcekit-lsp:Apple 为 Swift 提供的语言服务器协议(LSP)实现。它位于 Xcode 的 Toolchain 中,提供代码补全、跳转定义、错误检查和重构功能。xcode-build-server(非 Apple 官方,但至关重要):生成buildServer.json文件。由于sourcekit-lsp默认无法感知项目的具体构建标志(Build Flags)和模块配置,该工具通过读取.xcodeproj并询问xcodebuild实际编译方式,为 LSP 提供必要的上下文信息。xcodegen(非 Apple 官方):通过 YAML 文件生成.xcodeproj。作者使用它来自动化项目脚手架,避免手动打开 Xcode 的项目编辑器。
3. Doom Emacs 配置架构
作者的配置结构清晰,将核心配置与语言模块分离:
config.el:极简配置,仅设置字体、主题和目录,并加载各个模块。modules/ios.el:存放 iOS 开发的核心逻辑。modules/keybindings.el:集中管理所有快捷键映射,便于维护和检索。init.el:启用(swift +lsp)语言模块,自动获得swift-mode和基础的 LSP 支持。
4. 解决 LSP 配置痛点
指向正确的 sourcekit-lsp
Mac 上通常存在两个 sourcekit-lsp 二进制文件:一个在命令行工具目录,另一个在活跃的 Xcode 中。版本不一致会导致诊断信息混乱。作者通过 xcode-select -p 获取当前活跃的开发者目录,并强制设置环境变量 DEVELOPER_DIR 和 lsp-sourcekit-executable,确保 Emacs 子进程使用的工具链与 Xcode 一致。
编辑器基础设置
- 启用
lsp-deferred。 - 禁用内联提示(Inlay Hints)以减少视觉噪音。
- 设置 Swift 缩进为 4 个空格。
- 使用
apheleia包实现保存时自动格式化,调用xcrun swift-format。
自动化 buildServer.json 生成
sourcekit-lsp 默认是“盲目”的,不知道项目的构建配置。作者编写了一个 Emacs Lisp 函数,在打开 Swift 文件时自动检测是否存在 buildServer.json。如果缺失,则调用 xcode-build-server 生成该文件,从而让 LSP 获得完整的代码感知能力。
关键要点
- Xcode 并非不可替代:iOS 开发的底层能力完全由命令行工具提供,图形界面仅是可选的封装。
- 工具链整合是关键:
xcodebuild负责构建,simctl负责模拟器控制,sourcekit-lsp负责代码智能,xcode-build-server负责连接构建配置与 LSP。 - Emacs 的强大编排能力:通过 Emacs Lisp 脚本,可以将分散的命令行工具串联成流畅的工作流(如自动检测、自动构建、自动日志流)。
- 一致性体验:通过为 iOS 开发编写专门的 Doom Emacs 模块,实现了与 Rust、Elixir 等其他语言开发相同的快捷键和操作逻辑,消除了上下文切换的认知负担。
- 自动化消除摩擦:通过 Hook 机制自动处理
buildServer.json的生成,避免了手动维护配置文件的繁琐。
意义与影响
这一实践展示了高级文本编辑器在专业软件开发中的巨大潜力。它打破了“iOS 开发必须使用 Xcode”的固有认知,证明了通过深入理解底层工具链,开发者可以在任何支持脚本化的环境中构建出媲美甚至超越 IDE 的开发体验。
对于 Emacs/Vim 用户而言,这是一份极具参考价值的技术蓝图,展示了如何将 Linux/Unix 哲学下的工具链思维应用于封闭的 Apple 生态。对于更广泛的开发者社区,它强调了“理解工具本质”的重要性——当开发者不再依赖 GUI 的黑盒,而是直接掌控底层命令时,他们获得了更高的灵活性、可定制性以及跨平台工作流的一致性。
