.xcodeproj 是什么
project.pbxproj 文件被包含于 Xcode 工程文件 .xcodeproj 之中
,.xcodeproj 是xcode用来组织工程项目的文件,它是一种旧风格的 Property List 文件,历史可追溯到 NeXT 的 OpenStep。
它用来组织我们工程中使用到的文件,各种工程配置信息等等.
怎么打开它?
有一款叫Plist Edit pro的软件可以打开它
当然我们也可以用xcode来打开,将一个project.pbxproj拖到一个工程中,右键选择 Open As - ASCII Property List方式打开
,这样会以对象的形式打开,便于我们观察.
当然,还可以利用plutil把它转换为json,xml,binary格式
plutil -convert json -o - project.pbxproj > abc.json
结构介绍
整体结构如下
这里你会看到每个对象都有一个24位的十六进制表示的标识符,这个标识符不仅是本工程中唯一,跨工程也是唯一的.我们无从知晓xcode本身是怎么生成这个唯一码的,不过不影响,我们可以给它任意的24位十六进制字符,只要它是唯一的就可以.
属性 | 类型 | 值 | 备注 |
---|---|---|---|
archiveVersion | String | 1 | 目前看在所有的xcode中这个值都取1 |
classes | Dictionary | nil | 一般都是空的 |
objectVersion | String | 50 | 48是xcode 8.0-compatible 50是xcode9.3-compatible 51是xcode10.0-compatible |
objects | Dictionary | 成员 | |
rootObject | String | root object的UUID | 是objects中的某个成员的健值 |
objects 中的键值对被分成了若干个 section, section 的顺序是 Xcode 私有 API 钦定的,但每个 section 内部的键值对会根据 Key 的字典序排列,以此增加可读性。
内部都是通过UUID来进行引用的.从表面看,所有的对象都在objects下面,是一维的,但是,他们可以通过UUID来组成二维结构.
objectVersion的取值,会影响到objects中的object的类型,因为某些类型只有高级别的xcode才会支持.
常见的object类型有:
- PBXBuildFile
- PBXContainerItemProxy
- PBXBuildPhase
- PBXAppleScriptBuildPhase
- PBXCopyFilesBuildPhase
- PBXFrameworksBuildPhase
- PBXHeadersBuildPhase
- PBXResourcesBuildPhase
- PBXShellScriptBuildPhase
- PBXSourcesBuildPhase
- PBXFileReference
- PBXGroup
- PBXTarget
- PBXAggregateTarget
- PBXLegacyTarget
- PBXNativeTarget
- PBXProject
- PBXReferenceProxy
- PBXVariantGroup
- XCBuildConfiguration
- XCConfigurationList
我们从可视化的角度来看待一个工程
这里对应的就是 PBXProject,它代表的就是我们平时看到的项目project.
Attribute | Type | Value | Comment |
---|---|---|---|
reference | UUID | 24位16进制字符 | |
isa | PBXProject | Empty | |
attributes | Dictionary | 工程的常用属性设置 | 有LastUpgradeCheck,ORGANIZATIONNAME,TargetAttributes等 |
buildConfigurationList | Reference | An element reference | The object is a reference to a XCConfigurationList element. |
compatibilityVersion | String | A string representation of the XcodeCompatibilityVersion. | |
developmentRegion | String | The region of development. | |
hasScannedForEncodings | Number 0 or 1 | Whether file encodings have been scanned. | |
knownRegions | List | A list of string | The known regions for localized files. |
mainGroup | Reference | An element reference | The object is a reference to a PBXGroup element. |
productRefGroup | Reference | An element reference | The object is a reference to a PBXGroup element. |
projectDirPath | String | The relative path of the project. | |
projectReferences | Array of map | Each map in the array contains two keys: ProductGroup and ProjectRef. | |
projectRoot | String | The relative root path of the project. | |
targets | List | A list of element reference | The objects are a reference to a PBXTarget element. |
示例如下
/* Begin PBXProject section */
4CFBA7EB2099B5BC00E39A19 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = pingan.inc;
TargetAttributes = {
4C51184D2255E2DB00914224 = {
CreatedOnToolsVersion = 10.2;
};
4CE1AA532265BD64001EF020 = {
CreatedOnToolsVersion = 10.2;
};
4CFBA7F22099B5BC00E39A19 = {
CreatedOnToolsVersion = 9.3;
};
4CFBA80A2099B5BD00E39A19 = {
CreatedOnToolsVersion = 9.3;
TestTargetID = 4CFBA7F22099B5BC00E39A19;
};
4CFBA8152099B5BD00E39A19 = {
CreatedOnToolsVersion = 9.3;
TestTargetID = 4CFBA7F22099B5BC00E39A19;
};
};
};
buildConfigurationList = 4CFBA7EE2099B5BC00E39A19 /* Build configuration list for PBXProject "DemoMain" */;
compatibilityVersion = "Xcode 10.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 4CFBA7EA2099B5BC00E39A19;
productRefGroup = 4CFBA7F42099B5BC00E39A19 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = AD433F0BCF3E4ED4D2C03BEB /* Products */;
ProjectRef = 24338332C0278FA0BF128891 /* YLBusiness1.xcodeproj */;
},
{
ProductGroup = 4C144E2B225598B50024F074 /* Products */;
ProjectRef = 4C144E2A225598B50024F074 /* YLBusiness2.xcodeproj */;
},
{
ProductGroup = 4C144E37225598BA0024F074 /* Products */;
ProjectRef = 4C144E36225598BA0024F074 /* YLBusiness3.xcodeproj */;
},
{
ProductGroup = 4C144E43225598BF0024F074 /* Products */;
ProjectRef = 4C144E42225598BF0024F074 /* YLBusiness4.xcodeproj */;
},
);
projectRoot = "";
targets = (
4CFBA7F22099B5BC00E39A19 /* DemoMain */,
4CFBA80A2099B5BD00E39A19 /* DemoMainTests */,
4CFBA8152099B5BD00E39A19 /* DemoMainUITests */,
4C51184D2255E2DB00914224 /* Hello */,
4CE1AA532265BD64001EF020 /* LesGo */,
);
};
/* End PBXProject section */
其中的attributse中的TargetAttributes就是在图中的 工程的 targets列表.
还有个很常见的是 PBXGroup,这个是我们在工程组织中看到的group.也是我们看到的文件的组织结构.
/* Begin PBXGroup section */
4C144E2B225598B50024F074 /* Products */ = {
isa = PBXGroup;
children = (
4C144E31225598B50024F074 /* libBusiness2.a */,
4C144E33225598B50024F074 /* Business2Tests.xctest */,
4C144E35225598B50024F074 /* Business2Bundle.bundle */,
);
name = Products;
sourceTree = "<group>";
};
4C144E37225598BA0024F074 /* Products */ = {
isa = PBXGroup;
children = (
4C144E3D225598BA0024F074 /* libBusiness3.a */,
4C144E3F225598BA0024F074 /* Business3Tests.xctest */,
4C144E41225598BA0024F074 /* Business3Bundle.bundle */,
);
name = Products;
sourceTree = "<group>";
};
4C144E43225598BF0024F074 /* Products */ = {
isa = PBXGroup;
children = (
4C144E49225598BF0024F074 /* libBusiness4.a */,
4C144E4B225598BF0024F074 /* Business4Tests.xctest */,
4C144E4D225598BF0024F074 /* Business4Bundle.bundle */,
);
name = Products;
sourceTree = "<group>";
};
........太多了....省略
/* End PBXGroup section */
Attribute | Type | Value | Comment |
---|---|---|---|
reference | UUID | A 96 bits identifier | |
isa | PBXGroup | Empty | |
children | List | A list of element reference | The objects are a reference to a PBXFileElement element. |
name | String | The filename. | |
sourceTree | String | 是个特定字符串 | <absolute> :for absolute paths <group> :for paths relative to the group SOURCE_ROOT: for paths relative to the project DEVELOPER_DIR :for paths relative to the developer directory. BUILT_PRODUCTS_DIR :for paths relative to the build products directory. |
SDKROOT: for paths relative to the SDK directory. |
这里的sourceTree的取值,在xcode中,是展示在最右边的属性中的
在group中的每一个文件,实际上都是一个 PBXFileReference对象,项目所引用的每一个外部文件,比如源代码文件、资源文件、库文件、生成目标文件等,每一个外部文件都可以在PBXFileReference中找到
/* Begin PBXFileReference section */
24338332C0278FA0BF128891 /* YLBusiness1.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = YLBusiness1.xcodeproj; path = Modules/YLBusiness1/YLBusiness1.xcodeproj; sourceTree = "<group>"; };
377280FB4B7932AA0F83F08F /* Pods-DemoMainTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DemoMainTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-DemoMainTests/Pods-DemoMainTests.debug.xcconfig"; sourceTree = "<group>"; };
41DB0A36B9FFEBB516E4ABE7 /* libPods-DemoMainTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-DemoMainTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
.....太多了省略.....
/* End PBXFileReference section */
Attribute | Type | Value | Comment |
---|---|---|---|
reference | UUID | A 96 bits identifier | |
isa | PBXFileReference | Empty | |
fileEncoding | Number | See the PBXFileEncoding enumeration. | |
explicitFileType | String | See the PBXFileType enumeration. | |
lastKnownFileType | String | See the PBXFileType enumeration. | |
name | String | The filename. | |
path | String | The path to the filename. | |
sourceTree | String | See the PBXSourceTree enumeration. |
还有个 PBXContainerItemProxy,也是比较常见的,它是用来描述一个target的
/* Begin PBXContainerItemProxy section */
3BCAE28295B22FEE4F9370FC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 24338332C0278FA0BF128891 /* YLBusiness1.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 4CE211C720A0577E000137EA;
remoteInfo = Business1Tests;
};
4030246F37A79E480733FAF4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 24338332C0278FA0BF128891 /* YLBusiness1.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 4CE211E620A0800C000137EA;
remoteInfo = Business1Bundle;
};
......很多,省略.......
/* End PBXContainerItemProxy section */
Attribute | Type | Value | Comment |
---|---|---|---|
reference | UUID | A 96 bits identifier | |
isa | PBXContainerItemProxy | Empty | |
containerPortal | Reference | An element reference | The object is a reference to a PBXProject element.,这个element可以是PBXFileReference,也可以是其它,看具体情况 |
proxyType | Number | 1 | |
remoteGlobalIDString | Reference | An element reference | A unique reference ID.比如,有子工程的时候,这个target来自于子工程的,这个值就是存在子工程中 |
remoteInfo | String |
PBXAggregateTarget,这个不太常见,这个通常是在我们创建.a或者.framework时候,添加的aggrate target
属性 | 类型 | 值 | 备注 |
---|---|---|---|
reference | UUID | ||
buildConfigurationList | Refrence | nil | reference to a XCConfigurationList element |
buildPhases | List | nil | The objects are a reference to a PBXBuildPhase element. |
dependencies | List | 依赖的element列表 | The objects are a reference to a PBXTargetDependency element. |
name | String | targe的名称 | |
productName | String |
/* Begin PBXAggregateTarget section */
4CE1AA532265BD64001EF020 /* LesGo */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 4CE1AA542265BD64001EF020 /* Build configuration list for PBXAggregateTarget "LesGo" */;
buildPhases = (
);
dependencies = (
);
name = LesGo;
productName = LesGo;
};
/* End PBXAggregateTarget section */
怎么操作它?
最常用的,也就是cocoapods官方开源并使用的Xcodeproj库,在安装cocoapods的时候,已经安装在我们的电脑上了,如果没有安装过cocoapods,可以使用 gem install xcodeproj来安装
官方地址在Xcodeproj
它是一个ruby的库,需要了解基本的ruby语法才能操作.
当然,还有其他语言写的库,例如
OC写的操纵库 XcodeEditor
swift写的XcodeGen ,它还提供了通过撰写一个.yml文件的方式来帮你生成整个xcodeproj工程.使用 xcodegen 管理 iOS 项目对这个工具的使用有个简单的介绍
另外一个使用swift来操作的库是tuist和tuist/xcodeproj,更新的很频繁,对swift版本感兴趣的可以看看这个
国内还有些写了一些很实用的工具,来导出xcodeproj文件的不同点,具体请看
pbxprojHelper ,这个是一个mac上的GUI工具,pbxprojHelper是其中文说明.
还有个python版本的
mod-pbxproj ,文档比较详细
nodejs版本的,Cordova 就是基于它管理 Xcode 工程的
cordova-node-xcode
哪里使用它?
- podfile文件的高级定制
- 组件化建立工程
备注:
其实还有个能够生成xcodeproj的夸平台工具 cmake
参考
xcode-project-file-format
Xcode工程文件project.pbxproj小结
Let-s-Talk-About-project-pbxproj