学习和理解 Xcode 构建系统

问题描述 投票:0回答:2

好吧,我对 Xcode 的构建过程很好奇。设置多个目标,如何自动进行版本控制以及总体了解系统,以便我可以操纵它来做我想做的事情。

是否有人有任何书籍或可以向我指出一些文档,以便我可以弄清楚所有这些?

非常感谢。

另一件事,如果有人真的看到了这一点,因为改变了它。

但是有人知道有哪些书会关注 Xcode 4 吗?有 Xcode 3 Unleashed,但我真的很好奇是否有任何书籍重点关注 Xcode 4。

xcode debugging automation build target
2个回答
10
投票

对于一致、可重复、可自动化的构建来说,真正重要的一件事是了解

xcodebuild
命令。遗憾的是,除了手册页(类型
man xcodebuild
)之外,我找不到任何官方文档。 这里有一个有用的自动化 iPhone 构建指南,其中包括使用
xcodebuild
进行构建以及使用
agvtool
进行版本控制。这与 Mac 应用程序的一般构建同样相关。

通常使用 xcodebuild 构建非常简单:

cd project_dir
xcodebuild -project myproject.xcodeproj -configuration Release ARCHS="x86_64 i386" build

一旦您可以从这样的脚本进行构建,就可以很容易地插入到自动构建系统中。


3
投票

Xcode 构建过程

[LLVM]Clang LLVMSwift LLVM

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 公开了其中一些步骤:

  1. Preprocessing
  • 替换宏

  • 拆分

    .h
    .m

    在 Xcode 中,您可以通过选择

     查看 
    .m

    文件的预处理器输出
      select .m file -> Product -> Perform Action -> Preprocess
    
  1. Compiling
    - 翻译低级中间代码。
    通常,您在调试不属于您的代码时可以看到此文件。 Xcode 允许您查看输出。

     select .m file -> Product -> Perform Action -> Assemble
    
  2. Assembling
    (产生
    .o
    ) - 将代码转换为目标文件 (
    .o
    文件)[Mach-O] 在 Xcode 中,您将在 Xcode 中的
    <product_name>.build/Objects-normal
    文件夹中找到这些目标文件派生数据目录。

  3. Static Linking
    (产生
    .app
    ,
    .a
    ,
    .framework
    ...)[关于] - 它是静态链接器的一部分,必须解析目标文件和库/框架之间的符号。此过程会生成一个合并的可执行文件,其中可以包含其他资源和动态二进制文件

  4. 输出二进制

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

© www.soinside.com 2019 - 2024. All rights reserved.