美文网首页
swift基础_编译和调试

swift基础_编译和调试

作者: 李永开 | 来源:发表于2022-02-09 16:18 被阅读0次

    零.编译swiftc

    1. 网上很多教程有问题,建议多看看官网教程

    2. 准备环境
      brew install cmake ninja sccache
      检查环境
      Run cmake --version: This should be 3.19.6 or higher.
      Run python3 --version: Check that this succeeds.
      Run ninja --version: Check that this succeeds.
      Run sccache --version: Check that this succeeds.

    3. 下载swift源码
      https://github.com/apple/swift/releases找到最新的版本,使用git clone --branch swift-5.5.2-RELEASE https://github.com/apple/swift.git下载

    4. 运行./swift/utils/update-checkout --tag swift-5.5.2-RELEASE --clone下载编译swift相关的库

    图片.png
    1. 编译swift源码,可以得到swfitc
    • 设置sccache
      sccache --start-server
      export SCCACHE_CACHE_SIZE="100G"
    • 3.1使用ninja编译
      swiftRes ./swift/utils/build-script -r --debug-swift-stdlib --lldb
      得到编译后的产物在
      Build files have been written to: /Volumes/yulepan/swiftRes/build/Ninja-RelWithDebInfoAssert+stdlib-DebugAssert/llvm-macosx-x86_64
    • 3.2 使用xcode编译
      ./swift/utils/build-script -x -R --debug-swift
      得到编译后的产物在
      Build files have been written to: /Volumes/yulepan/swiftRes/build/Xcode-ReleaseAssert+swift-DebugAssert
    1. 在vscode的launch.json里面配置我们的swiftc
    图片.png
    1. 遇到问题,可以百度搜索Swift源码编译

    一.使用xcode编译swiftc

    如果你使用上面的命令失败了,那么还是用xcode吧,毕竟苹果爸爸在mac上主要支持xcode,其他的例如vscode appcode都不支持。

    • 我使用ninja在我的M1和MacBook Pro 2019款编译都失败了,后来经过断断续续一个月的尝试,终于成功了。
    • 基于MacBook Pro 2019 Intel芯片,swift-5.5.3-RELEASE,cmake version 3.22.2, Xcode 13.1.0
    • 不要用硬盘啊,否则会出现签名的错误Command CodeSign failed with a nonzero exit code,真的非常蛋疼
    • 总编译时长为3个小时左右,要有耐心,而且电脑尽量不要开其他东西,否则影响速度
    • 这是我参考的教程
    1. 终端执行./swift/utils/build-script --release-debuginfo --debug-swift-stdlib -x --skip-ios --skip-watchos --skip-tvos --swift-darwin-supported-archs="x86_64"
    2. 使用xcode打开cmark.xcodeproj
    图片.png
    将Scheme选择为cmake,然后 command+B 编译下,1秒就成功了。不要习惯性的command+R,这样的话它会一直run,永远不会结束
    图片.png
    特别快
    图片.png
    1. 编译ALL_BUILD
      打开Swift.xcodeproj
    图片.png

    找到ALL_BUILD(话说真的难找啊)


    图片.png

    选中


    图片.png
    然后编辑scheme
    图片.png
    选择优化选项
    图片.png

    点击close,然后command+b编译吧。

    1. 创建自己的target
    图片.png
    点击+号
    图片.png
    创建好后是这样的,多了一个自己的target
    图片.png
    点击自己的target,在Build Settings里面搜索runtime,将Enable Handened Runtime设置为NO,否则你是不能在源码里面打断点的
    图片.png
    然后找到Build Phases,点击+号将刚才在RelWithDebInfo模式下的ALL_BUILD作为依赖
    图片.png
    同样的步骤,找到Edit Scheme
    图片.png
    将自己的target的编译模式设为RelWithDebInfo
    图片.png
    1. 在自己的target的main里面写一个class,然后初始化,并打上断点
    图片.png
    HeapObject.cpp里面打上断点,然后编译,你会发现断点能走进源码了😄
    图片.png

    二.分析SIL

    SIL:swift intermediate language -> swift中间语言


    执行swiftc -dump-ast main.swift拿到main.swift的抽象语法树
    (source_file "main.swift"
      (class_decl range=[main.swift:8:1 - line:10:1] "LYKClass" interface type='LYKClass.Type' access=internal non-resilient
        (destructor_decl implicit range=[main.swift:8:7 - line:8:7] "deinit" interface type='(LYKClass) -> () -> ()' access=internal
          (parameter "self")
          (parameter_list)
          (brace_stmt implicit range=[main.swift:8:7 - line:8:7]))
        (constructor_decl implicit range=[main.swift:8:7 - line:8:7] "init()" interface type='(LYKClass.Type) -> () -> LYKClass' access=internal designated
          (parameter "self")
          (parameter_list)
          (brace_stmt implicit range=[main.swift:8:7 - line:8:7]
            (return_stmt range=[main.swift:8:7 - line:8:7]))))
      (top_level_code_decl range=[main.swift:11:1 - line:11:20]
        (brace_stmt implicit range=[main.swift:11:1 - line:11:20]
          (pattern_binding_decl range=[main.swift:11:1 - line:11:20]
            (pattern_named type='LYKClass' 'cls')
            Original init:
            (call_expr type='LYKClass' location=main.swift:11:11 range=[main.swift:11:11 - line:11:20] nothrow arg_labels=
              (constructor_ref_call_expr type='() -> LYKClass' location=main.swift:11:11 range=[main.swift:11:11 - line:11:11] nothrow
                (declref_expr implicit type='(LYKClass.Type) -> () -> LYKClass' location=main.swift:11:11 range=[main.swift:11:11 - line:11:11] decl=main.(file).LYKClass.init()@main.swift:8:7 function_ref=single)
                (type_expr type='LYKClass.Type' location=main.swift:11:11 range=[main.swift:11:11 - line:11:11] typerepr='LYKClass'))
              (tuple_expr type='()' location=main.swift:11:19 range=[main.swift:11:19 - line:11:20]))
            Processed init:
            (call_expr type='LYKClass' location=main.swift:11:11 range=[main.swift:11:11 - line:11:20] nothrow arg_labels=
              (constructor_ref_call_expr type='() -> LYKClass' location=main.swift:11:11 range=[main.swift:11:11 - line:11:11] nothrow
                (declref_expr implicit type='(LYKClass.Type) -> () -> LYKClass' location=main.swift:11:11 range=[main.swift:11:11 - line:11:11] decl=main.(file).LYKClass.init()@main.swift:8:7 function_ref=single)
                (type_expr type='LYKClass.Type' location=main.swift:11:11 range=[main.swift:11:11 - line:11:11] typerepr='LYKClass'))
              (tuple_expr type='()' location=main.swift:11:19 range=[main.swift:11:19 - line:11:20])))
    ))
      (var_decl range=[main.swift:11:5 - line:11:5] "cls" type='LYKClass' interface type='LYKClass' access=internal let readImpl=stored immutable))
    

    执行swiftc -emit-sil main.swift > ./main.sil && open main.sil拿到main.swift的sil
    sil_stage canonical
    
    import Builtin
    import Swift
    import SwiftShims
    
    class LYKClass {
      @_hasStorage @_hasInitialValue var age: Int { get set }
      @_hasStorage @_hasInitialValue var name: String { get set }
      @objc deinit
      init()
    }
    
    @_hasStorage @_hasInitialValue let cls: LYKClass { get }
    
    // cls
    sil_global hidden [let] @$s4main3clsAA8LYKClassCvp : $LYKClass
    
    // main
    sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
    bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
      alloc_global @$s4main3clsAA8LYKClassCvp         // id: %2
      %3 = global_addr @$s4main3clsAA8LYKClassCvp : $*LYKClass // user: %7
      %4 = metatype $@thick LYKClass.Type             // user: %6
      // function_ref LYKClass.__allocating_init()
      %5 = function_ref @$s4main8LYKClassCACycfC : $@convention(method) (@thick LYKClass.Type) -> @owned LYKClass // user: %6
      %6 = apply %5(%4) : $@convention(method) (@thick LYKClass.Type) -> @owned LYKClass // user: %7
      store %6 to %3 : $*LYKClass                     // id: %7
      %8 = integer_literal $Builtin.Int32, 0          // user: %9
      %9 = struct $Int32 (%8 : $Builtin.Int32)        // user: %10
      return %9 : $Int32                              // id: %10
    } // end sil function 'main'
    
    // variable initialization expression of LYKClass.age
    sil hidden [transparent] @$s4main8LYKClassC3ageSivpfi : $@convention(thin) () -> Int {
    bb0:
      %0 = integer_literal $Builtin.Int64, 10         // user: %1
      %1 = struct $Int (%0 : $Builtin.Int64)          // user: %2
      return %1 : $Int                                // id: %2
    } // end sil function '$s4main8LYKClassC3ageSivpfi'
    
    // Int.init(_builtinIntegerLiteral:)
    sil public_external [transparent] @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int {
    // %0                                             // user: %2
    bb0(%0 : $Builtin.IntLiteral, %1 : $@thin Int.Type):
      %2 = builtin "s_to_s_checked_trunc_IntLiteral_Int64"(%0 : $Builtin.IntLiteral) : $(Builtin.Int64, Builtin.Int1) // user: %3
      %3 = tuple_extract %2 : $(Builtin.Int64, Builtin.Int1), 0 // user: %4
      %4 = struct $Int (%3 : $Builtin.Int64)          // user: %5
      return %4 : $Int                                // id: %5
    } // end sil function '$sSi22_builtinIntegerLiteralSiBI_tcfC'
    
    // LYKClass.age.getter
    sil hidden [transparent] @$s4main8LYKClassC3ageSivg : $@convention(method) (@guaranteed LYKClass) -> Int {
    // %0 "self"                                      // users: %2, %1
    bb0(%0 : $LYKClass):
      debug_value %0 : $LYKClass, let, name "self", argno 1 // id: %1
      %2 = ref_element_addr %0 : $LYKClass, #LYKClass.age // user: %3
      %3 = begin_access [read] [dynamic] %2 : $*Int   // users: %4, %5
      %4 = load %3 : $*Int                            // user: %6
      end_access %3 : $*Int                           // id: %5
      return %4 : $Int                                // id: %6
    } // end sil function '$s4main8LYKClassC3ageSivg'
    
    // LYKClass.age.setter
    sil hidden [transparent] @$s4main8LYKClassC3ageSivs : $@convention(method) (Int, @guaranteed LYKClass) -> () {
    // %0 "value"                                     // users: %6, %2
    // %1 "self"                                      // users: %4, %3
    bb0(%0 : $Int, %1 : $LYKClass):
      debug_value %0 : $Int, let, name "value", argno 1 // id: %2
      debug_value %1 : $LYKClass, let, name "self", argno 2 // id: %3
      %4 = ref_element_addr %1 : $LYKClass, #LYKClass.age // user: %5
      %5 = begin_access [modify] [dynamic] %4 : $*Int // users: %6, %7
      store %0 to %5 : $*Int                          // id: %6
      end_access %5 : $*Int                           // id: %7
      %8 = tuple ()                                   // user: %9
      return %8 : $()                                 // id: %9
    } // end sil function '$s4main8LYKClassC3ageSivs'
    
    // LYKClass.age.modify
    sil hidden [transparent] @$s4main8LYKClassC3ageSivM : $@yield_once @convention(method) (@guaranteed LYKClass) -> @yields @inout Int {
    // %0 "self"                                      // users: %2, %1
    bb0(%0 : $LYKClass):
      debug_value %0 : $LYKClass, let, name "self", argno 1 // id: %1
      %2 = ref_element_addr %0 : $LYKClass, #LYKClass.age // user: %3
      %3 = begin_access [modify] [dynamic] %2 : $*Int // users: %5, %8, %4
      yield %3 : $*Int, resume bb1, unwind bb2        // id: %4
    
    bb1:                                              // Preds: bb0
      end_access %3 : $*Int                           // id: %5
      %6 = tuple ()                                   // user: %7
      return %6 : $()                                 // id: %7
    
    bb2:                                              // Preds: bb0
      end_access %3 : $*Int                           // id: %8
      unwind                                          // id: %9
    } // end sil function '$s4main8LYKClassC3ageSivM'
    
    // variable initialization expression of LYKClass.name
    sil hidden [transparent] @$s4main8LYKClassC4nameSSvpfi : $@convention(thin) () -> @owned String {
    bb0:
      %0 = string_literal utf8 "water"                // user: %5
      %1 = integer_literal $Builtin.Word, 5           // user: %5
      %2 = integer_literal $Builtin.Int1, -1          // user: %5
      %3 = metatype $@thin String.Type                // user: %5
      // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
      %4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %5
      %5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %6
      return %5 : $String                             // id: %6
    } // end sil function '$s4main8LYKClassC4nameSSvpfi'
    
    // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
    sil [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
    
    // LYKClass.name.getter
    sil hidden [transparent] @$s4main8LYKClassC4nameSSvg : $@convention(method) (@guaranteed LYKClass) -> @owned String {
    // %0 "self"                                      // users: %2, %1
    bb0(%0 : $LYKClass):
      debug_value %0 : $LYKClass, let, name "self", argno 1 // id: %1
      %2 = ref_element_addr %0 : $LYKClass, #LYKClass.name // user: %3
      %3 = begin_access [read] [dynamic] %2 : $*String // users: %4, %6
      %4 = load %3 : $*String                         // users: %7, %5
      retain_value %4 : $String                       // id: %5
      end_access %3 : $*String                        // id: %6
      return %4 : $String                             // id: %7
    } // end sil function '$s4main8LYKClassC4nameSSvg'
    
    // LYKClass.name.setter
    sil hidden [transparent] @$s4main8LYKClassC4nameSSvs : $@convention(method) (@owned String, @guaranteed LYKClass) -> () {
    // %0 "value"                                     // users: %11, %8, %4, %2
    // %1 "self"                                      // users: %5, %3
    bb0(%0 : $String, %1 : $LYKClass):
      debug_value %0 : $String, let, name "value", argno 1 // id: %2
      debug_value %1 : $LYKClass, let, name "self", argno 2 // id: %3
      retain_value %0 : $String                       // id: %4
      %5 = ref_element_addr %1 : $LYKClass, #LYKClass.name // user: %6
      %6 = begin_access [modify] [dynamic] %5 : $*String // users: %8, %7, %10
      %7 = load %6 : $*String                         // user: %9
      store %0 to %6 : $*String                       // id: %8
      release_value %7 : $String                      // id: %9
      end_access %6 : $*String                        // id: %10
      release_value %0 : $String                      // id: %11
      %12 = tuple ()                                  // user: %13
      return %12 : $()                                // id: %13
    } // end sil function '$s4main8LYKClassC4nameSSvs'
    
    // LYKClass.name.modify
    sil hidden [transparent] @$s4main8LYKClassC4nameSSvM : $@yield_once @convention(method) (@guaranteed LYKClass) -> @yields @inout String {
    // %0 "self"                                      // users: %2, %1
    bb0(%0 : $LYKClass):
      debug_value %0 : $LYKClass, let, name "self", argno 1 // id: %1
      %2 = ref_element_addr %0 : $LYKClass, #LYKClass.name // user: %3
      %3 = begin_access [modify] [dynamic] %2 : $*String // users: %5, %8, %4
      yield %3 : $*String, resume bb1, unwind bb2     // id: %4
    
    bb1:                                              // Preds: bb0
      end_access %3 : $*String                        // id: %5
      %6 = tuple ()                                   // user: %7
      return %6 : $()                                 // id: %7
    
    bb2:                                              // Preds: bb0
      end_access %3 : $*String                        // id: %8
      unwind                                          // id: %9
    } // end sil function '$s4main8LYKClassC4nameSSvM'
    
    // LYKClass.deinit
    sil hidden @$s4main8LYKClassCfd : $@convention(method) (@guaranteed LYKClass) -> @owned Builtin.NativeObject {
    // %0 "self"                                      // users: %6, %2, %1
    bb0(%0 : $LYKClass):
      debug_value %0 : $LYKClass, let, name "self", argno 1 // id: %1
      %2 = ref_element_addr %0 : $LYKClass, #LYKClass.name // user: %3
      %3 = begin_access [deinit] [static] %2 : $*String // users: %5, %4
      destroy_addr %3 : $*String                      // id: %4
      end_access %3 : $*String                        // id: %5
      %6 = unchecked_ref_cast %0 : $LYKClass to $Builtin.NativeObject // user: %7
      return %6 : $Builtin.NativeObject               // id: %7
    } // end sil function '$s4main8LYKClassCfd'
    
    // LYKClass.__deallocating_deinit
    sil hidden @$s4main8LYKClassCfD : $@convention(method) (@owned LYKClass) -> () {
    // %0 "self"                                      // users: %3, %1
    bb0(%0 : $LYKClass):
      debug_value %0 : $LYKClass, let, name "self", argno 1 // id: %1
      // function_ref LYKClass.deinit
      %2 = function_ref @$s4main8LYKClassCfd : $@convention(method) (@guaranteed LYKClass) -> @owned Builtin.NativeObject // user: %3
      %3 = apply %2(%0) : $@convention(method) (@guaranteed LYKClass) -> @owned Builtin.NativeObject // user: %4
      %4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $LYKClass // user: %5
      dealloc_ref %4 : $LYKClass                      // id: %5
      %6 = tuple ()                                   // user: %7
      return %6 : $()                                 // id: %7
    } // end sil function '$s4main8LYKClassCfD'
    
    // LYKClass.__allocating_init()
    sil hidden [exact_self_class] @$s4main8LYKClassCACycfC : $@convention(method) (@thick LYKClass.Type) -> @owned LYKClass {
    // %0 "$metatype"
    bb0(%0 : $@thick LYKClass.Type):
      %1 = alloc_ref $LYKClass                        // user: %3
      // function_ref LYKClass.init()
      %2 = function_ref @$s4main8LYKClassCACycfc : $@convention(method) (@owned LYKClass) -> @owned LYKClass // user: %3
      %3 = apply %2(%1) : $@convention(method) (@owned LYKClass) -> @owned LYKClass // user: %4
      return %3 : $LYKClass                           // id: %4
    } // end sil function '$s4main8LYKClassCACycfC'
    
    // LYKClass.init()
    sil hidden @$s4main8LYKClassCACycfc : $@convention(method) (@owned LYKClass) -> @owned LYKClass {
    // %0 "self"                                      // users: %6, %2, %14, %1
    bb0(%0 : $LYKClass):
      debug_value %0 : $LYKClass, let, name "self", argno 1 // id: %1
      %2 = ref_element_addr %0 : $LYKClass, #LYKClass.age // user: %5
      %3 = integer_literal $Builtin.Int64, 10         // user: %4
      %4 = struct $Int (%3 : $Builtin.Int64)          // user: %5
      store %4 to %2 : $*Int                          // id: %5
      %6 = ref_element_addr %0 : $LYKClass, #LYKClass.name // user: %13
      %7 = string_literal utf8 "water"                // user: %12
      %8 = integer_literal $Builtin.Word, 5           // user: %12
      %9 = integer_literal $Builtin.Int1, -1          // user: %12
      %10 = metatype $@thin String.Type               // user: %12
      // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
      %11 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %12
      %12 = apply %11(%7, %8, %9, %10) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13
      store %12 to %6 : $*String                      // id: %13
      return %0 : $LYKClass                           // id: %14
    } // end sil function '$s4main8LYKClassCACycfc'
    
    sil_vtable LYKClass {
      #LYKClass.age!getter: (LYKClass) -> () -> Int : @$s4main8LYKClassC3ageSivg    // LYKClass.age.getter
      #LYKClass.age!setter: (LYKClass) -> (Int) -> () : @$s4main8LYKClassC3ageSivs  // LYKClass.age.setter
      #LYKClass.age!modify: (LYKClass) -> () -> () : @$s4main8LYKClassC3ageSivM // LYKClass.age.modify
      #LYKClass.name!getter: (LYKClass) -> () -> String : @$s4main8LYKClassC4nameSSvg   // LYKClass.name.getter
      #LYKClass.name!setter: (LYKClass) -> (String) -> () : @$s4main8LYKClassC4nameSSvs // LYKClass.name.setter
      #LYKClass.name!modify: (LYKClass) -> () -> () : @$s4main8LYKClassC4nameSSvM   // LYKClass.name.modify
      #LYKClass.init!allocator: (LYKClass.Type) -> () -> LYKClass : @$s4main8LYKClassCACycfC    // LYKClass.__allocating_init()
      #LYKClass.deinit!deallocator: @$s4main8LYKClassCfD    // LYKClass.__deallocating_deinit
    }
    
    
    
    // Mappings from '#fileID' to '#filePath':
    //   'main/main.swift' => 'main.swift'
    

    开始分析

    class LYKClass {
        var age: Int = 10
        var name: String = "water"
    }
    /*
     class LYKClass {
       @_hasStorage @_hasInitialValue var age: Int { get set }
       @_hasStorage @_hasInitialValue var name: String { get set }
       @objc deinit
       init()
     }
     */
    
    
    let lykCls = LYKClass()
    /*
    @_hasStorage @_hasInitialValue let lykCls: LYKClass { get }
     */
    
    
    // lykCls -> 创建了一个全局的类LYKClass
    //sil_global hidden [let] @$s4main6lykClsAA8LYKClassCvp : $LYKClass
    

    看不懂s4main6lykClsAA8LYKClassCvp这个是什么,可以使用符号重组命令xcrun swift-demangle s4main6lykClsAA8LYKClassCvp,可以看出来s4main6lykClsAA8LYKClassCvp就是LYKClass这个类

    图片.png

    这是main函数
    0% 1% ... 9%等都是虚拟的寄存器

    // main
    sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
    bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
      alloc_global @$s4main6lykClsAA8LYKClassCvp      // id: %2    -> 创建了一个全局的LYKClass对象
      %3 = global_addr @$s4main6lykClsAA8LYKClassCvp : $*LYKClass // user: %7
      %4 = metatype $@thick LYKClass.Type             // user: %6
      // function_ref LYKClass.__allocating_init()
      %5 = function_ref @$s4main8LYKClassCACycfC : $@convention(method) (@thick LYKClass.Type) -> @owned LYKClass // user: %6
      %6 = apply %5(%4) : $@convention(method) (@thick LYKClass.Type) -> @owned LYKClass // user: %7
      store %6 to %3 : $*LYKClass                     // id: %7
      %8 = integer_literal $Builtin.Int32, 0          // user: %9
      %9 = struct $Int32 (%8 : $Builtin.Int32)        // user: %10
      return %9 : $Int32                              // id: %10
    } // end sil function 'main'
    

    相关文章

      网友评论

          本文标题:swift基础_编译和调试

          本文链接:https://www.haomeiwen.com/subject/iypwkrtx.html