Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Growing LINE for iOS

Growing LINE for iOS

Christopher Rogers
LINE App Dev Team4 Senior Software Engineer
https://linedevday.linecorp.com/jp/2019/sessions/C2-3

LINE DevDay 2019

November 21, 2019
Tweet

More Decks by LINE DevDay 2019

Other Decks in Technology

Transcript

  1. 2019 DevDay Growing LINE for iOS > Christopher Rogers >

    LINE App Dev Team4 Senior Software Engineer
  2. Lines of Code 400,000 800,000 1,200,000 1,600,000 1.0.0 1.2.0 1.3.0

    1.3.4 1.6.1 2.0.2 2.3.1 3.1.0 3.2.1 3.5.0 3.6.5 3.8.2 3.9.3 4.0.1 4.3.1 4.5.0 4.7.1 4.9.1 5.0.2 5.2.1 5.4.0 5.8.0 5.10.0 6.1.1 6.4.0 6.6.1 6.8.5 6.9.2 7.1.2 7.3.0 7.5.0 7.8.0 7.12.0 7.15.0 8.0.0 8.2.1 8.4.1 8.6.0 8.9.0 8.12.1 8.16.1 8.19.0 9.0.2 9.5.0 9.7.1 9.15.1 9.18.0 Objective C Swift
  3. Agenda > Dependencies > Launch Time > Bridging Objective-C &

    Swift > Xcode Project Size > Build Times
  4. Ƃ Carthage > Pre-builds frameworks > No integration with Xcode

    > Little to no configuration > Two dependency managers…
  5. Hard Problems in Computer Science Caching With Carthage > Remote

    build artifact caching with Rome > Cache poisoning > Local caches often broke
  6. Dynamic Frameworks > Solution: make them static frameworks! > Downsides

    to static frameworks • Cannot bundle resources • Code reuse between executables results in increased binary size > Dynamic linking (usually) happens on launch
  7. Ƃ How To Create > Create dynamic framework > Mach-O

    type: Static Library > Do not embed > Resources
  8. Ƃ Mixing It Up > Public headers become part of

    module alongside Swift > Enable Clang modules if needed • CLANG_ENABLE_MODULES • DEFINES_MODULE • PRODUCT_MODULE_NAME
  9. Ƃ Module Maps > MODULEMAP_FILE > umbrella makes directory contents

    part of module > export controls if imported modules are implicitly imported
  10. Launch Time 0 ms 2,000 ms 4,000 ms 6,000 ms

    8,000 ms 10,000 ms 8.4.0 8.5.0 20%ile 50%ile mean 80%ile
  11. Bridging Objective-C Categories on Swift Types To Swift > Circular

    dependency • Generated header (MyApp-Swift.h) • Bridging header (MyApp-Bridging-Header.h) Problematic Code
  12. > @objc(MyObjCSwiftClass) class MySwiftClass { } > @class MyObjCSwiftClass; can

    fail to bridge back to MySwiftClass (rare) > My fix (#27682) should land in Swift 5.2 Bridging Swift Classes Back To Swift via Objective-C Bridging Objective-C Categories on Swift Types To Swift > Circular dependency • Generated header (MyApp-Swift.h) • Bridging header (MyApp-Bridging-Header.h) Problematic Code
  13. MyObjCSwiftClass+CategoryName.h Importing in Header // import generated header, which contains

    MyObjCSwiftClass #import "LINE-Swift.h" @interface MyObjCSwiftClass (CategoryName)
  14. MyObjCSwiftClass+CategoryName.h Importing in Header #ifdef __swift__ @import LINE; #else //

    import generated header, which contains MyObjCSwiftClass #import "LINE-Swift.h" #endif @interface MyObjCSwiftClass (CategoryName)
  15. > Was this a part of the target template? >

    Why was this setting needed? Understanding What Has Been Configured Merge Conflicts > Requires understanding Xcode’s project file format Xcode Project Size
  16. > Was this a part of the target template? >

    Why was this setting needed? Understanding What Has Been Configured Slow > Modifying anything was painfully slow Merge Conflicts > Requires understanding Xcode’s project file format Xcode Project Size
  17. Ƃ XcodeGen > YAML config file > Can write comments

    > Less conflicts > 88k lines of Xcode configuration are now ~1,200 lines of YAML. > Can’t use Xcode to edit project
  18. > Xcode sometimes decides to rebuild everything > Incremental builds

    in Swift sometimes too coarse grained Tooling Problems CocoaPods > Unnecessarily rebuilt after cleaning Generated Header (LINE-Swift.h) > Nearly a clean build when modified Problem Areas
  19. Precompiling Generated Header > Mileage may vary > Usually not

    necessary nor recommended Quick Improvements
  20. > Extended type gets marked dirty when extension modified >

    Files marked dirty will propagate dirty flag to all of its extensions > OTHER_SWIFT_FLAGS = -driver-show-incremental Limiting Access to Swift Extensions Precompiling Generated Header > Mileage may vary > Usually not necessary nor recommended Quick Improvements
  21. And Incremental Compilation Swift Extensions class MyClass { func foo()

    { IndexSet().bar() } } extension IndexSet { func bar() {} }
  22. And Incremental Compilation Swift Extensions class MyClass { func foo()

    { IndexSet().bar() } } extension IndexSet { fileprivate func bar() {} }
  23. And Incremental Compilation Swift Extensions class MyClass { func foo()

    { IndexSet().bar() } } extension IndexSet { func bar() {} }
  24. > Including dependencies managed by CocoaPods & Carthage Build &

    Cache Modules With Bazel Split Up Codebase Into Modules > Currently 224 modules > Categorize modules Long-Term Approach
  25. > Specific category for extension-safe modules Code Size for App

    Extensions Understanding Dependency Graph > What is OK to import? > Where to put new code? Module Categories
  26. > Restriction: Cannot import feature-private modules > Small, focused >

    Includes feature-public modules Others Module Naming Convention > Module categories have set prefixes and/or suffixes Feature-Private (Feature) > Restriction: Cannot import other features’ private modules > Example features: Messaging, Timeline, Calls, Pay Module Categories
  27. > Reading Package.swift for build settings Build Code From SwiftPM

    in Bazel Replace CocoaPods & Carthage With SwiftPM for Dependency Resolution > Using swift package resolve Building With Bazel
  28. Replace CocoaPods & Carthage With SwiftPM for Dependency Resolution >

    Done, but removed SwiftPM due to reliability issues (mostly with CI builds) (SR-10718) > Now Bazel is downloading hard-coded dependencies Current Status
  29. > Manually created Bazel BUILD files for all dependencies Build

    Code From SwiftPM in Bazel Replace CocoaPods & Carthage With SwiftPM for Dependency Resolution > Done, but removed SwiftPM due to reliability issues (mostly with CI builds) (SR-10718) > Now Bazel is downloading hard-coded dependencies Current Status
  30. > Manually created Bazel BUILD files for all dependencies Build

    Code From SwiftPM in Bazel Bonus: Move Code Generation to Bazel > Mostly done > No longer have to codegen unnecessarily Replace CocoaPods & Carthage With SwiftPM for Dependency Resolution > Done, but removed SwiftPM due to reliability issues (mostly with CI builds) (SR-10718) > Now Bazel is downloading hard-coded dependencies Current Status
  31. Improve Developer Experience > Code viewer & breakpoints working in

    Xcode with Tulsi > Code completion is not complete > Making modifications to code built by Bazel not great Remaining Issues
  32. > Split up codebase into more modules > Needed for

    true gains in incremental build times Build More in Bazel Improve Developer Experience > Code viewer & breakpoints working in Xcode with Tulsi > Code completion is not complete > Making modifications to code built by Bazel not great Remaining Issues
  33. > Split up codebase into more modules > Needed for

    true gains in incremental build times Build More in Bazel Cache Reusability > Some differences between machines prevent build cache reuse > Mostly resolved Improve Developer Experience > Code viewer & breakpoints working in Xcode with Tulsi > Code completion is not complete > Making modifications to code built by Bazel not great Remaining Issues