Slide 1

Slide 1 text

Exploring Clang Modules Samuel Giddins 1

Slide 2

Slide 2 text

@segiddins CocoaPods, Bundler, RubyGems Mobile Developer Experience @ Square Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 2

Slide 3

Slide 3 text

Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 3

Slide 4

Slide 4 text

cool_function.h #define AUTHORS_NAME "segiddins" extern void printMyName(char *); main.c #include "cool_function.h" int main(int argc, char **argv) { printMyName(AUTHORS_NAME); } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 4

Slide 5

Slide 5 text

main.c extern void printMyName(char *); int main(int argc, char **argv) { printMyName("segiddins"); } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 5

Slide 6

Slide 6 text

#include "header.h" #define MAGIC_NUMBER 42 ... ... ... #include "header2.h" // also includes header.h preprocessed into: static int secretNumber = -1; static int secretNumber = 42; Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 6

Slide 7

Slide 7 text

// header.h #ifndef __HEADER_H #define __HEADER_H ... #endif // #ifndef __HEADER_H Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 7

Slide 8

Slide 8 text

#import "header.h" Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 8

Slide 9

Slide 9 text

Enter Module Maps Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 9

Slide 10

Slide 10 text

Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 10

Slide 11

Slide 11 text

UsefulFramework.modulemap / module.modulemap framework module UsefulFramework { umbrella header "UsefulFramework.h" export * module * { export * } } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 11

Slide 12

Slide 12 text

UsefulFramework.modulemap framework module UsefulFramework { umbrella header "UsefulFramework.h" export * module * { export * } } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 12

Slide 13

Slide 13 text

UsefulFramework.modulemap framework module UsefulFramework { umbrella header "UsefulFramework.h" export * module * { export * } } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 13

Slide 14

Slide 14 text

UsefulFramework.modulemap framework module UsefulFramework { umbrella header "UsefulFramework.h" export * module * { export * } } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 14

Slide 15

Slide 15 text

UsefulFramework.modulemap framework module UsefulFramework { umbrella header "UsefulFramework.h" export * module * { export * } } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 15

Slide 16

Slide 16 text

main.swift import UsefulFramework main.m @import UsefulFramework; Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 16

Slide 17

Slide 17 text

Module Maps, the hard part Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 17

Slide 18

Slide 18 text

Module Maps, the hard part Lessons from CocoaPods Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 18

Slide 19

Slide 19 text

• Umbrella Directories • Explicit Submodules • Private Headers • Textual Headers • ... • Automatic Module Map Discovery • Relative Paths Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 19

Slide 20

Slide 20 text

Umbrella Directories framework module UsefulFramework { umbrella "HeadersDirectory" } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 20

Slide 21

Slide 21 text

Explicit Submodules Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 21

Slide 22

Slide 22 text

Explicit Submodules framework module UsefulFramework { umbrella header "UsefulFramework.h" explicit module ForSubclassEyesOnly { header "ComplicatedTextField_subclass.h" } } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 22

Slide 23

Slide 23 text

Private Headers framework module UsefulFramework { umbrella header "UsefulFramework.h" private header "PrivateHashMapImpl.h" } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 23

Slide 24

Slide 24 text

Textual Headers framework module UsefulFramework { umbrella header "UsefulFramework.h" textual header "AssertMacros.h" } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 24

Slide 25

Slide 25 text

Requires framework module UsefulFramework { umbrella header "UsefulFramework.h" requires objc_arc, blocks, !altivec } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 25

Slide 26

Slide 26 text

Conflicts framework module UsefulFramework { umbrella header "UsefulFramework.h" conflict PointlessFramework, "we do something more useful than that framework" } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 26

Slide 27

Slide 27 text

Automatic Module Map Discovery $ tree include include !"" baking.h !"" cake.h !"" cookie.h !"" module.modulemap Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 27

Slide 28

Slide 28 text

Relative Paths Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 28

Slide 29

Slide 29 text

Relative Paths framework module UsefulFramework { header "UsefulFramework.h" } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 29

Slide 30

Slide 30 text

Modules & Swift Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 30

Slide 31

Slide 31 text

But my Swift code doesn't have headers... Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 31

Slide 32

Slide 32 text

But my Swift code doesn't have headers... It does ! Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 32

Slide 33

Slide 33 text

swiftc Understands .swiftmodule Files Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 33

Slide 34

Slide 34 text

The Mixed Framework Process 1. Compile all .swift files 2. Generate ModuleName-Swift.h in the (empty) .framework 3. "Extend" existing module map with .Swift submodule 4. Compile .m files Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 34

Slide 35

Slide 35 text

Extended Module Maps module ModuleName.Swift { header "ModuleName-Swift.h" requires objc } Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 35

Slide 36

Slide 36 text

Same-Module Imports Superclass.m #import Subclass.swift // nothing to import! Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 36

Slide 37

Slide 37 text

Same-Module Imports swiftc Useful.swift -module-name UsefulFramework -import-underlying-module -emit-module -emit-objc-header -Xcc -fmodule-map-file="UsefulFramework.modulemap" Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 37

Slide 38

Slide 38 text

Swift Static Libraries in CocoaPods All of the changes needed: https://github.com/CocoaPods/CocoaPods/pull/6966 Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 38

Slide 39

Slide 39 text

Are Modules the Future? • Tied to headers • Swift module stability • Still confusing • Better than C Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 39

Slide 40

Slide 40 text

Some Resources • Clang Docs https://clang.llvm.org/docs/Modules.html • Clang Source https://github.com/llvm-mirror/clang/blob/master/include/clang/ Basic/Module.h • CocoaPods Source https://github.com/CocoaPods/CocoaPods/blob/master/lib/ cocoapods/generator/module_map.rb • Trial & Error Exploring Clang Modules – Samuel Giddins @ try! Swift Tokyo 2018 40

Slide 41

Slide 41 text

@segiddins Mobile Developer Experience @ Square Exploring Clang Modules 41