仅在条件编译块中设置,编译器是否从发布版本中完全删除语句?

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

例如:

struct L {
    #if DEBUG
    static let og:((String) -> Void)? = { print($0) }
    #else
    static let og:((String) -> Void)? = nil
    #endif
}
L.og?("Howdy!")
print("Done.")

在此代码的发布版本中,Swift编译器对L.og?("Howdy!")行做了什么?它会完全优化生产线吗?还是在运行时将表达式L.og评估为nil?我如何证明任一答案?

我为自己回答这个问题所做的事情

我制作了一个小程序,只包含您上面看到的代码,并使用debugrelease配置对它进行了构建。然后,我用swift build -c分解了两个二进制文件。正如预期的那样,在调试程序集中,我可以看到“ Howdy”消息。但是,我对程序集和macOS体系结构了解不足,不足以证明发行程序集中不存在“ Howdy”。

接下来,我将objdump代码放入一个更大的iOS项目中,将方案Run操作Build Configuration设置设置为'Release',在L.og行上设置一个断点,启动了应用程序,并在遇到断点时,我按了Xcode Debug导航器中的“ Step into”按钮,以进入L.og行,并且正如预期的那样,Xcode / lldb调试器没有进入L.og,但确实如此无法证明二进制文件的内容。

L.og不讨论此技术细节。

说明

假定一个典型的构建环境,其中仅在Swift docs on "Optional Chaining"配置上设置编译器标志-DDEBUG,而在debug配置上设置not

swift build lldb
2个回答
0
投票

使用条件编译,编译器将在构建时评估标志的状态。

release块内评估为true的代码被编译,并且在#if块内评估为false的代码被忽略。 (它将被剥离,并且不会出现在二进制文件中。)对于您而言,对于发行版,就好像您的代码是:

#if

因此,struct L { static let og:((String) -> Void)? = nil } L.og?("Howdy!") print("Done.") 中的“可选链接”会将L.og?("Howdy!")评估为nil,并且该代码将永远不会做任何事情。

我不知道您问题的最后一部分的答案,因为编译器永远无法做任何事情,因此编译器是否完全优化了这一行。生成Swift代码的LLVM编译器非常聪明,在发布模式下,它很可能会将代码完全剥离掉,但是我不确定。您必须确保查看程序集输出。


0
投票

我正在阅读L.og,并且我认为这有助于我找到问题的答案。我不知道如何从命令行快速编译中执行此操作,因此我在Xcode中使用最小的iOS项目完成了此操作。

我编辑了方案运行操作,内部配置设置为“发布”。我保留了[调试可执行程序]的复选框,以便Xcode可以将源代码与程序集相关联。我已验证这实际上是通过优化构建项目的。这是来自Xcode Report导航器的(截断的)build命令,它与修改后的方案的构建相对应。注意中间的this answer

-O

这里是AppDelgate中的测试代码。

CompileSwift normal x86_64 (in target: Beyond) cd /Users/ftal/Code/Beyond /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -c /Users/ftal/Code/Beyond/Beyond/ViewController.swift /Users/ftal/Code/Beyond/Beyond/AppDelegate.swift /Users/ftal/Code/Beyond/Beyond/Log.swift -emit-module-path /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Objects-normal-tsan/x86_64/Beyond.swiftmodule -emit-module-doc-path /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Objects-normal-tsan/x86_64/Beyond.swiftdoc -serialize-diagnostics-path /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Objects-normal-tsan/x86_64/Beyond-master.dia -emit-objc-header-path /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Objects-normal-tsan/x86_64/Beyond-Swift.h -emit-dependencies-path /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Objects-normal-tsan/x86_64/Beyond-master.d -target x86_64-apple-ios12.2-simulator -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.4.sdk -I /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Products/Release-iphonesimulator -F /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Products/Release-iphonesimulator -g -module-cache-path /Users/ftal/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -sanitize=thread -swift-version 5 -enforce-exclusivity=checked -O -serialize-debugging-options -Xcc -working-directory -Xcc /Users/ftal/Code/Beyond -enable-anonymous-context-mangled-names -Xcc -I/Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/swift-overrides.hmap -Xcc -iquote -Xcc /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Beyond-generated-files.hmap -Xcc -I/Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Beyond-own-target-headers.hmap -Xcc -I/Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Beyond-all-target-headers.hmap -Xcc -iquote -Xcc /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Beyond-project-headers.hmap -Xcc -I/Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Products/Release-iphonesimulator/include -Xcc -I/Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/DerivedSources-normal/x86_64 -Xcc -I/Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/DerivedSources/x86_64 -Xcc -I/Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/DerivedSources -module-name Beyond -num-threads 12 -o /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Objects-normal-tsan/x86_64/ViewController.o -o /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Objects-normal-tsan/x86_64/AppDelegate.o -o /Users/ftal/Library/Developer/Xcode/DerivedData/Beyond-hfvhdaxgxprsdyasgilratcpkqze/Build/Intermediates.noindex/Beyond.build/Release-iphonesimulator/Beyond.build/Objects-normal-tsan/x86_64/Log.o

我在func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    print("Before")
    L.og?("Howdy!")
    print("After")
    return true
}
处设置了一个断点。我运行了这个项目。遇到断点时,我在return true提示符下输入了dis -f -m

lldb

我很确定我在Before
After
Beyond was compiled with optimization - stepping may behave oddly; variables may not be available.
(lldb) dis -f -m

** 15       func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

Beyond`specialized AppDelegate.application(_:didFinishLaunchingWithOptions:):
    0x103b2aba0 <+0>:   pushq  %rbp
    0x103b2aba1 <+1>:   movq   %rsp, %rbp
    0x103b2aba4 <+4>:   pushq  %r15
    0x103b2aba6 <+6>:   pushq  %r14
    0x103b2aba8 <+8>:   pushq  %r13
    0x103b2abaa <+10>:  pushq  %r12
    0x103b2abac <+12>:  pushq  %rbx
    0x103b2abad <+13>:  pushq  %rax


    0x103b2abae <+14>:  movq   0x8(%rbp), %rdi
    0x103b2abb2 <+18>:  callq  0x103b2af38               ; symbol stub for: __tsan_func_entry
    0x103b2abb7 <+23>:  movq   0x251a(%rip), %rcx        ; (void *)0x0000000105fa0b68: type metadata for Any
    0x103b2abbe <+30>:  addq   $0x8, %rcx
    0x103b2abc2 <+34>:  leaq   0x37c7(%rip), %rsi        ; lazy cache variable for type metadata for Swift._ContiguousArrayStorage<Any>
    0x103b2abc9 <+41>:  movq   0x24f0(%rip), %r8         ; (void *)0x0000000105e64e70: type metadata accessor for Swift._ContiguousArrayStorage
    0x103b2abd0 <+48>:  xorl   %edi, %edi
    0x103b2abd2 <+50>:  movq   %rsi, %rdx
    0x103b2abd5 <+53>:  callq  0x103b2adc0               ; merged type metadata accessor for __C.UIApplicationLaunchOptionsKey
    0x103b2abda <+58>:  movq   %rax, %r14
    0x103b2abdd <+61>:  movl   $0x40, %esi
    0x103b2abe2 <+66>:  movl   $0x7, %edx
    0x103b2abe7 <+71>:  movq   %rax, %rdi
    0x103b2abea <+74>:  callq  0x103b2af92               ; symbol stub for: swift_allocObject
    0x103b2abef <+79>:  movq   %rax, %rbx
    0x103b2abf2 <+82>:  leaq   0x10(%rax), %rdi
    0x103b2abf6 <+86>:  callq  0x103b2af5c               ; symbol stub for: __tsan_write16
    0x103b2abfb <+91>:  movaps 0x1dbe(%rip), %xmm0       ; __swift_reflection_version + 16
    0x103b2ac02 <+98>:  movups %xmm0, 0x10(%rbx)
    0x103b2ac06 <+102>: leaq   0x20(%rbx), %r15

** 16           print("Before")

    0x103b2ac0a <+106>: leaq   0x38(%rbx), %rdi
    0x103b2ac0e <+110>: callq  0x103b2af62               ; symbol stub for: __tsan_write8
    0x103b2ac13 <+115>: movq   0x243e(%rip), %r12        ; (void *)0x0000000105f99190: type metadata for Swift.String
    0x103b2ac1a <+122>: movq   %r12, 0x38(%rbx)
    0x103b2ac1e <+126>: movq   %r15, %rdi
    0x103b2ac21 <+129>: callq  0x103b2af62               ; symbol stub for: __tsan_write8
    0x103b2ac26 <+134>: movabsq $0x65726f666542, %rax     ; imm = 0x65726F666542 
    0x103b2ac30 <+144>: movq   %rax, 0x20(%rbx)
    0x103b2ac34 <+148>: leaq   0x28(%rbx), %rdi
    0x103b2ac38 <+152>: callq  0x103b2af62               ; symbol stub for: __tsan_write8
    0x103b2ac3d <+157>: movabsq $-0x1a00000000000000, %rax ; imm = 0xE600000000000000 
    0x103b2ac47 <+167>: movq   %rax, 0x28(%rbx)
    0x103b2ac4b <+171>: movabsq $-0x1f00000000000000, %rdx ; imm = 0xE100000000000000 
    0x103b2ac55 <+181>: movl   $0x20, %esi
    0x103b2ac5a <+186>: movl   $0xa, %ecx
    0x103b2ac5f <+191>: movq   %rbx, %rdi
    0x103b2ac62 <+194>: movq   %rdx, %r8
    0x103b2ac65 <+197>: callq  0x103b2af08               ; symbol stub for: Swift.print(_: Any..., separator: Swift.String, terminator: Swift.String) -> ()


    0x103b2ac6a <+202>: movq   %rbx, %rdi
    0x103b2ac6d <+205>: callq  0x103b2afbc               ; symbol stub for: swift_release

   11       static let og:((String) -> Void)? = { print($0) }
   12       #else
** 13       static let og:((String) -> Void)? = nil
   14       #endif
   15   }

    0x103b2ac72 <+210>: leaq   0x3677(%rip), %rdi        ; globalinit_33_3570E65C86025A8C4F03B9A75B67FFAA_token0
    0x103b2ac79 <+217>: callq  0x103b2af56               ; symbol stub for: __tsan_read8
    0x103b2ac7e <+222>: cmpq   $-0x1, 0x366a(%rip)       ; (void *)0x0000000000000200
    0x103b2ac86 <+230>: je     0x103b2aca7               ; <+263> at AppDelegate.swift:17:11
    0x103b2ac88 <+232>: leaq   0x3661(%rip), %rdi        ; globalinit_33_3570E65C86025A8C4F03B9A75B67FFAA_token0
    0x103b2ac8f <+239>: leaq   0x1fa(%rip), %rsi         ; globalinit_33_3570E65C86025A8C4F03B9A75B67FFAA_func0 at Log.swift
    0x103b2ac96 <+246>: callq  0x103b2afb6               ; symbol stub for: swift_once
    0x103b2ac9b <+251>: leaq   0x364e(%rip), %rdi        ; globalinit_33_3570E65C86025A8C4F03B9A75B67FFAA_token0
    0x103b2aca2 <+258>: callq  0x103b2af56               ; symbol stub for: __tsan_read8

** 17           L.og?("Howdy!")

    0x103b2aca7 <+263>: leaq   0x39f2(%rip), %rdi        ; static Beyond.L.og : Swift.Optional<(Swift.String) -> ()>
    0x103b2acae <+270>: callq  0x103b2af56               ; symbol stub for: __tsan_read8
    0x103b2acb3 <+275>: movq   0x39e6(%rip), %rbx        ; static Beyond.L.og : Swift.Optional<(Swift.String) -> ()>
    0x103b2acba <+282>: leaq   0x39e7(%rip), %rdi        ; static Beyond.L.og : Swift.Optional<(Swift.String) -> ()> + 8
    0x103b2acc1 <+289>: callq  0x103b2af56               ; symbol stub for: __tsan_read8
    0x103b2acc6 <+294>: testq  %rbx, %rbx
    0x103b2acc9 <+297>: je     0x103b2acfe               ; <+350> [inlined] generic specialization <Any> of Swift._allocateUninitializedArray<A>(Builtin.Word) -> (Swift.Array<A>, Builtin.RawPointer) at AppDelegate.swift:18

   1    //
   1    //
   2    //  AppDelegate.swift

    0x103b2accb <+299>: movq   0x39d6(%rip), %r15        ; static Beyond.L.og : Swift.Optional<(Swift.String) -> ()> + 8
    0x103b2acd2 <+306>: movq   %r15, %rdi
    0x103b2acd5 <+309>: callq  0x103b2afc2               ; symbol stub for: swift_retain
    0x103b2acda <+314>: movabsq $0x217964776f48, %rdi     ; imm = 0x217964776F48 
    0x103b2ace4 <+324>: movabsq $-0x1a00000000000000, %rsi ; imm = 0xE600000000000000 

** 17           L.og?("Howdy!")

    0x103b2acee <+334>: movq   %r15, %r13
    0x103b2acf1 <+337>: callq  *%rbx


    0x103b2acf3 <+339>: movq   %rbx, %rdi
    0x103b2acf6 <+342>: movq   %r15, %rsi
    0x103b2acf9 <+345>: callq  0x103b2ae50               ; outlined consume of Swift.Optional<@escaping @callee_guaranteed (@guaranteed Swift.String) -> ()>
    0x103b2acfe <+350>: movl   $0x40, %esi
    0x103b2ad03 <+355>: movl   $0x7, %edx
    0x103b2ad08 <+360>: movq   %r14, %rdi
    0x103b2ad0b <+363>: callq  0x103b2af92               ; symbol stub for: swift_allocObject
    0x103b2ad10 <+368>: movq   %rax, %rbx
    0x103b2ad13 <+371>: leaq   0x10(%rax), %rdi
    0x103b2ad17 <+375>: callq  0x103b2af5c               ; symbol stub for: __tsan_write16
    0x103b2ad1c <+380>: movaps 0x1c9d(%rip), %xmm0       ; __swift_reflection_version + 16
    0x103b2ad23 <+387>: movups %xmm0, 0x10(%rbx)
    0x103b2ad27 <+391>: leaq   0x20(%rbx), %r14

** 18           print("After")

    0x103b2ad2b <+395>: leaq   0x38(%rbx), %rdi
    0x103b2ad2f <+399>: callq  0x103b2af62               ; symbol stub for: __tsan_write8
    0x103b2ad34 <+404>: movq   %r12, 0x38(%rbx)
    0x103b2ad38 <+408>: movq   %r14, %rdi
    0x103b2ad3b <+411>: callq  0x103b2af62               ; symbol stub for: __tsan_write8
    0x103b2ad40 <+416>: movabsq $0x7265746641, %rax       ; imm = 0x7265746641 
    0x103b2ad4a <+426>: movq   %rax, 0x20(%rbx)
    0x103b2ad4e <+430>: leaq   0x28(%rbx), %rdi
    0x103b2ad52 <+434>: callq  0x103b2af62               ; symbol stub for: __tsan_write8
    0x103b2ad57 <+439>: movabsq $-0x1b00000000000000, %rax ; imm = 0xE500000000000000 
    0x103b2ad61 <+449>: movq   %rax, 0x28(%rbx)
    0x103b2ad65 <+453>: movabsq $-0x1f00000000000000, %rdx ; imm = 0xE100000000000000 
    0x103b2ad6f <+463>: movl   $0x20, %esi
    0x103b2ad74 <+468>: movl   $0xa, %ecx
    0x103b2ad79 <+473>: movq   %rbx, %rdi
    0x103b2ad7c <+476>: movq   %rdx, %r8
    0x103b2ad7f <+479>: callq  0x103b2af08               ; symbol stub for: Swift.print(_: Any..., separator: Swift.String, terminator: Swift.String) -> ()


    0x103b2ad84 <+484>: movq   %rbx, %rdi
    0x103b2ad87 <+487>: callq  0x103b2afbc               ; symbol stub for: swift_release

-> 19           return true
-> 20       }
-> 21   }

->  0x103b2ad8c <+492>: callq  0x103b2af3e               ; symbol stub for: __tsan_func_exit
    0x103b2ad91 <+497>: movb   $0x1, %al
    0x103b2ad93 <+499>: addq   $0x8, %rsp
    0x103b2ad97 <+503>: popq   %rbx
    0x103b2ad98 <+504>: popq   %r12
    0x103b2ad9a <+506>: popq   %r13
    0x103b2ad9c <+508>: popq   %r14
    0x103b2ad9e <+510>: popq   %r15
    0x103b2ada0 <+512>: popq   %rbp
    0x103b2ada1 <+513>: retq   

   1    //

    0x103b2ada2 <+514>: movq   %rax, %rbx
    0x103b2ada5 <+517>: callq  0x103b2af3e               ; symbol stub for: __tsan_func_exit
    0x103b2adaa <+522>: movq   %rbx, %rdi
    0x103b2adad <+525>: callq  0x103b2af26               ; symbol stub for: _Unwind_Resume
    0x103b2adb2 <+530>: ud2    
    0x103b2adb4 <+532>: nopw   %cs:(%rax,%rax)
    0x103b2adbe <+542>: nop    
(lldb) 
** 13两行中看到的输出都表明,即使由于条件编译块而导致该可选项始终为** 17时,编译器也无法优化该可选项。 
© www.soinside.com 2019 - 2024. All rights reserved.