Xcode 工程管理(Project、Target、xcconf
Project
xcodeproj
一般地,在 iOS 开发中最开始都会通过一个模板新建一个 Xcode Project,Project 会将开发应用程序所需的文件和资源组织起来。
创建一个 Project 后,可以看到Project 是一个后缀为 .xcodeproj 的包文件。通过 Xcode 打开工程可以在 project editor 中看到 Project 不同的设置项,分别为 Info、Build Settings 和 Package Dependencies。
-
Info-
Deployment Target设置工程的目标版本; -
Configurations配置项,默认为 Debug(调试) 和 Release(发布),可以通过 Copy 其中任意一项进行新增配置,通过 xcconfig 文件进行绑定对应的project或者target。 -
Localization国际化;
-
-
Build SettingsBuild Settings (构建设置)中包含了构建选项、编译选项等等,构建设置提供构建 Product 所需的信息。对于在构建过程中执行的每个任务,构建设置控制该任务的执行方式。类似于 Key=Value 的形式,未编辑的情况,会从 iOS Default 继承。可参考Build settings reference
-
Package Dependencies官方提供的一种 Swift 包管理的方式
在 project editor 左侧可以看到 Targets 列表,Project 和 Target 是一对多的关系。
pbxproj
打开 .xcodeproj包文件可以看到真正管理文件和资源的是 .pbxproj 文件,在 Xcode 中能看见所有的公共配置信息都存在于 project.pbxproj 中,它本质上是一种旧风格的 Property List (Plist)文件。
project.pbxproj 使用 UUID 作为交叉引用的索引,保证每个配置信息对象的唯一性。整个文件内容类似 Map,格式如下:
{
archiveVersion = 1;
classes = {
};
objectVersion = 55;
objects = {
}
rootObject =
}
第一层级总共有 5 个键值对,Key 分别为:archiveVersion,classes,objectVersion,objects 和 rootObject。其中所有的配置对象都放在 objects 对应的 Value 中,objects 对应的 Value 也是一个字典,Key 都为 UUID,Value 依然是个字典。
section
objects 的键值对根据内容类型被分成了若干个 section,采用注释的方式分节也使得可读性更强。section 的数量跟工程有关,尤其是每个工程的 BuildPhase 和 Target 差别都很大。下面列出了一个 section 列表(非完整),主要包含:
- 跟文件相关的
BuildFile,Group和FileReference; - 跟编译相关的
BuildPhase和Build Configuration(List); - 以及一些
Target和TargetDependency。
PBXBuildFile
PBXBuildPhase
PBXAppleScriptBuildPhase
PBXCopyFilesBuildPhase
PBXFrameworksBuildPhase
PBXHeadersBuildPhase
PBXResourcesBuildPhase
PBXShellScriptBuildPhase
PBXSourcesBuildPhase
PBXContainerItemProxy
PBXFileElement
PBXFileReference
PBXGroup
PBXVariantGroup
PBXTarget
PBXAggregateTarget
PBXLegacyTarget
PBXNativeTarget
PBXProject
PBXTargetDependency
XCBuildConfiguration
XCConfigurationList
操作 .pbxproj 文件的工具
-
CocoaPods 写的 Ruby 解析库,用于修改引入 CocoaPods 的工程文件并保存为 XML 格式。CocoaPods 本身是很强大的,还可以用来操作
Xcode workspaces (.xcworkspace),configuration files (.xcconfig)和Xcode Scheme files (.xcscheme)。 -
强大的 Python 解析库,支持一定的修改操作,可输出 OpenStep 格式,但是顺序和注释内容无法完美还原,有些鸡肋。
-
用 Python 写的统一多设备生成的 UUID 的工具,主要用途是统一工程在多设备上生成的 UUID,避免工程文件冲突。
-
Ruby 写的解析库。
-
Cordova 基于它管理 Xcode 工程
Target
Target 是编译的模板,定义了要构建的 Product,它将构建 Product 所需的文件和资源组织成一系列可以执行的构建操作。不同的 Target,经过编译生成的Product类型也可以不同,其会继承 Project的 Build Setting,并可重新设置自己的编译配置。
Build Settings
Target 的 Build Settings 在未编辑的情况下,默认继承 Project的 Build Settings,当对其进行编辑后,会覆盖 Project 的设置。如果需要同时继承 Project 设置,可以通过设置 $(inherited)继承 Project 的 Build Settings。
Tips: 在 Build Settings 中,点击 All 和 Levels,可以查看配置是在 Target 或者 Project,以及覆盖和继承情况。
bs_buildsettings_displaylevels.png
xcconfig
扩展名为 .xcconfig 的文件是构建配置文件,也称为 xcconfig 文件,是一个纯文本文件,用于定义和覆盖 Project 或 Target 的特定构建配置的构建设置。
添加构建配置 (xcconfig) 文件
- 添加 xcconfig 文件
bs_buildconfigurationfile.png
- 将配置设置文件映射到构建配置
bs_buildconfigurationfile4.png
- 将构建设置拖到配置设置文件中
bs_buildconfigurationfile5.png
编写 xcconfig 文件
-
语法
BUILD_SETTING_NAME = valueBUILD_SETTING_NAME是构建设置的 Name,可以在Build settings reference查找,或者通过 Xcode 右侧的快速帮助检查器 查看Declaration
XC_O_navigator_quickhelp.png
-
支持不同平台不同方式构建
BUILD_SETTING_DECLARATION_NAME[CONDITIONAL=CONDITION_VALUE] = VALUE_DEFINITIONCONDITIONAL CONDITION_VALUE sdk iphoneos10.2arch arm64例如:
OTHER_LDFLAGS[sdk=macosx*][arch=x86_64] = -lncurses -
引用其他构建配置文件的设置
引用文件可以使用相对路径与绝对路径(最好以
$(SRCROOT)为开始)#include "MyOtherConfigFile.xcconfig"在引用其它文件后防止被覆盖,可以使用
$(inherited)BUILD_SETTING_DECLARATION_NAME = $(inherited) ADDITIONAL_VALUE
Build Settings 优先级
Target .xcconfig > Target > Project.xcconfig > Project > System Default Values
bs_buildsetting_precedence.png
Scheme
Scheme(方案)指定了要构建的 Target 、Configuration 以及要执行的操作 Action,因此 每个 Target 可以有多个 Scheme,Xcode 会自动为每个 Target 创建一个 Scheme。
sce_schemeeditor.png
Workspace
Workspace 直译工作空间,其文件格式为 xcworkspace,可以将工作空间用作多个相关项目的容器。Xcode将检测工作区中多个 Target 之间的隐式链接依赖关系,并通过 Scheme 以正确的顺序构建 Target。
Workspace、Project、Target、Scheme、Build Configuration 之间的联系
bs_buildsysteminteractions_diagram.png
工程多环境配置方案
多 Configurations
通过多个 xcconfig 文件 配合 Configurations,实现不同的环境下编译选项的个性化配置,生成不同的 Products
多 Targets
多 Target 配置,适用于生成有代码或者资源差异的 Product 时:
- 通过在 project editor 左侧对原有 Target 进行 Duplicate,复制一份同样的 Target;
- 修改引用资源、编译代码文件以及
bundleId等配置信息 - 新增 Scheme 绑定新增的 Target