把 Xcode 项目搬到 Windows 上开发,和 Mac 同事共用一个仓库
团队里已经有一个在 Mac 上用 Xcode 开发的 iOS 项目,你想在 Windows 上接着写代码、编译、装到 iPhone 上调试,提交后 Mac 同事照常用 Xcode 打开。这篇按顺序讲怎么把工程在 Windows 上跑起来,以及两边共用一个仓库时要约定的几件事。
需要准备的是仓库的访问权限、一部 iPhone 和数据线、团队开发者账号下的证书,以及装好 KXBuild 和 VS Code 插件的电脑,还没装的按安装页操作。
拉取代码
Mac 上的源码和工程文件都用 LF 换行,而 Windows 版 Git 默认检出时把换行改成 CRLF。克隆前先让 Git 保持 LF,避免脚本在 Windows 上执行出错,也不会让你提交的文件在 Mac 同事那边显示整文件改动。
1git config --global core.autocrlf input
2git clone git@example.com:team/MyApp.git D:\proj\MyApp
工程放在短路径下,例如 D:\proj。目录层级太深时 Windows 可能报文件名过长。
用 VS Code 打开
在 VS Code 中「文件 → 打开文件夹」,选 .xcodeproj 或 .xcworkspace 所在的目录,也可以把这个目录直接拖进 VS Code。用 CocoaPods 的工程打开 Podfile 所在目录。
打开后左侧 KXBuild 视图列出目录下的工程和每个 target。仓库里有多个工程时,F5 和「构建」作用于带星标的启动项目,点工程节点即可切换,详见侧边栏与状态栏。

体检
第一次打开工程先运行一次体检。它会检查编译环境、CocoaPods 和设备驱动,并准备好 iOS 端的工程。以下两种做法任选其一。
- VS Code 插件。在 KXBuild 视图标题栏的「···」中运行「体检并修复开发环境」。
- 命令行。在工程目录执行下面的命令。
1kxbuild doctor .\MyApp.xcodeproj
KXBuild 视图里 target 读不出来、构建报环境相关的错误时,也先运行一次体检。
安装依赖
Swift Package
工程里通过 Xcode「Add Package Dependencies」加的 Swift Package 不用手动处理,第一次构建前自动下载并解析,版本按仓库里的 Package.resolved 来,和 Mac 同事用的完全一样。这个文件在 .xcodeproj/project.xcworkspace/xcshareddata/swiftpm/(用工作区的在 .xcworkspace/xcshareddata/swiftpm/),要提交到仓库。
拉不下包或者报找不到包时,强制重新解析一次,相当于 Xcode 的 Reset Package Caches。
1kxbuild resolve .\MyApp.xcodeproj --force
要在 Windows 上给工程新加一个包,在命令面板运行 KXBuild: 添加 Swift Package 依赖…,按提示输入包的 Git 地址并选择产品,效果和 Xcode 里添加一样,Mac 同事拉取后直接能用。详见 Swift 技术栈。
CocoaPods
在 Podfile 所在目录运行一次 pod install,生成 Pods 目录和 .xcworkspace。之后编译和调试都用 .xcworkspace,用 .xcodeproj 会找不到 Pods 里的库。
1pod install
同事改了 Podfile 或者 Podfile.lock 变了,拉取代码后要重新 pod install,否则构建会提示 sandbox 和 Podfile.lock 不同步。Podfile 写法、镜像源和常见问题见 CocoaPods。
确认 scheme
工程有哪些 scheme、target 和 Bundle ID,可以用下面的命令查看。
1kxbuild project info .\MyApp.xcodeproj
同事在 Xcode 里建的 scheme 如果没有勾选 Shared,只存在他自己的 xcuserdata 里,Windows 上看不到,构建时会报 scheme not found。请他在 Xcode 的 Product → Scheme → Manage Schemes 中给要用的 scheme 勾上 Shared,这些 scheme 会保存到 xcshareddata/xcschemes,提交后两边都能用。
签名
Windows 上没有 Xcode 替你下载证书,需要把证书和描述文件放进证书目录。团队已有的证书直接用。
- 证书。请有权限的同事在 Mac 的「钥匙串访问」里把 Apple Development 证书连同私钥导出为 .p12,只有 .cer 不行。也可以用你自己的 Apple ID 在团队下另建一张开发证书。
- 描述文件。先在开发者网站的 Devices 里登记你的 iPhone 的 UDID,再重新生成或下载包含这台设备的 Development 描述文件。UDID 用
kxdevice device list查看,第一列就是。
把两个文件放进工程根目录的 keychain 文件夹,在同目录的 password.properties 里写一行「文件名=密码」。只想放一次、所有工程共用的,放到 KXBuild 安装目录下的 keychain 文件夹。
1development.p12=123456
工程里原有的签名设置不用改。构建时和 Xcode 一样按工程的签名设置选证书,自动签名的工程按 Bundle ID 和团队 ID 匹配描述文件,所以证书和描述文件要属于工程里 DEVELOPMENT_TEAM 的那个团队。报错时对照证书与签名排查。
在真机上运行
用数据线接上 iPhone,在 KXBuild 视图的「设备」节点点一下选中它,第一次连接要装设备驱动、在手机上点信任并打开开发者模式,见设备准备。然后在源码里打断点,按 F5,KXBuild 构建、签名、安装、启动并停在断点上。Swift 和 Objective-C 代码都能断点。
工程有多个 app target 时按 F5 会让你选一个。不想每次都选,可以在 target 行上直接点「构建并运行」,或者在 launch.json 里固定,写法见运行与调试。
和 Mac 同事协作
.gitignore 该忽略什么
个人状态、构建产物和证书不进仓库。下面是一份两边都适用的写法,已有 .gitignore 的补上缺的几行即可。
1# Xcode 个人状态
2xcuserdata/
3*.xcuserstate
4.DS_Store
5
6# 构建产物
7DerivedData/
8build/
9compile_commands.json
10
11# 证书目录,含私钥和密码
12keychain/
xcuserdata 里是每个人的断点、窗口布局和未共享的 scheme,提交了会互相覆盖。build/ 是 KXBuild 放 ipa 的地方。compile_commands.json 是 Windows 上代码提示用的,会自动生成。keychain/ 里有私钥和密码,一定不能提交。
要提交的是 .xcodeproj 里的 project.pbxproj、xcshareddata 目录(共享 scheme 和 Package.resolved),以及 Podfile 和 Podfile.lock。
Pods 目录要不要提交
两种做法 CocoaPods 官方都认可。不提交 Pods 目录,仓库小、合并清爽,每个人拉取后自己 pod install,多数团队这样做。提交 Pods 目录,拉下来就能编译,不依赖网络和镜像源,但每次升级依赖都会带来大量文件改动。无论选哪种,Podfile.lock 都要提交,保证两边装到的版本一致。
project.pbxproj 合并冲突
两个人同时加文件、改构建设置时,project.pbxproj 最容易冲突。减少冲突的几个做法。
- 勤拉取、小提交。加完文件尽快提交,不要攒很多改动一起合并。
- 让 Mac 同事把分组转成文件夹。Xcode 16 起新建的工程默认用文件夹(蓝色图标),目录里的文件自动参与编译,加文件不再改动 project.pbxproj。老工程的分组(黄色图标)可以在 Xcode 里右键选「Convert to Folder」转换。
- 改设置用编辑器。在 Windows 上改构建设置时用工程设置编辑器,保存时只改动涉及的那几行,不会重排整个文件。
真的冲突了,打开 project.pbxproj 手动解决,两边新加的条目通常都要保留,删掉冲突标记即可。解决后先在 Windows 上构建一次,确认工程能正常读取再提交。
工程还是分组结构时,在 Windows 上新建的源文件要加进 project.pbxproj 才会参与编译。这类改动最稳妥的做法是请 Mac 同事在 Xcode 里把文件加进工程,或者先转成文件夹结构。
Storyboard 和 XIB
Storyboard、XIB、资源目录和 Core Data 模型在 Windows 上都能正常编译,但没有 Interface Builder,不能可视化编辑界面文件。约定界面文件在 Mac 上改,Windows 上照常编译和运行。在 Windows 上开发的新界面可以用 SwiftUI 或者纯代码写 UIKit,两边都能改。
Storyboard 是 XML,文本编辑器能打开,但手工改约束和连线容易出错,除了改个文字、改个类名这类小改动,不建议在 Windows 上直接编辑。多人同时改同一个 Storyboard 也容易冲突,界面较多的项目可以按模块拆成多个 Storyboard。
Run Script 脚本
Build Phases 里的 Run Script 在 Windows 上同样会执行。脚本里调用了只在 Mac 上安装的工具,例如用 Homebrew 装的 SwiftLint、SwiftGen,Windows 上会找不到命令导致构建失败。这类脚本先判断命令是否存在再调用,找不到就跳过。
1if command -v swiftlint >/dev/null 2>&1; then
2 swiftlint
3else
4 echo "warning: swiftlint not installed, skipped"
5fi
链接报 …vpfi 未定义
Debug 构建在链接阶段报 undefined symbol: …vpfi,是开源 Swift 编译器按文件编译时的已知问题。出现在 @State private var count = 0 这类带初始值的属性上,而结构体的 init 写在另一个文件里。远程 Swift Package 默认已经整模块编译,报错的是工程自己的代码或本地包。
不用改代码,在自己的电脑和构建机上设置环境变量 KXBUILD_SWIFT_WHOLE_MODULE=all,重开 VS Code 后再构建,所有 Swift 目标都改为整模块编译,工程文件不变,Mac 同事那边也不受影响。代价是改一个文件要重新编译整个模块。
1setx KXBUILD_SWIFT_WHOLE_MODULE all
取值说明见目录与环境变量。
修改常见配置
不用打开 Xcode 也能改工程配置,改完的格式和 Xcode 保存的一样,Mac 同事拉取后没有多余的改动。
- 工程设置。在 KXBuild 视图中右键 target 选「KXBuild: 编辑目标设置」,General 页可以改 Display Name、Bundle Identifier、版本号、最低 iOS 版本和签名方式,Build Settings 页和 Xcode 一样能看到每个设置在哪一层生效。详见工程设置编辑器。
- Info.plist 与 entitlements。双击
Info.plist、.entitlements或PrivacyInfo.xcprivacy打开表格编辑器,加权限说明文字、改 URL Scheme、调 ATS 设置都在这里,保存时保持文件原有的格式和缩进。详见属性列表编辑器。
