Slide 1

Slide 1 text

Standardizing build system using modern Swift Packages in LINE 2022-11-10 Mobile DevOps Summit 2022 Kohki Miki (@giginet) LINE Corp

Slide 2

Slide 2 text

Self Introduction β€’ Kohki Miki πŸ‡―πŸ‡΅ (@giginet) β€’ Senior iOS Engineer @ LINE Corp (2022/7~) β€’ Developer Experience team β€’ OSS Maintainer : fastlane / Carthage / XcodeGen, etc…

Slide 3

Slide 3 text

Agenda β€’ Our current build system and its issues β€’ Introduce my new SwiftPM-based build tool β€’ Handling Swift Packages as cachable and reusable.

Slide 4

Slide 4 text

State of LINE β€’ LINE β€’ A communication app used by 200 million users β€’ 2,000,000+ lines of Swift Code (iOS)

Slide 5

Slide 5 text

Build Phases of LINE Prebuilt Tasks Building Application Bazel Xcode

Slide 6

Slide 6 text

Prebuilt Frameworks β€’ Regular Swift, Obj-C OSS libraries β€’ C/C++ libraries (e.g. Image processing, encryption) β€’ Binary Frameworks β€’ Separated Features β€’ Code generation from API Schemes Prebuilt Tasks Bazel

Slide 7

Slide 7 text

Prebuilt Frameworks β€’ Regular Swift, Obj-C OSS libraries β€’ C/C++ libraries (e.g. Image processing, encryption) β€’ Binary Frameworks β€’ Separated Features β€’ Code generation from API Schemes Prebuilt Tasks Bazel

Slide 8

Slide 8 text

Prebuilt Frameworks β€’ Regular Swift, Obj-C OSS libraries β€’ C/C++ libraries (e.g. Image processing, encryption) β€’ Binary Frameworks β€’ Separated Features β€’ Code generation from API Schemes Prebuilt Tasks Bazel

Slide 9

Slide 9 text

Prebuilt Frameworks β€’ Regular Swift, Obj-C OSS libraries β€’ C/C++ libraries (e.g. Image processing, encryption) β€’ Binary Frameworks β€’ Separated Features β€’ Code generation from API Schemes Prebuilt Tasks Bazel

Slide 10

Slide 10 text

Prebuilt Frameworks β€’ Regular Swift, Obj-C OSS libraries β€’ C/C++ libraries (e.g. Image processing, encryption) β€’ Binary Frameworks β€’ Separated Features β€’ Code generation from API Schemes Prebuilt Tasks Bazel

Slide 11

Slide 11 text

Build time of each steps 926.42 seconds 503.4 seconds Prebuilt Tasks Building Application Bazel Xcode

Slide 12

Slide 12 text

Problems on maintainability β€’ Tough to maintain Bazel β€’ Implementing tasks in Starlark β€’ No tests β€’ Learning cost for Bazel β€’ Large numbers of submodules β€’ No dependency resolver β€’ Abandoned dependencies Implementations of Bazel rules in Starlark

Slide 13

Slide 13 text

Problems on maintainability β€’ Tough to maintain Bazel β€’ Implementing tasks in Starlark β€’ No tests β€’ Learning cost for Bazel β€’ Large numbers of submodules β€’ No dependency resolver β€’ Abandoned dependencies Submodules hell

Slide 14

Slide 14 text

Problems on maintainability β€’ Tough to maintain Bazel β€’ Implementing tasks in Starlark β€’ No tests β€’ Learning cost for Bazel β€’ Large numbers of submodules β€’ No dependency resolver β€’ Abandoned dependencies http_archive( name = "APIKit", build_file = "//Configuration/repositories:APIKit.BUILD", sha256 = "0d19ebb5769ca464c7b10671ca1df21b8e9edad198f59e2d854c48cc580383 43", strip_prefix = "APIKit-5.0.0", url = "https://github.com/ishkawa/APIKit/archive/ 5.0.0.tar.gz", ) http_archive( name = "APNGKit", build_file = "//Configuration/repositories:APNGKit.BUILD", sha256 = "89245edaabcda2872141ecfcfad6d88fa5f0293af52a4cbcd2dd2fd6e3f931 99", strip_prefix = β€œAPNGKit-2.2.1”, url = β€œhttps://github.com/onevcat/APNGKit/archive/ 2.2.1.tar.gz”, ) Dependency de f initions on our WORKSPACE

Slide 15

Slide 15 text

Build speeds β€’Bazel used to improve build time dramatically β€’However, Apple Silicon(M1) improves build type than Bazel Need more maintainable build work f low

Slide 16

Slide 16 text

Our requirements β€’ Replacing the prebuilt task β€’ Simple. based on the standard build system β€’ Reusing build artifacts and caching well β€’ Easy to develop and testable β€’ Easy to update dependencies

Slide 17

Slide 17 text

Swift Package with Xcode β€’ Swift Package integration for Xcode is the best solution β€’ Maintained in the future β€’ Most packages are supported

Slide 18

Slide 18 text

Cache Swift Packages with Xcode Xcode stores Swift Package dependencies in Derived Data It can be purged easily!

Slide 19

Slide 19 text

How to cache Swift Packages? Using Swift Package and Swift Package Manager(SwiftPM) is a good choice However, it’s dif f icult to keep build speed by using caches I developed a new tool! Scipio

Slide 20

Slide 20 text

Scipio - An awesome build tool - https://github.com/giginet/Scipio

Slide 21

Slide 21 text

Scipio β€’ Developing new build tool Scipio β€’ Convert Swift Packages to portable binaries β€’ https://github.com/giginet/Scipio β€’ Cache System β€’ Support Static Frameworks β€’ Inspired by Carthage

Slide 22

Slide 22 text

Basic ideas of Scipio β€’ Follow the Apple standard build system β€’ Integrate SwiftPM and XCFramework β€’ Resolving Swift Packages with SwiftPM β€’ Converting to XCFramework Swift Package XCFramework Convert

Slide 23

Slide 23 text

XCFrameworks β€’ Binary distribution format β€’ They can contain multiple frameworks for various architectures and platforms Library.xcframework for arm64 iOS devices for x86_64 iOS Simulators for arm64 Mac devices

Slide 24

Slide 24 text

Using Scipio Prepare a Package.swift describes all app’s dependencies // swift-tools-version: 5.7 import PackageDescription let package = Package( name: "Dependencies", platforms: [.iOS(.v13),], dependencies: [ .package(url: "https://github.com/apple/swift-log.git", from: "1.4.4"), .package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.0.0")), ], targets: [ .target( name: "Dependencies", dependencies: [ .product(name: "Logging", package: "swift-log"), .product(name: "OrderedCollections", package: "swift-collections"), .product(name: "DequeModule", package: "swift-collections"), .product(name: "Collections", package: "swift-collections"), ]), ] )

Slide 25

Slide 25 text

Build all dependencies with Scipio $ scipio prepare /path/to/Dependencies πŸ” Resolving Dependencies... πŸ—‘ Cleaning Dependencies... πŸ“¦ Building OrderedCollections for iOS πŸš€ Combining into XCFramework... πŸ“¦ Building DequeModule for iOS πŸš€ Combining into XCFramework... πŸ“¦ Building Collections for iOS πŸš€ Combining into XCFramework... πŸ“¦ Building Logging for iOS πŸš€ Combining into XCFramework... ❇ Succeeded.

Slide 26

Slide 26 text

1. Resolve and checkout package manifest with SwiftPM 2. Scipio generates Xcode Project from each package 3. Build the projects with xcodebuild 4. xcodebuild generates XCFramework How does Scipio work? Resolve manifests Fetch packages Generate Xcode Project Build XCFrameworks

Slide 27

Slide 27 text

Cache mechanism β€’ Scipio supports cache system β€’ Generate matadata within XCFrameworks β€’ Called VersionFile

Slide 28

Slide 28 text

What is VersionFile { "buildOptions" : { "buildConfiguration" : "debug", "isDebugSymbolsEmbedded" : true, "frameworkType" : "static", "sdks" : [ "iOS" ], "isSimulatorSupported" : true }, "targetName" : "AwesomeKit", "clangVersion" : "clang-1400.0.29.102", "pin" : { "version" : "5.0.1", "revision" : "d458564516e5676af9c70b4f4b2a9178294f1bc6" } } β€’ A JSON f ile contains build contexts β€’ Scipio try to check this before building β€’ Building will be skipped if existing framework is valid .AwesomeKit.version

Slide 29

Slide 29 text

Project cache β€’ Just compare with VersionFile in a destination directory β€’ If a valid VersionFile is exist, Scipio skips building AwesomeKit.xcframework .AwesomeKit.version Destination Directory $ scipio prepare /path/to/Dependencies πŸ” Resolving Dependencies... πŸ—‘ Cleaning Dependencies... βœ… Valid OrderedCollections.xcframework is exists. Skip building. βœ… Valid DequeModule.xcframework is exists. Skip building. βœ… Valid Collections.xcframework is exists. Skip building. βœ… Valid Logging.xcframework is exists. Skip building. ❇ Succeeded.

Slide 30

Slide 30 text

Disk cache β€’ Save XCFrameworks to a system cache directory β€’ Compare SHA256 hash of VersionFiles β€’ Restore same frameworks built in the past AwesomeKit.xcframework Destination Directory System Cache Directory AAAAAA.xcframework BBBBBB.xcframework Restore

Slide 31

Slide 31 text

Remote cache ‒ Just replace storage with remotes (e.g. Amazon S3) ‒ Share all caches among developers AwesomeKit.xcframework Destination Directory Remote object storage AAAAAA.xcframework BBBBBB.xcframework Restore 􀇃

Slide 32

Slide 32 text

Kind of Swift Packages β€’ Swift Package can support various use cases β€’ C Family language supports (SE-0038) β€’ Binary Dependencies (SE-0272) β€’ Artifact bundles (SE-0305)

Slide 33

Slide 33 text

SE-0038 C languages supports β€’ Package Manager C Language Target Support β€’ https://github.com/apple/swift-evolution/blob/main/ proposals/0038-swiftpm-c-language-targets.md β€’ Create Swift Package for C/C++ libraries

Slide 34

Slide 34 text

SE-0272 Binary Framework β€’ SE-0272 Package Manager Binary Dependencies β€’ https://github.com/apple/swift-evolution/blob/main/ proposals/0272-swiftpm-binary-dependencies.md β€’ Distribute prebuilt binaries in Swift Package let package = Package( name: "SomePackage", targets: [ .binaryTarget( name: "SomePackageLib", url: "https://github.com/some/package/releases/download/1.0.0/SomePackage-1.0.0.zip", checksum: "839F9F30DC13C30795666DD8F6FB77DD0E097B83D06954073E34FE5154481F7A" ), .binaryTarget( name: "SomeLibOnDisk", path: "artifacts/SomeLibOnDisk.zip" ) ] )

Slide 35

Slide 35 text

SE-0305 Artifact bundles β€’ Package Manager Binary Target Improvements β€’ https://github.com/apple/swift-evolution/ blob/main/proposals/0305-swiftpm-binary- target-improvements.md β€’ Artifact bundle β€’ A directory structure to distribute executables for multiple architectures in Swift Packages .artifactbundle α΅“ info.json α΅“ β”‚ α΅“ β”‚ β”‚ α΅“ β”‚ β”‚ β”” β”‚ β”” β”‚ α΅“ β”‚ β”” α΅“ β”‚ β”” β”‚ α΅“ β”‚ β”” β”‚ α΄½ β””α΄»

Slide 36

Slide 36 text

Future works β€’ We’re migrating Prebuilt frameworks to Swift Packages β€’ Improve Scipio β€’ Improving stability β€’ Supporting Binary targets

Slide 37

Slide 37 text

Conclusion β€’ Migrating our build system β€’ Using Swift packages is a good solution β€’ Created an OSS, Scipio β€’ Feedbacks and Pull Requests are welcome β€’ https://github.com/giginet/Scipio β€’ Please look forward to our future work!

Slide 38

Slide 38 text

Thank you for listening