xcodeproj工程文件

1,162 阅读6分钟

作为一个iOS开发者,在工作的每一天,我们都与 Xcode project打交道,如果使用Cocoapods管理第三方库,那还少不了xcworkspace,今天,我们从内容格式的角度来了解下这两个文件

pbxproj 和 xcworkspace

xcode project

在苹果的文档中是这样描述工程文件的:

Xcode project 里面包含了软件编译所需的所有文件,资源和一些编译设置信息,包括这些文件之前的依赖联系。
它包含一个或者多个targets,target用来描述如果去编译。工程文件定义了编译每一个target的编译方式。

***.xcodeproj文件中,显示包内容,我们就可以找到project.pbxproj文件,打开文件

// !$*UTF8*$!
{
    archiveVersion = 1; 
    classes = {

    };
    objectVersion = 51;
    objects = {
    };
    rootObject = AD5BA36126F07D6B00BBB9AF /* Project object */;
}
  • archiveVersion: 这个值一直为1,并且 classes字段值一直为空。
  • objectVersion: 这个代表了当前Xcode的版本。
  • rootObject: 是最重要的一个keypbxproj是一个树型结构,rootObject是其根节点,它的值是一个标识符,指向一个PXBProject对象,也就是我们常用的 Xcode对象。

xcworkspace

workspace是一个Xcode文档,他对project和其他文档进行分组,以便可以一起处理。一个workspace包含一个或多个Xcode工程,以及想要包含处理的其他文件。 workspace的结构如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "group:HQPDemo.xcodeproj">
   </FileRef>
   <FileRef
      location = "group:Pods/Pods.xcodeproj">
   </FileRef>
</Workspace>

workspce包含了两个xcodeproj对象,location存放的是文件的相对路径。

Xcode Objects

Xcode Object identifiers

所有的Objects都有一个唯一的标识符,例如rootObject = AD5BA36126F07D6B00BBB9AF,通过这个唯一的标识符在工程文件中,找到相对应的值。 在工程文件中,我们可以找到该对象:

AD5BA36126F07D6B00BBB9AF /* Project object */ = {
    isa = PBXProject;
    attributes = {
        LastSwiftUpdateCheck = 1250;
        LastUpgradeCheck = 1250;
        TargetAttributes = {
            AD5BA36826F07D6B00BBB9AF = {
                CreatedOnToolsVersion = 12.5.1;
            };
            AD5BA37E26F07D7000BBB9AF = {
                CreatedOnToolsVersion = 12.5.1;
                TestTargetID = AD5BA36826F07D6B00BBB9AF;
            };
            AD5BA38926F07D7000BBB9AF = {
                CreatedOnToolsVersion = 12.5.1;
                TestTargetID = AD5BA36826F07D6B00BBB9AF;
            };
        };
        
   };
   buildConfigurationList = AD5BA36426F07D6B00BBB9AF /* Build
   configuration list for PBXProject "HQPDemo" */;
   compatibilityVersion = "Xcode 9.3";
   developmentRegion = en;
   hasScannedForEncodings = 0;
   knownRegions = (
       en,Base
   );
    mainGroup = AD5BA36026F07D6B00BBB9AF;
    productRefGroup = AD5BA36A26F07D6B00BBB9AF /* Products */;
    projectDirPath = "";
    projectRoot = "";
    targets = (
        AD5BA36826F07D6B00BBB9AF /* HQPDemo */,
        AD5BA37E26F07D7000BBB9AF /* HQPDemoTests */,
        AD5BA38926F07D7000BBB9AF /* HQPDemoUITests */,
    );
};

PBXProject

rootObject指向一个PBXObject实例。

  • buildConfigurationList指向 XCConfigurationList对象,通常一个工程都有DebugRelease这两个配置。

  • mainGroup指向 PBXGroup对象,它是一个集合,它包含了工程编译的所有文件。

AD5BA36026F07D6B00BBB9AF = {
    isa = PBXGroup;
    children = (
        AD5BA36B26F07D6B00BBB9AF /* HQPDemo */,
        AD5BA38226F07D7000BBB9AF /* HQPDemoTests */,
        AD5BA38D26F07D7000BBB9AF /* HQPDemoUITests */,
        AD5BA36A26F07D6B00BBB9AF /* Products */,
        BB80D1A639BC424ACD0B0514 /* Pods */,
        66A61A52D7288E9C33A3B97A /* Frameworks */,
    );
    sourceTree = "<group>";
};
  • targets是该工程包含的所有target的合集。每一个taget为PBXNativeTarget对象,

截屏2021-10-08 下午10.03.56.png

PBXGroup

PBXGroup对象是一个或多个对象的集合。

  • PBXFileReference: 是一个包含文件引用的集合,可以是源文件、framework、二进制文件、或者其他工程文件
  • PBXReferenceProxy:一个包含工程外引用的集合,通常在需要引用一个依赖工程的时候用到。
  • PBXGroup: 一个group可以包含其他group,在UI中展示的形式为一个子文件夹

截屏2021-10-08 下午10.12.27.png

PBXFilereference

所有的实物都被定义为PBXFilereference对象。

2B64ADE26330B6773355D9FA /* Pods_HQPDemoTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HQPDemoTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };

3D84B89EBA3CA1C9B9C8C4B4 /* Pods-HQPDemo-HQPDemoUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HQPDemo-HQPDemoUITests.debug.xcconfig"; path = "Target Support Files/Pods-HQPDemo-HQPDemoUITests/Pods-HQPDemo-HQPDemoUITests.debug.xcconfig"; sourceTree = "<group>"; };
  • sourceTree是该实物对象路径<group>代表在PBXFilereference对象所属的group下。当是project自身时,sourceTree的值就是BUILT_PRODUCTS_DIR

  • lastKnownFileType表示源码文件的类型,sourcecode.swift表示该文件为swift文件

xcconfig: text.xcconfig
swift   : sourcecode.swift
xcassets: folder.assetcatalog
plist   : text.plist.xml
  • explicitFileType表示要构建的对象,例如
AD5BA36926F07D6B00BBB9AF /* HQPDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HQPDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };

在构建的时候需要将其构建为app文件。

PBXNativeTarget

PBXNativeTarget对象用来描述如何来构建target

AD5BA36826F07D6B00BBB9AF /* HQPDemo */ = {
    isa = PBXNativeTarget;
    buildConfigurationList = AD5BA39326F07D7000BBB9AF /* Build
    configuration list for PBXNativeTarget "HQPDemo" */;
    buildPhases = (
        F854D8F9C862E74399020DEA /* [CP] Check Pods Manifest.lock */,
        AD5BA36526F07D6B00BBB9AF /* Sources */,
        AD5BA36626F07D6B00BBB9AF /* Frameworks */,
        AD5BA36726F07D6B00BBB9AF /* Resources */,
        AB27C9DC0F1571380994A639 /* [CP] Embed Pods Frameworks */,
    );
    buildRules = ();
    dependencies = ();
    name = HQPDemo;
    productName = HQPDemo;
    productReference = AD5BA36926F07D6B00BBB9AF /* HQPDemo.app */;
    productType = "com.apple.product-type.application";
};

buildPhaseXcode中的展现形式如下图所示,是和buildPhases的步骤一一对应的。

截屏2021-10-08 下午10.59.07.png

productReference的值为

AD5BA36926F07D6B00BBB9AF /* HQPDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HQPDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };

说明其为一个可执行的二进制文件PBXNativeTarget对象有其自己的buildConfigurationList(环境变量设置)

PBXBuildPhase

PBXBuildPhase(构建步骤)有7个不同的类型:

  • PBXAppleScriptBuildPhase: 运行苹果脚本。
  • PBXCopyFilesBuildPhase: 拷贝文件。
  • PBXFrameworksBuildPhase: 链接 framework 文件。
  • PBXHeadersBuildPhase: 编译的头文件。
  • PBXResourcesBuildPhase: 资源文件。
  • PBXShellScriptBuildPhase: 执行sh shell脚本。
  • PBXSourcesBuildPhase: 编译的源文件。 对于我们来言,我们的注意点应该放在PBXSourcesBuildPhase对象上

PBXSourcesBuildPhase

AD5BA36526F07D6B00BBB9AF /* Sources */ = {
    isa = PBXSourcesBuildPhase;
    buildActionMask = 2147483647;
    files = (
        AD5BA37126F07D6B00BBB9AF /* ViewController.swift in Sources */,
        AD5BA36D26F07D6B00BBB9AF /* AppDelegate.swift in Sources */,
        AD5BA36F26F07D6B00BBB9AF /* SceneDelegate.swift in Sources */,
        );
        runOnlyForDeploymentPostprocessing = 0;
};

它是一个需要编译源文件(PBXBuildFile)集合的入口,在这里,所有编译3个源文件,在Xcode中的展现形式如下图所示。

截屏2021-10-08 下午11.15.43.png

PBXBuildFile

PBXBuildFilexcode编译文件的核心。PBXBuildFilePBXFileReference相关联。

AD5BA36F26F07D6B00BBB9AF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD5BA36E26F07D6B00BBB9AF /* SceneDelegate.swift */; };
AD5BA36E26F07D6B00BBB9AF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };

lastKnownFileType来指明源文件的类型。文件类型我们在PBXFilereference中做了一次简单总结。

通过以上内容,我们对xcodeproj文件做了一个整体的介绍,希望通过这篇文章能够对xcode工程文件有进一步的认识。在Cocoapods中,通过xcodeprojGem 库来对工程文件进行修改的。通过了解工程结构,我们可以更好的做一些工程自动化的操作。

本文参考文章:

Xcode - xcworkspace and xcodeproj

PBXProj Identifiers

A dive into Xcode projects and workspaces