本文主要想通过解析 Xcode 编译 log,让我们更加清晰的了解 Xcode 是如何帮助我们生成 app。
如下图,可以发现 xcode 是根据 target 分开进行编译的。每个 target 的具体的编译过程也可以通过展开 log 日志获得。
日志基本的格式就是首先简明一句说明要干什么,然后缩进的几行说明具体的操作。比如:
(1) ProcessPCH /.../Pods-SSZipArchive-prefix.pch.pch Pods-SSZipArchive-prefix.pch normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler
(2) cd /.../Dev/objcio/Pods
setenv LANG en_US.US-ASCII
setenv PATH "..."
(3) /.../Xcode.app/.../clang
(4) -x objective-c-header
(5) -arch armv7
... configuration and warning flags ...
(6) -DDEBUG=1 -DCOCOAPODS=1
... include paths and more ...
(7) -c
(8) /.../Pods-SSZipArchive-prefix.pch
(9) -o /.../Pods-SSZipArchive-prefix.pch.pch
就是在处理 pch 头文件,首先切换到 pch 的目录下,然后设置环境变量,然后启动 clang 并进行一系列的配置。在这之后一般就会产生具体的 .o文件作为产出(一般是有多个,针对不同的平台架构分别有一个,不过一般紧接着会把这些聚合成一个通用的 library。)。同时注意,不同的 target 也是有编译顺序的,具体的要看 target 之间的依赖关系。
接下来就是编译过程的控制,在 xcode 中可以通过 Build phases, Build settings 以及 Build rules 来进行控制。
Build phases 主要是用来控制从源文件到可执行文件的整个过程的,所以应该说是面向源文件的,包括编译哪些文件,以及在编译过程中执行一些自定义的脚本什么的。编译的时候将根据顺序来进行编译。这里固定的有:
- Compile Sources:编译源文件。
- Link Binary With Libraries:相关的链接库。
- Copy Bundle Resources:要拷贝的资源文件,有时候如果一个资源文件在开发过程中发现找不到,可以在这里找一下,看看是不是加进来了。
- 如果使用了 Cocoapods,那么将会被添加:
- [CP] Check Pods Manifest.lock:检查 Podfile.lock 和 Manifest.lock 文件的一致性
- [CP] Embed Pods Frameworks:将所有 cocoapods 打的 framework 拷贝到包中。
- [CP] Copy Pods Resources:将所有 cocoapods 的资源文件拷贝到包中。
Build rules 主要是用来控制如何编译某种类型的源文件的,假如说相对某种类型的原文件进行特定的编译,那么就应该在这里进行编辑了。同时这里也会大量的运用一些 xcode 中的环境变量,完整的官方文档在这里:Build Settings Reference ,例如:
- Copy Plist File:在编译打包的时候,将 info.plist 文件拷贝。
- Compress PNG File:在编译打包的时候,将 PNG 文件压缩。
- Swift Compiler:Swift 文件的编译方式,使用 Swift 编译器。
- …
Build settings 则是对编译工作的细节进行设定,在这个窗口里可以看见大量的设置选项,从编译到打包再到代码签名都有,这里要注意 settings 的 section 分类,同时一般通过右侧的 inspector 就可以很好的理解选项的意义了。
最后,要说一下我们的工程文件.pbxproj,以上的所有的这些选项都保存在这个文件中。当然也包括 target 的信息,项目所有文件的信息,这个文件是一个文本文件,可以用文本编辑器打开。里头的内容基本是可读性比较强的。基本的思路很面向对象,每个东西都有属性,如果属性是另一个对象,值就是那个对象的一个『引用』,就是一串数字(唯一的)作为表示。每个对象都有这样的引用。
Building App 命令解析
构建一个应用程序不仅仅是编译和链接Obj-C文件。让我们先来看看这些步骤在整个构建流中的位置。 以下是构建日志中比较关键的流程:
Build target CompileDemo_Example of project CompileDemo with configuration Debug
WriteAuxiliaryFile xxx/CompileDemo_Example.hmap (in target 'CompileDemo_Example' from project 'CompileDemo')
cd /Users/xxx/workspace/code/CompileDemo/Example
write-file CompileDemo_Example.hmap
CompileC xxx/CDAppDelegate.o xxx/CDAppDelegate.m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC xxx/main.o xxx/main.m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
Ld CompileDemo_Example normal (in target 'CompileDemo_Example' from project 'CompileDemo')
CompileStoryboard CompileDemo/Base.lproj/LaunchScreen.storyboard
CompileAssetCatalog CompileDemo/Images.xcassets
ProcessInfoPlistFile CompileDemo/Info.plist
LinkStoryboards ...
Touch CompileDemo_Example.app
CodeSign CompileDemo_Example.app
Build succeeded
主要流程就是把各个文件编译,最后链接到一起制作App。 这里重要的两点:
- CompileC: Xcode如何编译类c代码
- Ld: Xcode如何将目标文件链接到可执行文件中
命令解释
- CreateBuildDirectory : 创建build目录,包含最终路径 Build/Products, 中间产物路径 Build/Intermediates.noindexs
CreateBuildDirectory /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex cd /Users/xxx/workspace/code/CompileDemo/Example builtin-create-build-directory /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex
* 每一个类都三个文件 .d、.dia、.o
* .d: 表示这个类所依赖的其他类,即使用import导入的头文件,会自动寻找所有的依赖头文件,包含多级依赖 (a依赖b,b又依赖c,那么最终a也会依赖c)
* .dia: 是diagnose的简写,就是诊断的意思,我们在Xcode写的源代码,经过编译的时候有时候会生成一些警告信息,都是放到这里面的
* .o: 对象文件,.m经过编译生成.o文件,用来链接到静态库/可执行文件中
- WriteAuxiliaryFile: 写入辅助文件
- 处理 Entitlements
- .LinkFileList (链接的对象文件.o列表)
- .SwiftFileList (swift 文件路径列表)
WriteAuxiliaryFile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/all-product-headers.yaml (in target 'CompileDemo_Example' from project 'CompileDemo') cd /Users/xxx/workspace/code/CompileDemo/Example write-file /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/all-product-headers.yaml WriteAuxiliaryFile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/CompileDemo_Example-project-headers.hmap (in target 'CompileDemo_Example' from project 'CompileDemo') cd /Users/xxx/workspace/code/CompileDemo/Example write-file /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/CompileDemo_Example-project-headers.hmap WriteAuxiliaryFile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CompileDemo_Example.LinkFileList (in target 'CompileDemo_Example' from project 'CompileDemo') cd /Users/xxx/workspace/code/CompileDemo/Example write-file /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CompileDemo_Example.LinkFileList WriteAuxiliaryFile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CompileDemo_Example.SwiftFileList (in target 'CompileDemo_Example' from project 'CompileDemo') cd /Users/xxx/workspace/code/CompileDemo/Example write-file /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CompileDemo_Example.SwiftFileList - CompileC
-x <language>: 输入文件是用什么编程语言写的-arch <architecture>: 编译的架构-std=<standard>: 编程语言的标准集-O0: 代码生成的时候的一些优化-D<macroname>=<value>: 宏定义 #define-iquote <directory>: inclue 的搜索路径-I<directory>: 头文件搜索文件夹-F<directory>: framework搜索文件-MMD -MT dependencies -MF: 依赖文件.d-MMD -MT dependencies -MF /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/main.d--serialize-diagnostics: 代码诊断结果.dia-W: 编译警告-Werror: 警告转错误-c: 表示编译步骤:preprocess compile assemble,没有链接步骤- ...
- Libtool :链接 .o 文件
Usage: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static [-] file [...] [-filelist listfile[,dirname]] [-arch_only arch] [-sacLT] [-no_warning_for_no_symbols] Usage: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool \ -dynamic [-] file [...] [-filelist listfile[,dirname]] [-arch_only arch] [-o output] [-install_name name] [-compatibility_version #] [-current_version #] [-seg1addr 0x#] [-segs_read_only_addr 0x#] [-segs_read_write_addr 0x#] [-seg_addr_table <filename>] [-seg_addr_table_filename <file_system_path>] [-all_load] [-noall_load]Libtool /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/Pods_CompileDemo_Example.framework/Pods_CompileDemo_Example normal (in target 'Pods-CompileDemo_Example' from project 'Pods') cd /Users/xxx/workspace/code/CompileDemo/Example/Pods export IPHONEOS_DEPLOYMENT_TARGET\=10.0 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool \ -static \ -arch_only arm64 \ -D \ -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.5.sdk \ -L/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator \ -filelist /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/Pods-CompileDemo_Example.build/Objects-normal/arm64/Pods_CompileDemo_Example.LinkFileList \ -framework Foundation \ -dependency_info /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/Pods-CompileDemo_Example.build/Objects-normal/arm64/Pods_CompileDemo_Example_libtool_dependency_info.dat \ -o /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/Pods_CompileDemo_Example.framework/Pods_CompileDemo_Example - Ld 将库链接到 app 可执行文件
- -L :.a
- -F :framework
- -Xlinker :给链接器传递参数,
-Xlinker -rpath-link -Xlinker <dir> -Xlinker <dir>
Ld /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo_Example.app/CompileDemo_Example normal (in target 'CompileDemo_Example' from project 'CompileDemo') cd /Users/xxx/workspace/code/CompileDemo/Example /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -target arm64-apple-ios9.3-simulator -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.5.sdk -L/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator -F/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator -F/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo -filelist /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CompileDemo_Example.LinkFileList -Xlinker -rpath -Xlinker /usr/lib/swift -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks -Xlinker -rpath -Xlinker @executable_path/Frameworks -dead_strip -Xlinker -object_path_lto -Xlinker /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CompileDemo_Example_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -Xlinker -objc_abi_version -Xlinker 2 -fobjc-arc -fobjc-link-runtime -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -L/usr/lib/swift -Xlinker -add_ast_path -Xlinker /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CompileDemo_Example.swiftmodule -framework CompileDemo -Xlinker -sectcreate -Xlinker __TEXT -Xlinker __entitlements -Xlinker /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/CompileDemo_Example.app-Simulated.xcent -framework CoreGraphics -framework UIKit -framework Foundation -framework Pods_CompileDemo_Example -Xlinker -no_adhoc_codesign -Xlinker -dependency_info -Xlinker /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CompileDemo_Example_dependency_info.dat -o /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo_Example.app/CompileDemo_Example - 拷贝/处理资源文件
- CpResource : caf、json、db、bundle、txt、jpg
- CompileStoryboard 编译 .storyboard 为 .storyboardc 文件
- CopyPlistFile
- CopyPNGFile :copy直接放在项目文件夹中的图片文件,不是 .xcassets 中的图片
- CompileAssetCatalog (编译 .xcassets 文件 为 Assets.car)
- 对 .xcassets 文件进行处理 ,生成 .car 文件,同时会对 AppIcon 和 LaunchImage 进行处理,同时会对文件名称重新格式化命名
- 生成
assetcatalog_generated_info.plist(是必须的AppIcon和LaunchImage信息),assetcatalog_dependencies(文件内容主要是AppIcon和LaunchImage的文件名称)
CompileAssetCatalog /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo_Example.app /Users/xxx/workspace/code/CompileDemo/Example/CompileDemo/Images.xcassets (in target 'CompileDemo_Example' from project 'CompileDemo') cd /Users/xxx/workspace/code/CompileDemo/Example /Applications/Xcode.app/Contents/Developer/usr/bin/actool --output-format human-readable-text --notices --warnings --export-dependency-info /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/assetcatalog_dependencies --output-partial-info-plist /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/assetcatalog_generated_info.plist --app-icon AppIcon --compress-pngs --enable-on-demand-resources YES --filter-for-device-model iPod9,1 --filter-for-device-os-version 15.5 --development-region English --target-device iphone --target-device ipad --minimum-deployment-target 9.3 --platform iphonesimulator --compile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo_Example.app /Users/xxx/workspace/code/CompileDemo/Example/CompileDemo/Images.xcassets - ProcessInfoPlistFile:处理 info.plist 信息,把上面的处理 .xcassets 生成的 plist 文件合并到当前的 info.plist 文件上
ProcessInfoPlistFile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo_Example.app/Info.plist /Users/xxx/workspace/code/CompileDemo/Example/CompileDemo/CompileDemo-Info.plist (in target 'CompileDemo_Example' from project 'CompileDemo') cd /Users/xxx/workspace/code/CompileDemo/Example builtin-infoPlistUtility /Users/xxx/workspace/code/CompileDemo/Example/CompileDemo/CompileDemo-Info.plist -producttype com.apple.product-type.application -genpkginfo /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo_Example.app/PkgInfo -expandbuildsettings -format binary -platform iphonesimulator -additionalcontentfile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Base.lproj/Main-SBPartialInfo.plist -additionalcontentfile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Base.lproj/LaunchScreen-SBPartialInfo.plist -additionalcontentfile /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/assetcatalog_generated_info.plist -o /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo_Example.app/Info.plist
- LinkStoryboards 链接前面生成的 storyboradc
- PhaseScriptExecution:执行脚本,build phase 中的
- CodeSign 签名:前面生成的
Entitlements变成的.xcent文件,经过处理放置到.app文件夹下面
如果项目是基于CocoaPods,可以在Pods/Target Support Files/Pods-项目名/Pods-项目名-resource.sh文件中来看一下编译过程中对不同资源文件进行处理的命令。如下图,此处不逐一解释。
CompileC
- 命令 Clang’s support for modules.
-
-x <language>: 输入文件是用什么编程语言写的,确保Clang与它编译的语言完全一致 -
export LANG:配置语言环境 -
-arch <architecture>: 编译的架构 -
-std=<standard>: 编程语言的标准集 -
-O0:代码生成的时候的一些优化级别,O0是不优化,以便编译器输出更详细,使编译器输出更接近于输入的代码,减少逐行调试和逐行设置断点导致的问题。 -
-g:启用调试信息生成 -
-DDEBUG=1: 确保可以使用#if DEBUG -
-D<macroname>=<value>: 宏定义 #define -
-iquote <directory>: inclue 的搜索路径,#include "header.h"将在这个目录中查找,但#include < header.h >不会 -
-I<directory>: 头文件搜索文件夹,include的引号和尖括号样式将在此目录中查找。 -
-F<directory>: framework搜索文件,-framework Some.framework会优先在这里搜索 -
-iquote,-I的使用会优先指定到 hmap,而不是头文件的路径,以加速头文件路径查找 -
-MMD -MT dependencies -MF: 依赖文件.d, 目的应该是如果这个文件发生变化,应该重建的东西都有哪些-MMD -MT dependencies -MF /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/main.d -
--serialize-diagnostics: 代码诊断结果.dia -
-c: 表示编译步骤:preprocess compile assemble,没有链接步骤 -
-o:输出结果目录 -
-fobjc-legacy-dispatch:告诉clang应该采用什么样的Objective-C消息发送分派方法。 -
-fobjc-arc:使用arc -
-fmodules启用模块、基于模块的导入和模块相关语法,像@import。 -
-gmodules打开模块调试。 -
-fmodules-cache-path:告诉编译器在哪里缓存模块查找结果。Xcode在一个名为ModuleCache的文件夹中创建缓存数据目录。- 注意,模块缓存不是特定于项目的,而是在共享位置。如果你看一眼你的模块缓存目录,你会看到如下内容:
- 一个
Session.modulevalidation文件,模块构建会话文件,在xxx/DerivedData/ModuleCache - 一个
modules.timestamp文件,时间戳文件 - 一堆目录文件,所有目录名都是13个大写字母数字字符。
- 在每个目录中都有名为
$(MODULE_NAME)-$(THIRTEEN_ALPHANUMERICS).pcm及 的文件。大部分成对出现。有的可能有modules.idx文件,$(MODULE_NAME)-$(THIRTEEN_ALPHANUMERICS).pcm.lock也有可能有
- 一个
- 这些是预编译的模块文件和相关的跟踪信息,保证模块的安全使用。
- 注意,模块缓存不是特定于项目的,而是在共享位置。如果你看一眼你的模块缓存目录,你会看到如下内容:
-
-fmodules-prune-interval:为编译器删除模块缓存的时间设置了一个最小界限。Xcode将其设置为24小时,这比编译器默认的7天要激进得多。 -
-fmodules-prune-after:表示,如果一个模块缓存文件在指定的秒数内没有被访问,那么它就可以被删除。Xcode将这个时间设置为4天,而不是编译器默认的31天。 -
-fmodules-validate-once- over -build-session:避免模块在单个构建会话期间重复验证。 -
-fbuild-session-file:命名一个文件,该文件的修改时间被视为构建会话开始的时间,这对于一些与模块何时验证什么相关的决策很重要。 -
-Wnon-modular-include-in-framework-module:打开警告:“warning: include of non-modular header inside framework module…” -
Configure warnings
-Wno-:禁用警告;其余的则使他们得以实现。-Werror-:导致编译器将已定义的警告转化成error。
-
-isysroot:告诉clang提供的目录是文件系统的根目录,并查找与该文件夹相关的系统头文件、库和工具。这是一种一次性重写标准查找路径的快速简便方法,而不需要一堆-I、-L、-F等标记来逐个完成。虽然它为我们做了很多工作,但还是有很多路径需要 -iquote,-I, -F。 -
-mios-simulator-version-min:最小system -
...
-
CompileC /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CDViewController.o /Users/xxx/workspace/code/CompileDemo/Example/CompileDemo/CDViewController.m normal arm64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target 'CompileDemo_Example' from project 'CompileDemo')
<!--进入$SRCROOT目录,所有目标文件的根目录-->
cd /Users/xxx/workspace/code/CompileDemo/Example
export LANG\=en_US.US-ASCII
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
-x objective-c
-target arm64-apple-ios9.3-simulator
-fmessage-length\=0
-fdiagnostics-show-note-include-stack
-fmacro-backtrace-limit\=0
<!--使用与C99对应的版本,并使用GNU扩展-->
-std\=gnu99
-fobjc-arc
-fmodules
-gmodules
-fmodules-cache-path\=/Users/xxx/workspace/DerivedData/ModuleCache.noindex -fmodules-prune-interval\=86400
-fmodules-prune-after\=345600
-fbuild-session-file\=/Users/xxx/workspace/DerivedData/ModuleCache.noindex/Session.modulevalidation
-fmodules-validate-once-per-build-session
-Wnon-modular-include-in-framework-module
-Werror\=non-modular-include-in-framework-module
-Wno-trigraphs
-fpascal-strings
-O0
-Wno-missing-field-initializers
-Wno-missing-prototypes
-Werror\=return-type
-Wno-implicit-atomic-properties
-Werror\=deprecated-objc-isa-usage
-Wno-objc-interface-ivars
-Werror\=objc-root-class
-Wno-arc-repeated-use-of-weak
-Wduplicate-method-match
-Wno-missing-braces
-Wparentheses
-Wswitch
-Wunused-function
-Wno-unused-label
-Wno-unused-parameter
-Wunused-variable
-Wunused-value
-Wempty-body
-Wuninitialized
-Wconditional-uninitialized
-Wno-unknown-pragmas
-Wno-shadow
-Wno-four-char-constants
-Wno-conversion
-Wconstant-conversion
-Wint-conversion
-Wbool-conversion
-Wenum-conversion
-Wno-float-conversion
-Wno-non-literal-null-conversion
-Wno-objc-literal-conversion -Wshorten-64-to-32
-Wpointer-sign
-Wno-newline-eof
-Wno-selector
-Wno-strict-selector-match
-Wundeclared-selector
-Wno-deprecated-implementations
-DDEBUG\=1
-DCOCOAPODS\=1
-DOBJC_OLD_DISPATCH_PROTOTYPES\=1
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.5.sdk
-fstrict-aliasing
-Wprotocol
-Wdeprecated-declarations
-g
-Wno-sign-conversion
-Wno-infinite-recursion
-Wno-comma
-Wno-block-capture-autoreleasing
-Wno-strict-prototypes
-Wno-semicolon-before-method-body
-fobjc-abi-version\=2
<!--告诉clang应该采用什么样的Objective-C消息发送分派方法-->
-fobjc-legacy-dispatch
-index-store-path /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Index/DataStore
-iquote /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/CompileDemo_Example-generated-files.hmap
-I/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/CompileDemo_Example-own-target-headers.hmap
-I/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/CompileDemo_Example-all-non-framework-target-headers.hmap
-ivfsoverlay /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/all-product-headers.yaml
-iquote /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/CompileDemo_Example-project-headers.hmap
-I/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/include
-I/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo/CompileDemo.framework/Headers
-I/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/DerivedSources-normal/arm64
-I/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/DerivedSources/arm64
-I/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/DerivedSources
-F/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator
-F/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo
-include /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/PrecompiledHeaders/SharedPrecompiledHeaders/2206351231756493926/CompileDemo-Prefix.pch
-MMD -MT dependencies -MF /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CDViewController.d
--serialize-diagnostics /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CDViewController.dia
-c /Users/xxx/workspace/code/CompileDemo/Example/CompileDemo/CDViewController.m
-o /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CDViewController.o
-index-unit-output-path /CompileDemo.build/Debug-iphonesimulator/CompileDemo_Example.build/Objects-normal/arm64/CDViewController.o
<!--确保PATH包含特定于平台的二进制文件
它将用于解析命令名的PATH,如clang,设置为实际路径,如/usr/bin/clang:,
以冒号分隔的PATH列表中的每个目录将按从左到右的顺序搜索与命令名匹配的目录,第一个目录胜出。
如果没有找到匹配,则在shell中得到一个“未知命令”错误-->
export PATH\=/Users/xxx/Library/Developer/Toolchains/swift-BD-2022-05-25-15-51-44-lldb_framework-tools\=R-buildbot_osx_package-no_test.xctoolchain/usr/bin:
/Users/xxx/Library/Developer/Toolchains/swift-BD-2022-05-25-15-51-44-lldb_framework-tools\=R-buildbot_osx_package-no_test.xctoolchain/usr/local/bin:
/Users/xxx/Library/Developer/Toolchains/swift-BD-2022-05-25-15-51-44-lldb_framework-tools\=R-buildbot_osx_package-no_test.xctoolchain/usr/libexec:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/bin:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/libexec:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/bin:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/local/bin:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/local/bin:
/Applications/Xcode.app/Contents/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/local/bin:
/usr/local/bin:
/usr/bin:
/bin:
/usr/sbin:
/sbin
LD:将目标文件链接到可执行文件中
Ld $(CONFIGURATION_BUILD_DIR)/$(EXECUTABLE_PATH)
normal
x86_64
Xcode选择让clang前端为它管理所有的细节,而不是直接调用链接器。
为了做到这一点,它需要传递在编译过程中使用的许多选项,以保持相同的“环境”进行链接,所以这一次我们将遇到许多熟悉的标志,如-arch和-isysroot,用于设置目标架构、搜索路径等。
- 命令
-L:.a-F:framework-Xlinker:给链接器传递参数,是一个clang传参通道。-Xlinker -rpath-link -Xlinker <dir> -Xlinker <dir>(还有另一种 WL)-Xlinker -rpath -Xlinker @executable_path/Frameworks:运行时搜索路径,确保动态链接器dyld在运行时能够链接到内部的framework, 实际Xcode想要传递的参数是-rpath @executable_path/Frameworks,但每个参数前必须加-Xlinker-runpath: 运行可执行文件的搜索路径@executable_path:相对于可执行文件的路径,用于运行时dyld进行链接
-object_path_lto: link-time optimization (LTO),链接时间优化,这个参数告诉链接器在哪里写入LTO时需要创建的临时文件。- 如果没标记,会选个点执行LTO,之后删除临时文件
- 如果有标记,会保留该文件,以供其他工具随时查看,比如读取调试信息
-export_dynamic: 禁用全局内联和删除。可以防止LTO内联或以其他方式删除全局函数。最终需要导出的内容是动态确定的,应该是使 Xcode 更安全-no_deduplicate:禁用链接器中的重复数据删除通道-objc_abi_version:Obj-C ABI版本-dependency_info:链接时文件依赖信息
-filelist:指定 .LinkFileList 链接文件列表,避免了在命令行中使用大量的文件路径作为它们自己的参数。文件本身只是一个以换行符分隔的文件路径列表。-o:指定可执行文件输出路径,在 products 目录中的 app bundle 中,也是最终运行应用的地方。
Ld /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo/CompileDemo.framework/CompileDemo normal (in target 'CompileDemo' from project 'Pods')
cd /Users/xxx/workspace/code/CompileDemo/Example/Pods
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
-target arm64-apple-ios10.0-simulator
-dynamiclib
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.5.sdk
-L/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo
-F/Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo
-filelist /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/CompileDemo.build/Objects-normal/arm64/CompileDemo.LinkFileList
-install_name @rpath/CompileDemo.framework/CompileDemo
-Xlinker -rpath -Xlinker @executable_path/Frameworks
-Xlinker -rpath -Xlinker @loader_path/Frameworks -dead_strip
-Xlinker -object_path_lto
-Xlinker /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/CompileDemo.build/Objects-normal/arm64/CompileDemo_lto.o
-Xlinker -export_dynamic -Xlinker -no_deduplicate
-Xlinker -objc_abi_version -Xlinker 2
-fobjc-arc
-fobjc-link-runtime
-framework Foundation
-Xlinker -no_adhoc_codesign
-compatibility_version 1
-current_version 1
-Xlinker -dependency_info
-Xlinker /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/CompileDemo.build/Objects-normal/arm64/CompileDemo_dependency_info.dat
-o /Users/xxx/workspace/DerivedData/CompileDemo-fswmtdmeapiqpkexlcagflyhmyfs/Build/Products/Debug-iphonesimulator/CompileDemo/CompileDemo.framework/CompileDemo
Manual Swift: Understanding the Swift/Objective-C Build Pipeline
Big Nerd Ranch - Build Log Groveling for Fun and Profit: Manual Swift Continued
Build Log Groveling for Fun and Profit, Part 2: Even More Manual Swift