一、build 日志
在 Xcode 的 Report navigator
中可以看到 build 日志(如下圖所示)。
每一行任務就是一個 task,每個 task顯示的信息有狀態、任務名、耗時,點擊最右邊的箭頭,可以展開每條任務的執行細節。類似這種格式:
CompileC /Users/xianglongchen/Library/Developer/Xcode/DerivedData/Playground_iOS-hfqoqrhlwhirthhjzanxhdrxyfoz/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/SDWebImage.build/Objects-normal/x86_64/UIView+WebCacheOperation.o /Users/xianglongchen/Desktop/Playground_iOS/Pods/SDWebImage/SDWebImage/UIView+WebCacheOperation.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target: SDWebImage)
cd /Users/xianglongchen/Desktop/Playground_iOS/Pods
export LANG=en_US.US-ASCII
...
可以看到上面的任務細節中其實就是由很多條 shell 命令組成的,包括 CompileC
、Ld
等。
題外話:在 build log 中可以看到 Xcode 在構建過程中會在 DerivedData 這個目錄下生成一些臨時數據
二、build 流程設置
1. Build Phases
Build Phases 從一個高層面上展示了整個構建過程,我們可以在 Build Phases 里設置各個 Phases 的配置項,也可以新加一個或者多個 Build Phase。
上圖中所示的工程一共有 5 個 Phases,build 時會按照其指定的順序執行:
- Target Dependencies:用來告訴 build system 在開始構建當前 target 之前需要先構建好哪些 target
- [CP]Check Pods Manifest.lock:這是 CocoaPods 自動添加的一個 phase,因為項目中使用了 CocoaPods
- Compile Sources:告訴 build system 哪些資源需要參與編譯
- Link Binary With Libraries:告訴 build system 在當前 target 的所有源碼編譯成目標文件后要跟哪些庫鏈接
- Copy Bundle Resources:拷貝靜態資源(比如圖片、字體)到 app bundle 中
自定義 Build Phases
就像 CocoaPods 所做的那樣,我們可以添加自定義的 Phases,自定義 Build Phases 可以用來執行腳本、拷貝資源等等。
2. Build Rules
Build Rules 用來指定不同文件類型分別應該如何被編譯。通常情況下,我們不需要修改默認的規則,但是如果你想為一些新的文件類型添加自定義處理,你可以添加新的編譯規則。
3. Build Settings
在 Build Settings 中,我們可以設置每一個具體的 build 任務的細節。
Build Settings 中提供的選項非常豐富,涉及到了 build 的每個階段,從編譯到鏈接再到代碼簽名和打包。
更詳細介紹的見 Xcode Build System Guide(最新版的 Build Settings Reference 可以在 Xcode Help中查看: 1. In Xcode, choose Help > Xcode Help, or open the Xcode Help website.2. Search for “build settings.”)。
Tips:
在 Xcode 的 build setting 里面也可以通過 “option+鼠標左鍵雙擊” 來顯示幫助彈窗。
image
三、Project 文件
我們在前面所討論的所有設置最終都會被保存到 Xcode Project 文件中去,Xcode Project 文件的格式是 .xcodeproj
,這個文件實際上是一個文件夾。
平時我們基本上不會去看這個 .xcodeproj
文件的細節,除非你在 git merge 時遇到了沖突(嚴格上來講是 .xcodeproj
文件夾中的 project.pbxproj
文件)。
我們可以把這個 project.pbxproj
文件在文本編輯器中打開,這個文件中的內容的可讀性還是比較高的。
下面是一個示例項目的 project.pbxproj
文件簡化后的內容(只保留了 PBXProject
部分的內容):
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
/* End PBXBuildRule section */
/* Begin PBXFileReference section */
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
/* End PBXNativeTarget section */
/* Begin PBXProject section */
856951B22201BD8C0098E0BE /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1000;
ORGANIZATIONNAME = xianglongchen;
TargetAttributes = {
856951B92201BD8C0098E0BE = {
CreatedOnToolsVersion = 10.0;
};
};
};
buildConfigurationList = 856951B52201BD8C0098E0BE /* Build configuration list for PBXProject "Playground_iOS" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 856951B12201BD8C0098E0BE;
productRefGroup = 856951BB2201BD8C0098E0BE /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
856951B92201BD8C0098E0BE /* Playground_iOS */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
/* End XCConfigurationList section */
};
rootObject = 856951B22201BD8C0098E0BE /* Project object */;
}
可以看到這個 project.pbxproj
文件中的內容非常清晰,甚至還有注釋,仔細對比一下,跟 Xcode 中打開時的信息可以一一對應起來,包括文件目錄結構、build settings、build phases、build rules、target 等。
當你需要自動添加文件到 Xcode 工程中來時,可能就需要好好了解一下這個 project.pbxproj
文件了,不過已經有不少大神們踩過坑了,目前已知的一些不錯的解決方案:
- CocoaPods/Xcodeproj:CocoaPods 官方提供的工具,使用 Ruby 編寫的
- 使用代碼為 Xcode 工程添加文件:Draveness 的文章,強烈推薦閱讀,親測有效
- pbxprojHelper--Xcode工程文件助手
- venmo/synx
- Xcodeproj: 使用 ruby 自由的修改Xcode 工程文件
- alunny/node-xcode:一個 nodejs 工具,在 React Native 官方項目中有過應用
參考
- Build Process - objc.io(推薦)
- Xcode Build System Guide(最新版的 Build Settings Reference 可以在 Xcode Help中查看: 1. In Xcode, choose Help > Xcode Help, or open the Xcode Help website.2. Search for “build settings.”)
- The Xcode Build System
- Xcode中的 workspace, project, target 和 scheme
- Building an iOS App Without Xcode's Build System
- What's inside the Derived Data folder?
- 修改 xcodeproj 文件