好吧,我对 Xcode 的构建过程很好奇。设置多个目标,如何自动进行版本控制以及总体了解系统,以便我可以操纵它来做我想做的事情。
是否有人有任何书籍或可以向我指出一些文档,以便我可以弄清楚所有这些?
非常感谢。
另一件事,如果有人真的看到了这一点,因为改变了它。
但是有人知道有哪些书会关注 Xcode 4 吗?有 Xcode 3 Unleashed,但我真的很好奇是否有任何书籍重点关注 Xcode 4。
对于一致、可重复、可自动化的构建来说,真正重要的一件事是了解
xcodebuild
命令。遗憾的是,除了手册页(类型man xcodebuild
)之外,我找不到任何官方文档。 这里有一个有用的自动化 iPhone 构建指南,其中包括使用 xcodebuild
进行构建以及使用 agvtool
进行版本控制。这与 Mac 应用程序的一般构建同样相关。
通常使用 xcodebuild 构建非常简单:
cd project_dir
xcodebuild -project myproject.xcodeproj -configuration Release ARCHS="x86_64 i386" build
一旦您可以从这样的脚本进行构建,就可以很容易地插入到自动构建系统中。
Xcode 构建过程
xcodebuild
[示例]
Objective-C语言
1. Preprocessing
[Driver][Preprocessing][Parsing and Semantic Analysis] Parser `.m -> AST`
2.Compiling by compiler(Clang)
[Code Generation and Optimization](GCC_OPTIMIZATION_LEVEL) LLVM IR Generation `AST -> LLVM IR`.
3. Assembling
[LLVM backend] LLVM `LLVM IR -> .o`
4. Static Linking(ld)
5. Output binary
Xcode 和 Objective-C 公开了其中一些步骤:
Preprocessing
:替换宏
拆分
.h
和 .m
。
在 Xcode 中,您可以通过选择
查看
.m
文件的预处理器输出
select .m file -> Product -> Perform Action -> Preprocess
Compiling
- 翻译低级中间代码。 select .m file -> Product -> Perform Action -> Assemble
Assembling
(产生 .o
) - 将代码转换为目标文件 (.o
文件)[Mach-O] 在 Xcode 中,您将在 Xcode 中的 <product_name>.build/Objects-normal
文件夹中找到这些目标文件派生数据目录。
Static Linking
(产生 .app
, .a
, .framework
...)[关于] - 它是静态链接器的一部分,必须解析目标文件和库/框架之间的符号。此过程会生成一个合并的可执行文件,其中可以包含其他资源和动态二进制文件
输出二进制
Swift 语言
LVVM Frontend
1. Preprocessing
[Parse module] Parser `.m -> AST`
[Sema module] Type checking > type-checks AST and annotates it with type information
2.Compiling by compiler(Swiftc)
[SILGen module] SIL Generator `AST -> raw SIL` > optimizations
`Guaranteed Optimization Passes`, `Diagnostic Passes` `raw SIL -> canonical SIL. This optimization is applied in any case
`Optimization Passes`(SWIFT_OPTIMIZATION_LEVEL)
[IRGen] LLVM IR Generation
LVVM Backend
3. Assembling
[LLVM backend] LLVM `LLVM IR -> .o`
4. Static Linking(ld)
5. Output binary
Swift 示例
import Foundation
class ClassA {
func foo(param: String) -> Int {
return 1
}
}
AST
-dump-parse Parse input file(s) and dump AST(s)
-dump-ast Parse and type-check input file(s) and dump AST(s)
-print-ast Parse and type-check input file(s) and pretty print AST(s)
# xcrun swiftc -dump-parse "ClassA.swift"
(source_file "ClassA.swift"
(import_decl range=[ClassA.swift:8:1 - line:8:8] 'Foundation')
(class_decl range=[ClassA.swift:10:1 - line:14:1] "ClassA"
(func_decl range=[ClassA.swift:11:5 - line:13:5] "foo(param:)"
(parameter "self")
(parameter_list range=[ClassA.swift:11:13 - line:11:27]
...
#xcrun swiftc -dump-ast "ClassA.swift"
(source_file "ClassA.swift"
(import_decl range=[ClassA.swift:8:1 - line:8:8] 'Foundation')
(class_decl range=[ClassA.swift:10:1 - line:14:1] "ClassA" interface type='ClassA.Type' access=internal non-resilient
(func_decl range=[ClassA.swift:11:5 - line:13:5] "foo(param:)" interface type='(ClassA) -> (String) -> Int' access=internal
(parameter "self")
...
# xcrun swiftc -print-ast "ClassA.swift"
import Foundation
internal class ClassA {
internal func foo(param: String) -> Int
@objc deinit
internal init()
}
#xcrun swiftc -frontend -emit-syntax "ClassA.swift" | python -m json.tool
{
"kind": "SourceFile",
"layout": [
{
"kind": "CodeBlockItemList",
"layout": [
{
"kind": "CodeBlockItem",
"layout": [
{
"kind": "ImportDecl",
"layout": [
{
...
SIL
-emit-silgen Emit raw SIL file(s)
-emit-sil Emit canonical SIL file(s)
# xcrun swiftc -emit-silgen "ClassA.swift"
sil_stage raw
import Builtin
import Swift
import SwiftShims
import Foundation
class ClassA {
func foo(param: String) -> Int
@objc deinit
init()
}
// ClassA.foo(param:)
sil hidden [ossa] @$s6ClassAAAC3foo5paramSiSS_tF : $@convention(method) (@guaranteed String, @guaranteed ClassA) -> Int {
// %0 "param" // user: %2
sil_vtable ClassA {
#ClassA.foo: (ClassA) -> (String) -> Int : @$s6ClassAAAC3foo5paramSiSS_tF // ClassA.foo(param:)
#ClassA.init!allocator: (ClassA.Type) -> () -> ClassA : @$s6ClassAAACABycfC // ClassA.__allocating_init()
#ClassA.deinit!deallocator: @$s6ClassAAACfD // ClassA.__deallocating_deinit
}
// Mappings from '#fileID' to '#filePath':
// 'ClassA/ClassA.swift' => 'ClassA.swift'
...
LLVM 红外
-emit-ir Emit LLVM IR file(s)
xcrun swiftc -emit-ir "ClassA.swift"
; ModuleID = '<swift-imported-modules>'
source_filename = "<swift-imported-modules>"
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx12.0.0"
%objc_class = type { %objc_class*, %objc_class*, %swift.opaque*, %swift.opaque*, %swift.opaque* }
define i32 @main(i32 %0, i8** %1) #0 {
entry:
%2 = bitcast i8** %1 to i8*
ret i32 0
}
...
-emit-object Emit object file(s) (-c)
-emit-executable Emit a linked executable
您还可以使用 Xcode
Report Navigator
了解有关构建过程的更多信息。此外,Xcode v14
还包含构建过程可视化和分析的强大功能
Show the Report navigator -> <select build> -> <right_click> -> Show in Timeline
//or
Show the Report navigator -> <select build> -> Editor -> Open Timeline