.xcodeproj 文件夹概述

 .xcodeproj 文件(并不是文件其实是一个文件夹)咱们大约再了解不过,每次创建一个 Xcode 的 App 项目,根目录下面默许就是一个 项目名.xcodeprogj 文件和一个 项目名文件夹,项目名文件夹里面是咱们的初始几个文件:Assets.xcassets、Main.storybord、LaunchScreen.storyboard、Info.plist、.swift 文件,而 .xcodeproj 文件(内部的 project.pbxproj 文件)便是对整个项目工程信息以及项目内一切文件安排结构进行描述,它包含两个最重要的部分:项目内文件的引用和项目的 BuildSettings、BuildPhase 信息等。

 .xcodeproj 文件并不是一个文件,而是一个文件夹,而其内部最重要的文件便是:project.pbxproj 文件。默许情况下 .xcodeproj 文件夹内部还有一个 xcuserdata 文件夹一般是跟用户相关的一些设置,如断点记载(Breakpoints_v2.xcbkptlist 文件)等,一般不用放到版本办理中, project.xcworkspace 文件夹,它们内部没什么重要信息,暂时忽略,咱们把目光首要会集在 project.pbxproj 文件中,合并代码时咱们大约遇到过很屡次 project.pbxproj 文件抵触,特别是需求手动处理时,当咱们的项目大起来以后翻开 project.pbxproj 看到其内部成千上万的行数差不多要当场裂开,乍一眼看上去它内部结构极其复杂,细心看下的话也能够发现明晰的规律,每个区域的划分都遵从一个规则,苹果在每个区域加了相似 /* Begin xxx section */ ... /* End xxx section */ 的注释说明供咱们参考。

 project.pbxproj 文件本质是一个 ASCII text 文件,可是看下来觉得更像是一个相似 JSON 的结构。(The Xcode project file is an old-style plist (Next style) based on braces to delimit the hierarchy. 也被称为是一个旧式的 plist)

 运用 file 指令看到 project.pbxproj 文件是一个 ASCII text 文件:

xcodeprojDemo.xcodeproj % file project.pbxproj
project.pbxproj: ASCII text

 顺便运用 tree 指令咱们看一下 .xcodeproj 文件夹的内部安排:

xcodeprojDemo % file xcodeprojDemo.xcodeproj
xcodeprojDemo.xcodeproj: directory // xcodeproj 是一个文件夹
xcodeprojDemo % cd xcodeprojDemo.xcodeproj 
xcodeprojDemo.xcodeproj % ls
project.pbxproj        project.xcworkspace    xcuserdata
xcodeprojDemo.xcodeproj % tree  
.
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── xcuserdata
│     └── hmc.xcuserdatad
│         └── UserInterfaceState.xcuserstate
└── xcuserdata
    └── hmc.xcuserdatad
        └── xcschemes
            └── xcschememanagement.plist
7 directories, 5 files

 .xcodeproj 文件夹内部 7 个文件夹,5 个文件,下面咱们把目光都会集到 project.pbxproj 文件上,看下它内部包含的内容都代表了什么意义。

project.pbxproj 文件

 project.pbxproj 由来:

 project.pbxproj 文件被包含于 Xcode 工程文件 *.xcodeproj 之中,存储着 Xcode 工程的各项装备参数。它本质上是一种旧风格的 Property List 文件,历史可追溯到 NeXT 的 OpenStep。其可读性不如 xml 和 json,苹果却一直沿用至今。Property List 有许多种表现方法,最陈旧的格局就是之前提到的 NeXTSTEP 所运用的格局。与 json 最显着的差别是:数组用小括号括起来并用逗号离隔元素;字典用大括号括起来并用分号离隔键值对,键值之间用等号衔接;二进制数据用尖括号 括起来:

 数组:

( "1", "2", "3" )

 字典:

{
"key" = "value"; 
... 
}

 这也是 project.pbxproj 文件中所运用的格局。Property List 在苹果宗族的历史上存在三种格局:OpenStep,XML 和 Binary。除了 OpenStep 被废弃不支持写入以外,其余格局都提供 API 支持读写。iOS 开发 xcode中的project.pbxproj–深入分析

 project.pbxproj 文件是一个旧式的 plist(Next style),基于大括号来分隔层次结构。该文件以显式编码信息开头,通常是 UTF-8 编码信息。这意味着文件在开始时不得不带有 BOM(Byte Ordering Mark),不然解析将失败。

 project.pbxproj 文件更相似于 JSON 结构,重要的内容都包含在 objects 特点中,objects 嵌套其间,它其间的每个特点都由 24 位十六进制(96 位二进制位)表明方法的标识符作为仅有标识。此仅有标识符在整个文档中是仅有的。

// !$*UTF8*$!
{
    archiveVersion = 1;
    classes = {
    };
    objectVersion = 55;
    objects = {
        ......
    };
    rootObject = 8E8A672A2863E745003DB257 /* Project object */;
}

 objects 中的内容被运用 /* Begin xxx section */ ... /* End xxx section */ 格局的注释划作了一个一个区域,每个区域的几个元素加在一起表明工程的一些部分信息。

 把 objects 中的内容摘出来后,project.pbxproj 文件中只剩下一些基础信息,其间最重要的是 rootObject,它指向 PBXProject section。PBXProject 为根节点,代表着整个工程。PBXProject 中的 targets 特点是一个数组,能够包含多个 PBXNativeTarget,每个 PBXNativeTarget 代表着工程中的一个 target(这里需求了解 Project 和 Target 的包含联系),它维护着自己的需求编译的代码源文件(PBXSourcesBuildPhase)、storyboard 和 Assets.xcassets、图片视频等资源文件(PBXResourcesBuildPhase)以及依靠的库(PBXFrameworksBuildPhase,如:体系 framework、体系库、非体系 framework、非体系静态库)。

 PBXProject 和 PBXNativeTarget 都有一个 buildConfigurationList 特点指向它们各自的装备,在咱们的示例中看到 xcodeprojDemo Project 和 Target 的它俩的装备都坐落 XCConfigurationList section 中,然后在 XCBuildConfiguration section 中存放了装备的详细信息(buildSettings)。默许情况下是咱们最了解的 Debug 和 Release 两个装备。

 每个导入工程的文件都会有相应的 PBXFileReference 记载,假如该文件在导入时,选择了 create groups,会在相应的 PBXGroup 中有记载。

 每个在编译打包进程中被包含到可执行文件中的文件,都会有 PBXBuildFile 记载,依据类别分别在 PBXResourcesBuildPhase、PBXSourcesBuildPhase 等中有记载。XCode工程文件结构及Xcodeproj结构的运用( 二 )

Xcode工程相关(一):project.pbxproj 文件分析

 下面咱们依据 section 的划分,来分别看看 objects 中各个区的作用。

PBXBuildFile

 项目构建时所需的(或者说是参加项目构建的)代码源文件、资源文件、引进库等等,平常 git 发生抵触也首要是在这个区域内抵触,每新创建一对 .h/.m 文件,就会修改这个区域,各个 branch 都在创建/新增文件的时候,容易抵触。

/* Begin PBXBuildFile section */
        /* 这个 UIKit.framework 是手动引进的,并不是初始工程默许引进的,首要是用来检查手动引进体系库对 project.pbxproj 文件的影响 */ 
        8E7BDC08286E7FAB0027A0CB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E7BDC07286E7FAB0027A0CB /* UIKit.framework */; };
        /* 手动直接拖入项目根目录下的图片 */
        8E7BDC0E286FEAAE0027A0CB /* imagefile.png in Resources */ = {isa = PBXBuildFile; fileRef = 8E7BDC0D286FEAAE0027A0CB /* imagefile.png */; };
        8E8A67362863E745003DB257 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E8A67352863E745003DB257 /* AppDelegate.swift */; };
        8E8A67382863E745003DB257 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E8A67372863E745003DB257 /* SceneDelegate.swift */; };
        8E8A673A2863E745003DB257 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E8A67392863E745003DB257 /* ViewController.swift */; };
        8E8A673D2863E745003DB257 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8E8A673B2863E745003DB257 /* Main.storyboard */; };
        8E8A673F2863E746003DB257 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8E8A673E2863E746003DB257 /* Assets.xcassets */; };
        8E8A67422863E746003DB257 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8E8A67402863E746003DB257 /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */

PBXFileReference

 记载了项目相关一切文件的文件类型、途径 path、sourceTree,不管引进文件的时候是 create group 仍是 create reference,都会在这里添加一条记载。也看到了它和 PBXBuildFile 的区别,除了参加编译的文件,在 PBXFileReference 中还包含了构建发生的 xcodeprojDemo.app 文件。

/* Begin PBXFileReference section */
        8E7BDC07286E7FAB0027A0CB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
        8E7BDC0D286FEAAE0027A0CB /* imagefile.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = imagefile.png; sourceTree = "<group>"; };
        8E8A67322863E745003DB257 /* xcodeprojDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = xcodeprojDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
        8E8A67352863E745003DB257 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
        8E8A67372863E745003DB257 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
        8E8A67392863E745003DB257 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
        8E8A673C2863E745003DB257 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
        8E8A673E2863E746003DB257 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
        8E8A67412863E746003DB257 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
        8E8A67432863E746003DB257 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */

PBXFrameworksBuildPhase

 在这个 section 中装备的是工程依靠的体系 framework、体系库、非体系 framework、非体系静态库,对应 Build Phases 中的 Link Binary With Libraries。能够在工程装备 Build Phases 的 Link Binary With Libraries 中装备。

/* Begin PBXFrameworksBuildPhase section */
        8E8A672F2863E745003DB257 /* Frameworks */ = {
            isa = PBXFrameworksBuildPhase;
            buildActionMask = 2147483647;
            files = (
                8E7BDC08286E7FAB0027A0CB /* UIKit.framework in Frameworks */,
            );
            runOnlyForDeploymentPostprocessing = 0;
        };
/* End PBXFrameworksBuildPhase section */

PBXGroup

 工程中一切文件的 group 信息,这个和 xcode 文件目录是对应的,每一层的文件目录有仅有的 UUID,同一层 group 下的子 group 会和上一层的 group 的 UUID 有很高的重合度(根本只有 1-2 位不同),这个 PBXGroup section 中,子 group 没有用树的方法,而是采用相似列表的方法呈现了一切的 group 目录,能够脑补:翻开 xcode 左侧目录,然后让一切目录和文件 “左对齐”,然后就会生成如下的结构。

/* Begin PBXGroup section */
        8E7BDC06286E7FAB0027A0CB /* Frameworks */ = {
            isa = PBXGroup;
            children = (
                8E7BDC07286E7FAB0027A0CB /* UIKit.framework */,
            );
            name = Frameworks;
            sourceTree = "<group>";
        };
        8E8A67292863E745003DB257 = {
            isa = PBXGroup;
            children = (
                8E8A67342863E745003DB257 /* xcodeprojDemo */,
                8E8A67332863E745003DB257 /* Products */,
                8E7BDC06286E7FAB0027A0CB /* Frameworks */,
            );
            sourceTree = "<group>";
        };
        8E8A67332863E745003DB257 /* Products */ = {
            isa = PBXGroup;
            children = (
                8E8A67322863E745003DB257 /* xcodeprojDemo.app */,
            );
            name = Products;
            sourceTree = "<group>";
        };
        8E8A67342863E745003DB257 /* xcodeprojDemo */ = {
            isa = PBXGroup;
            children = (
                8E8A67352863E745003DB257 /* AppDelegate.swift */,
                8E8A67372863E745003DB257 /* SceneDelegate.swift */,
                8E8A67392863E745003DB257 /* ViewController.swift */,
                8E7BDC0D286FEAAE0027A0CB /* imagefile.png */,
                8E8A673B2863E745003DB257 /* Main.storyboard */,
                8E8A673E2863E746003DB257 /* Assets.xcassets */,
                8E8A67402863E746003DB257 /* LaunchScreen.storyboard */,
                8E8A67432863E746003DB257 /* Info.plist */,
            );
            path = xcodeprojDemo;
            sourceTree = "<group>";
        };
/* End PBXGroup section */

PBXNativeTarget

 每个 Target 的 Build Settings 和 Build Phases(Sources/Frameworks/Resources 等)的信息。

/* Begin PBXNativeTarget section */
        8E8A67312863E745003DB257 /* xcodeprojDemo */ = {
            isa = PBXNativeTarget;
            /* buildConfigurationList 特点指向了 Target 的 Configurations 列表,默许的:Debug 和 Release */
            buildConfigurationList = 8E8A67462863E746003DB257 /* Build configuration list for PBXNativeTarget "xcodeprojDemo" */;
            buildPhases = (
                /* 指向 PBXSourcesBuildPhase section,对应 Build Phases 中的 Compile Sources,表明那些需求编译的代码源文件 */
                8E8A672E2863E745003DB257 /* Sources */,
                /* 指向 PBXFrameworksBuildPhase section,对应 Build Phases 中的 Link Binary With Libraries,表明引进的体系 framework、体系库、非体系 framework、非体系静态库 */
                8E8A672F2863E745003DB257 /* Frameworks */,
                /* 指向 PBXResourcesBuildPhase section,对应 Build Phases 中的 Copy Bundle Resources,表明 Target 运用的资源文件,例如:LaunchScreen 和 Main Storyboard、Assets.xcassets 文件、图片、音频、视频文件等 */
                8E8A67302863E745003DB257 /* Resources */,
            );
            buildRules = (
            );
            dependencies = (
            );
            name = xcodeprojDemo;
            productName = xcodeprojDemo;
            productReference = 8E8A67322863E745003DB257 /* xcodeprojDemo.app */;
            productType = "com.apple.product-type.application";
        };
/* End PBXNativeTarget section */

PBXProject

 整个项目工程 Project 的信息,包含项目途径、Config 信息,相关版本号,一切的 Target 等信息。

/* Begin PBXProject section */
        8E8A672A2863E745003DB257 /* Project object */ = {
            isa = PBXProject;
            attributes = {
                BuildIndependentTargetsInParallel = 1;
                LastSwiftUpdateCheck = 1310;
                LastUpgradeCheck = 1310;
                TargetAttributes = {
                    8E8A67312863E745003DB257 = {
                        CreatedOnToolsVersion = 13.1;
                    };
                };
            };
            /* Project 的装备列表,默许也是 Debug 和 Release */
            buildConfigurationList = 8E8A672D2863E745003DB257 /* Build configuration list for PBXProject "xcodeprojDemo" */;
            compatibilityVersion = "Xcode 13.0";
            developmentRegion = en;
            hasScannedForEncodings = 0;
            knownRegions = (
                en,
                Base,
            );
            mainGroup = 8E8A67292863E745003DB257;
            productRefGroup = 8E8A67332863E745003DB257 /* Products */;
            projectDirPath = "";
            projectRoot = "";
            targets = (
                8E8A67312863E745003DB257 /* xcodeprojDemo */,
            );
        };
/* End PBXProject section */

PBXResourcesBuildPhase

 列举了项目中每个 Resources 的信息,对应 Build Phase 下的 Copy Bundle Resources,例如:LaunchScreen、Main Storyboaryd、Assets.xcassets、图片视频等资源文件。

/* Begin PBXResourcesBuildPhase section */
        8E8A67302863E745003DB257 /* Resources */ = {
            isa = PBXResourcesBuildPhase;
            buildActionMask = 2147483647;
            files = (
                8E8A67422863E746003DB257 /* LaunchScreen.storyboard in Resources */,
                8E8A673F2863E746003DB257 /* Assets.xcassets in Resources */,
                8E8A673D2863E745003DB257 /* Main.storyboard in Resources */,
                8E7BDC0E286FEAAE0027A0CB /* imagefile.png in Resources */,
            );
            runOnlyForDeploymentPostprocessing = 0;
        };
/* End PBXResourcesBuildPhase section */

PBXShellScriptBuildPhase

 对应 Xcode 中 Build Phases 下的 Run Script 脚本文件。

/* Begin PBXShellScriptBuildPhase section */
        8E7BDC0F287017BE0027A0CB /* ShellScript */ = {
            isa = PBXShellScriptBuildPhase;
            buildActionMask = 2147483647;
            files = (
            );
            inputFileListPaths = (
            );
            inputPaths = (
            );
            outputFileListPaths = (
            );
            outputPaths = (
            );
            runOnlyForDeploymentPostprocessing = 0;
            shellPath = /bin/sh;
            shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n";
        };
/* End PBXShellScriptBuildPhase section */

PBXSourcesBuildPhase

 对应 Build Phases 中的 Compile Sources,表明那些需求编译的代码源文件。

/* Begin PBXSourcesBuildPhase section */
        8E8A672E2863E745003DB257 /* Sources */ = {
            isa = PBXSourcesBuildPhase;
            buildActionMask = 2147483647;
            files = (
                8E8A673A2863E745003DB257 /* ViewController.swift in Sources */,
                8E8A67362863E745003DB257 /* AppDelegate.swift in Sources */,
                8E8A67382863E745003DB257 /* SceneDelegate.swift in Sources */,
            );
            runOnlyForDeploymentPostprocessing = 0;
        };
/* End PBXSourcesBuildPhase section */

PBXVariantGroup

 不同区域的资源文件的引用信息,假如你项目运用了国际化,相关的 xxx.string 就在这个 section 中。

/* Begin PBXVariantGroup section */
        8E8A673B2863E745003DB257 /* Main.storyboard */ = {
            isa = PBXVariantGroup;
            children = (
                8E8A673C2863E745003DB257 /* Base */,
            );
            name = Main.storyboard;
            sourceTree = "<group>";
        };
        8E8A67402863E746003DB257 /* LaunchScreen.storyboard */ = {
            isa = PBXVariantGroup;
            children = (
                8E8A67412863E746003DB257 /* Base */,
            );
            name = LaunchScreen.storyboard;
            sourceTree = "<group>";
        };
/* End PBXVariantGroup section */

XCBuildConfiguration

 在不同的 Configuration 下对应 Xcode 中 Build Settings 中的装备信息,默许的是:Debug 和 Release 两个 Configuration。下面分别是 xcodeprojDemo Project 和 xcodeprojDemo Target 的 Debug 和 Release 装备。

/* Begin XCBuildConfiguration section */
        8E8A67442863E746003DB257 /* Debug */ = {
            isa = XCBuildConfiguration;
            buildSettings = {
                ALWAYS_SEARCH_USER_PATHS = NO;
                CLANG_ANALYZER_NONNULL = YES;
                CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
                CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
                CLANG_CXX_LIBRARY = "libc++";
                CLANG_ENABLE_MODULES = YES;
                CLANG_ENABLE_OBJC_ARC = YES;
                CLANG_ENABLE_OBJC_WEAK = YES;
                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                CLANG_WARN_BOOL_CONVERSION = YES;
                CLANG_WARN_COMMA = YES;
                CLANG_WARN_CONSTANT_CONVERSION = YES;
                CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
                CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
                CLANG_WARN_EMPTY_BODY = YES;
                CLANG_WARN_ENUM_CONVERSION = YES;
                CLANG_WARN_INFINITE_RECURSION = YES;
                CLANG_WARN_INT_CONVERSION = YES;
                CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
                CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
                CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
                CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
                CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
                CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
                CLANG_WARN_STRICT_PROTOTYPES = YES;
                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
                CLANG_WARN_UNREACHABLE_CODE = YES;
                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
                COPY_PHASE_STRIP = NO;
                DEBUG_INFORMATION_FORMAT = dwarf;
                ENABLE_STRICT_OBJC_MSGSEND = YES;
                ENABLE_TESTABILITY = YES;
                GCC_C_LANGUAGE_STANDARD = gnu11;
                GCC_DYNAMIC_NO_PIC = NO;
                GCC_NO_COMMON_BLOCKS = YES;
                GCC_OPTIMIZATION_LEVEL = 0;
                GCC_PREPROCESSOR_DEFINITIONS = (
                    "DEBUG=1",
                    "$(inherited)",
                );
                GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
                GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
                GCC_WARN_UNDECLARED_SELECTOR = YES;
                GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
                GCC_WARN_UNUSED_FUNCTION = YES;
                GCC_WARN_UNUSED_VARIABLE = YES;
                IPHONEOS_DEPLOYMENT_TARGET = 15.0;
                MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
                MTL_FAST_MATH = YES;
                ONLY_ACTIVE_ARCH = YES;
                SDKROOT = iphoneos;
                SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
                SWIFT_OPTIMIZATION_LEVEL = "-Onone";
            };
            name = Debug;
        };
        8E8A67452863E746003DB257 /* Release */ = {
            isa = XCBuildConfiguration;
            buildSettings = {
                ALWAYS_SEARCH_USER_PATHS = NO;
                CLANG_ANALYZER_NONNULL = YES;
                CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
                CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
                CLANG_CXX_LIBRARY = "libc++";
                CLANG_ENABLE_MODULES = YES;
                CLANG_ENABLE_OBJC_ARC = YES;
                CLANG_ENABLE_OBJC_WEAK = YES;
                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                CLANG_WARN_BOOL_CONVERSION = YES;
                CLANG_WARN_COMMA = YES;
                CLANG_WARN_CONSTANT_CONVERSION = YES;
                CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
                CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
                CLANG_WARN_EMPTY_BODY = YES;
                CLANG_WARN_ENUM_CONVERSION = YES;
                CLANG_WARN_INFINITE_RECURSION = YES;
                CLANG_WARN_INT_CONVERSION = YES;
                CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
                CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
                CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
                CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
                CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
                CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
                CLANG_WARN_STRICT_PROTOTYPES = YES;
                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
                CLANG_WARN_UNREACHABLE_CODE = YES;
                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
                COPY_PHASE_STRIP = NO;
                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                ENABLE_NS_ASSERTIONS = NO;
                ENABLE_STRICT_OBJC_MSGSEND = YES;
                GCC_C_LANGUAGE_STANDARD = gnu11;
                GCC_NO_COMMON_BLOCKS = YES;
                GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
                GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
                GCC_WARN_UNDECLARED_SELECTOR = YES;
                GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
                GCC_WARN_UNUSED_FUNCTION = YES;
                GCC_WARN_UNUSED_VARIABLE = YES;
                IPHONEOS_DEPLOYMENT_TARGET = 15.0;
                MTL_ENABLE_DEBUG_INFO = NO;
                MTL_FAST_MATH = YES;
                SDKROOT = iphoneos;
                SWIFT_COMPILATION_MODE = wholemodule;
                SWIFT_OPTIMIZATION_LEVEL = "-O";
                VALIDATE_PRODUCT = YES;
            };
            name = Release;
        };
        8E8A67472863E746003DB257 /* Debug */ = {
            isa = XCBuildConfiguration;
            buildSettings = {
                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
                ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
                CODE_SIGN_STYLE = Automatic;
                CURRENT_PROJECT_VERSION = 1;
                GENERATE_INFOPLIST_FILE = YES;
                INFOPLIST_FILE = xcodeprojDemo/Info.plist;
                INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
                INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
                INFOPLIST_KEY_UIMainStoryboardFile = Main;
                INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
                INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
                LD_RUNPATH_SEARCH_PATHS = (
                    "$(inherited)",
                    "@executable_path/Frameworks",
                );
                MARKETING_VERSION = 1.0;
                PRODUCT_BUNDLE_IDENTIFIER = com.chm.xcodeprojDemo;
                PRODUCT_NAME = "$(TARGET_NAME)";
                SWIFT_EMIT_LOC_STRINGS = YES;
                SWIFT_VERSION = 5.0;
                TARGETED_DEVICE_FAMILY = "1,2";
            };
            name = Debug;
        };
        8E8A67482863E746003DB257 /* Release */ = {
            isa = XCBuildConfiguration;
            buildSettings = {
                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
                ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
                CODE_SIGN_STYLE = Automatic;
                CURRENT_PROJECT_VERSION = 1;
                GENERATE_INFOPLIST_FILE = YES;
                INFOPLIST_FILE = xcodeprojDemo/Info.plist;
                INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
                INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
                INFOPLIST_KEY_UIMainStoryboardFile = Main;
                INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
                INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
                LD_RUNPATH_SEARCH_PATHS = (
                    "$(inherited)",
                    "@executable_path/Frameworks",
                );
                MARKETING_VERSION = 1.0;
                PRODUCT_BUNDLE_IDENTIFIER = com.chm.xcodeprojDemo;
                PRODUCT_NAME = "$(TARGET_NAME)";
                SWIFT_EMIT_LOC_STRINGS = YES;
                SWIFT_VERSION = 5.0;
                TARGETED_DEVICE_FAMILY = "1,2";
            };
            name = Release;
        };
/* End XCBuildConfiguration section */

XCConfigurationList

 Configurations 的列表,列举了 Project 和 Target 的装备列表。

/* Begin XCConfigurationList section */
        8E8A672D2863E745003DB257 /* Build configuration list for PBXProject "xcodeprojDemo" */ = {
            isa = XCConfigurationList;
            buildConfigurations = (
                8E8A67442863E746003DB257 /* Debug */,
                8E8A67452863E746003DB257 /* Release */,
            );
            defaultConfigurationIsVisible = 0;
            defaultConfigurationName = Release;
        };
        8E8A67462863E746003DB257 /* Build configuration list for PBXNativeTarget "xcodeprojDemo" */ = {
            isa = XCConfigurationList;
            buildConfigurations = (
                8E8A67472863E746003DB257 /* Debug */,
                8E8A67482863E746003DB257 /* Release */,
            );
            defaultConfigurationIsVisible = 0;
            defaultConfigurationName = Release;
        };
/* End XCConfigurationList section */

 至此 .pbxproj 中的 section 就看完了,虽然内容许多,可是对项目构建、项目结构了解的话仍是能比较明晰的了解各个 section 的意义的,XcodeProj 大体来说就是装备了项目的文件途径信息 PBXBuildFile、项目中的 Target 及其依靠信息、编译中的 Config 信息(XCBuildConfiguration)。大致了解了他的结构后,就会觉得虽然各方面有条有理,可是,可是,架不住项目大文件多的时候,.pbxproj 的长度会指数级增长。

参考链接

参考链接:

  • Xcode Project File Format
  • [iOS]XcodeProject的内部结构分析
  • iOS 开发 xcode中的project.pbxproj–深入分析
  • iOS 开发:深入了解 Xcode 工程结构(一)
  • XCode工程文件结构及Xcodeproj结构的运用( 二 )
  • simonwagner/mergepbx
  • mjmsmith/pbxplorer
  • iOS 开发 xcode中的project.pbxproj–深入分析