iOS XcodeGen使用参考
资料
XcodeGen--Github
Better iOS projects: Getting (nearly) rid of Xcodeproject - A (not so) short Introduction to Xcodegen
Xcodegen构建Xcode Project
痛点
Xcode 使用项目文件 .xcodeproj 文件来捆绑 IDE 的源代码和资源。在大多数情况下是正常工作的,但它有以下几个缺点:
-
在不同的分支上添加了源码文件或资源后无法确定文件是否正确,虽然说你可以手动去解决.xcodeproj 文件中的合并冲突。
-
如果想要同步电脑上的文件夹结构或者项目中的group结构,我们往往是通过人工手动来决定,这就难免会造成混淆。幸运的是已经有工具可以来解决这个问题了,比如synx或xcodeproj gem的排序功能。
-
Xcode 只会在编译后才会提示你项目中存在文件的丢失。
-
编写依赖关系并构建多个目标的脚本可能会变得非常麻烦。
简介
XcodeGen 是一个工具,它允许我们从名为 project.yml
的文件中的定义生成 xcodeproj 文件。由于 xcodeproj 文件可以随时生成,我们甚至不必将它保存在我们的 git 中并且可以忽略它。
两个最重要的功能:
-
可以通过这种方式为各种平台(iOS,tvOS,macOS,watchOS)定义各种 Xcode target(application,frameworks 等)。
-
它还允许将源文件的文件夹连接到目标,从而更容易管理哪些源代码文件包含在哪个目标中。
另一种脚本生成 .xcodeproj 的方式是 gem xcodeproj
安装
使用 homebrew 安装
brew install xcodegen
或使用 mint 安装(mint 是一个包管理器)
mint install yonaskolb/xcodegen
project.yml
格式
在项目的根目录下创建 project.yml 文件。
cd path/
touch project.yml
open project.yml
文件内容:
name: AppName # 工程名
options: # 项目的一些常规配置
bundleIdPrefix: com.abc # 假定 BundleID: com.abc.project
developmentLanguage: zh-Hans # 可选
settings:
DEVELOPMENT_TEAM: ASJDAJS # 需要去 developer.apple.com 后台获取
# 上面是 PROJECT 文件中的配置
# 下面是 TARGETS 文件中的配置
targets:
AppName:
type: application
platform: iOS
deploymentTarget: "10.3"
sources:
#Sources
- subModule # 可选,如果项目有其他 module:例如 FileUpload-iOS/FileUpload
- path: AppName # 主项目
dependencies: # 可选,如果项目依赖某些静态库,如果依赖某些动态库 例如 NetworkExtension,方法见下
- framework: AppName/apath/bpath/cpath/xxx.framework
- sdk: CoreData.framework # 动态库可使用 sdk 类型添加
- sdk: libsqlite3.tbd
settings:
INFOPLIST_FILE: AppName/apath/Info.plist # 生成 info.plist
GCC_PREFIX_HEADER: AppName/apath/PrefixHeader.pch # pch 文件路径
# OTHER_LDFLAGS: "$(inherited) -framework CoreData" # 可选, 如果 "sdk:" 方式无法添加动态库 可尝试这种方式
PRODUCT_BUNDLE_IDENTIFIER: M.Practice
-
options - developmentLanguage: 如果不同分支上的项目生成不同 App,例如 cn-release 打包 CNAPP,kr-release 打包 KRAPP,且它们 Localization 中 Development Languagae 各不相同时,需要在每个分支上配置不同的参数。
-
targets - AppName - sources - path - excludes: 添加需要排除的文件
-
targets - AppName - settings:对应的是 TARGETS - Build Settings 中的配置
- OTHER_LDFLAGS: Other Linker Flags,添加动态库
问题
- 1> project.pbxproj 每次都变更
因为文件是由 xcodegen 生成出来的,所以此文件不需要纳入管理。
在 .gitignore 文件中忽略不掉的原因:该文件之前已经在暂存区了,所以忽略不掉,需要执行 git rm 将它从暂存区删掉。
git rm /path/Practice/Practice.xcodeproj/project.pbxproj
-
2> Missing Localizability
解决方法:目前先放着不管,因为解决办法全是基于修改.xcodeproj的,xcodegen每次重新生成文件,修改就会被重置掉。
https://github.com/CocoaPods/CocoaPods/issues/8494
-
3> Remove Duplicate References in Build Phase
解决办法:添加 excludes,在项目中排除静态库
-
4> pod update 阶段警告
解决办法:
-
5> Main Thread Checker 设置
在更新 Xcode 之后,NerdyUI 必须取消 Main Thread Checker 才可以使用 .color 方法
-
6> Parsing project spec failed: Decoding failed at "type": Nothing found
解决办法:一定要 project.yml 文件中各项的对齐情况,十分严格
- 7> 本地化文件成散装的
最好将 .string 文件放在 Localized 文件夹下,不要放在根目录中。
生成 TestTargets
如果原项目包含 Tests 和 UI Tests,可以在 project.yml 文件中添加 target
XcodegenApp-iOS-Tests:
type: bundle.unit-test
platform: iOS
deploymentTarget: "10.3"
sources:
- path: XcodegenAppTests
dependencies:
- target: XcodegenApp
XcodegenApp-iOS-UITests:
type: bundle.ui-testing
platform: iOS
sources:
- path: XcodegenAppUITests
dependencies:
- target: XcodegenApp
用法
回到终端,在项目根目录下输入命令 xcodegen 并回车。
options:
- --spec: .yml或.json项目规范的可选路径。默认为project.yml
- --project: 生成项目的目录的可选路径。默认情况下是所在的目录。
- --quiet: 禁止显示信息和成功消息。
- --use-cache: Used to prevent unnecessarily generating the project. If this is set, then a cache file will be written to when a project is generated. If xcodegen is later run but the spec and all the files it contains are the same, the project won't be generated.
- --cache-path: A custom path to use for your cache file. This defaults to ~/.xcodegen/cache/{PROJECT_SPEC_PATH_HASH}
优化脚本:
vim setup.sh
i
xcodegen && pod update --no-repo-update
esc
:wq
执行脚本:
sh setup.sh
增加忽略
- 忽略 project.pbxproj:
因为文件是由 xcodegen 生成出来的,所以此文件不需要纳入管理。
在 .gitignore 文件中忽略不掉的原因:该文件之前已经在暂存区了,所以忽略不掉,需要执行 git rm 将它从暂存区删掉。
git rm /path/Practice/Practice.xcodeproj/project.pbxproj
- 其他忽略
*.xcworkspace
*.xcodeproj
.DS_Store
模板
name: Practice
options:
bundleIdPrefix: "M"
developmentLanguage: en
settings:
DEVELOPMENT_TEAM: T265XVEUYV
targets:
Practice:
type: application
platform: iOS
deploymentTarget: "13.0"
sources:
- path: Practice
excludes:
- "MyFrameW.framework"
dependencies:
- framework: Practice/MyFrameW.framework
- sdk: CoreData.framework
- sdk: libsqlite3.tbd
- sdk: NetworkExtension.framework
settings:
INFOPLIST_FILE: Practice/Info.plist
GCC_PREFIX_HEADER: Practice/PrefixHeader.pch
PRODUCT_BUNDLE_IDENTIFIER: M.Practice
scheme:
disableMainThreadChecker: true