团队里已经有一个在 Mac 上用 Xcode 开发的 iOS 项目,你想在 Windows 上接着写代码、编译、装到 iPhone 上调试,提交后 Mac 同事照常用 Xcode 打开。这篇按顺序讲怎么把工程在 Windows 上跑起来,以及两边共用一个仓库时要约定的几件事。
需要准备的是仓库的访问权限、一部 iPhone 和数据线、团队开发者账号下的证书,以及装好 KXBuild 和 VS Code 插件的电脑,还没装的按安装页操作。更多教程可以直接看KXBuild官网:https://www.kxbuild.net/zh
Mac 上的源码和工程文件都用 LF 换行,而 Windows 版 Git 默认检出时把换行改成 CRLF。克隆前先让 Git 保持 LF,避免脚本在 Windows 上执行出错,也不会让你提交的文件在 Mac 同事那边显示整文件改动。
1git config --global core.autocrlf input2git clone git@example.com:team/MyApp.git D:\proj\MyApp
工程放在短路径下,例如
D:\proj。目录层级太深时 Windows 可能报文件名过长。
在 VS Code 中「文件 → 打开文件夹」,选
.xcodeproj 或
.xcworkspace 所在的目录,也可以把这个目录直接拖进 VS Code。用 CocoaPods 的工程打开 Podfile 所在目录。
打开后左侧 KXBuild 视图列出目录下的工程和每个 target。仓库里有多个工程时,F5 和「构建」作用于带星标的启动项目,点工程节点即可切换,详见侧边栏与状态栏。
第一次打开工程先运行一次体检。它会检查编译环境、CocoaPods 和设备驱动,并准备好 iOS 端的工程。以下两种做法任选其一。
1kxbuild doctor .\MyApp.xcodeproj
KXBuild 视图里 target 读不出来、构建报环境相关的错误时,也先运行一次体检。
工程里通过 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 技术栈。
在 Podfile 所在目录运行一次
pod install,生成 Pods 目录和
.xcworkspace。之后编译和调试都用
.xcworkspace,用
.xcodeproj 会找不到 Pods 里的库。
1pod install
同事改了 Podfile 或者 Podfile.lock 变了,拉取代码后要重新
pod install,否则构建会提示 sandbox 和 Podfile.lock 不同步。Podfile 写法、镜像源和常见问题见 CocoaPods。
工程有哪些 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 替你下载证书,需要把证书和描述文件放进证书目录。团队已有的证书直接用。
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 里固定,写法见运行与调试。
个人状态、构建产物和证书不进仓库。下面是一份两边都适用的写法,已有 .gitignore 的补上缺的几行即可。
1# Xcode 个人状态 2xcuserdata/ 3*.xcuserstate 4.DS_Store 5 6# 构建产物 7DerivedData/ 8build/ 9compile_commands.json1011# 证书目录,含私钥和密码12keychain/
xcuserdata 里是每个人的断点、窗口布局和未共享的 scheme,提交了会互相覆盖。
build/ 是
KXBuild 放 ipa 的地方。
compile_commands.json 是 Windows 上代码提示用的,会自动生成。
keychain/ 里有私钥和密码,一定不能提交。
要提交的是
.xcodeproj 里的
project.pbxproj、
xcshareddata 目录(共享 scheme 和 Package.resolved),以及 Podfile 和 Podfile.lock。
两种做法 CocoaPods 官方都认可。不提交 Pods 目录,仓库小、合并清爽,每个人拉取后自己
pod install,多数团队这样做。提交 Pods 目录,拉下来就能编译,不依赖网络和镜像源,但每次升级依赖都会带来大量文件改动。无论选哪种,Podfile.lock 都要提交,保证两边装到的版本一致。
两个人同时加文件、改构建设置时,
project.pbxproj 最容易冲突。减少冲突的几个做法。
真的冲突了,打开
project.pbxproj 手动解决,两边新加的条目通常都要保留,删掉冲突标记即可。解决后先在 Windows 上构建一次,确认工程能正常读取再提交。
工程还是分组结构时,在 Windows 上新建的源文件要加进 project.pbxproj 才会参与编译。这类改动最稳妥的做法是请 Mac 同事在 Xcode 里把文件加进工程,或者先转成文件夹结构。
Storyboard、XIB、资源目录和 Core Data 模型在 Windows 上都能正常编译,但没有 Interface Builder,不能可视化编辑界面文件。约定界面文件在 Mac 上改,Windows 上照常编译和运行。在 Windows 上开发的新界面可以用 SwiftUI 或者纯代码写 UIKit,两边都能改。
Storyboard 是 XML,文本编辑器能打开,但手工改约束和连线容易出错,除了改个文字、改个类名这类小改动,不建议在 Windows 上直接编辑。多人同时改同一个 Storyboard 也容易冲突,界面较多的项目可以按模块拆成多个 Storyboard。
Build Phases 里的 Run Script 在 Windows 上同样会执行。脚本里调用了只在 Mac 上安装的工具,例如用 Homebrew 装的 SwiftLint、SwiftGen,Windows 上会找不到命令导致构建失败。这类脚本先判断命令是否存在再调用,找不到就跳过。
1if command -v swiftlint >/dev/null 2>&1; then2 swiftlint3else4 echo "warning: swiftlint not installed, skipped"5fi
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 同事拉取后没有多余的改动。
Info.plist、
.entitlements 或
PrivacyInfo.xcprivacy 打开表格编辑器,加权限说明文字、改 URL Scheme、调 ATS 设置都在这里,保存时保持文件原有的格式和缩进。详见属性列表编辑器。来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047459/viewspace-3186650/ ,如需转载,请注明出处,否则将追究法律责任。