Slide 1

Slide 1 text

ࠓ೔͔Β͸͡ΊΔ swift-driver Θ͍Θ͍swi$c #23 25nd/Sep/2020 @___freddi___ 1

Slide 2

Slide 2 text

ຊ೔ͷ࿩ͷྲྀΕɾझࢫ • ίϯύΠϥͷʮυϥΠόʯʹ͍ͭͯ஌Δ • swift-driver ͷৄࡉʹ͍ͭͯ஌Δ • ࣮ࡍʹ ίʔυಡ·ͤͳ͕Βਐߦ͠·͢ɻ • Θ͔Μͳ͘ͳͬͨΒԕྀͤͣɺదٓࢭΊ͍ͯͩ͘͞ 2

Slide 3

Slide 3 text

ʮυϥΠόʯͱ͸ʁ • ͏·͘આ໌Ͱ͖ͳ͍ͷͰͱΓ͋͑ͣάάͬͨΒͳΜ͔͍͍ճ౴ ग़͖ͯͨ • What is a driver, for example, a compiler driver? at Quora • Ken Gregg (Founder and CEO, Bytellect LLC) ͞Μ͕આ໌ 3

Slide 4

Slide 4 text

υϥΠόͷΘ͔Γ΍͔ͬͨ͢આ໌ at Quora • There are several uses of the term “driver” in the world of computer so8ware and hardware. • ίϯϐϡʔλͷੈք΍ͱɺϋʔυ΢ΣΞͱιϑτ΢ΣΞʢ։ ൃʣͷੈքͰҧ͏Μ΍Ͱ 4

Slide 5

Slide 5 text

υϥΠόͷΘ͔Γ΍͔ͬͨ͢આ໌ ϋʔυ΢ΣΞฤ • The most common is device driver (some1mes just shortened to driver), which is a piece of so:ware that allows an opera1ng system to communicate with a hardware device. • େମͷ৔߹ʮυϥΠόʯͱ͍͏ͱϋʔυ΢ΣΞͷੈքΛࢦͯ͠ ͯɺOSͱσόΠεͷ΍ΓͱΓΛαϙʔτʢڐՄʣ͢Δ΍ͭ΍Ͱ • όευϥΠόɾϑΟϧλυϥΠόɾιϑτ΢ΣΞυϥΠόʢι ϑτ΢ΣΞͷੈքͷઆ໌Ͱ͸ͳ͍ʣ... 5

Slide 6

Slide 6 text

υϥΠόͷΘ͔Γ΍͔ͬͨ͢આ໌ ιϑτ΢ΣΞฤ • In so'ware development in general, the term driver is some6mes used to refer to a piece of so'ware that controls or drives some other piece of so'ware. • ιϑτ΢ΣΞ։ൃͷੈք΍ͱҰൠతʹ͸ɺυϥΠόͱ͍͏ݴ ༿͸͍͔ͭ͘ͷύʔπʹͳ͍ͬͯΔιϑτ΢ΣΞΛࢀরͨ͠ Γɺݺͼग़ͨ͠Γ͢Διϑτ΢ΣΞͷ͜ͱΛࢦ͢΍Ͱ 6

Slide 7

Slide 7 text

υϥΠόͷΘ͔Γ΍͔ͬͨ͢આ໌ ιϑτ΢ΣΞฤ LLVM ͷྫ • For example, the LLVM Compiler Driver (llvmc) is a tool that can be configured to invoke several compiler development tools and related tools, acAng as a single point of access for users of the LLVM set of tools. • ͨͱ͑͹ɺLLVM Compiler Driver ͸͍͔ͭ͘ͷίϯύΠϥʢͱͦͷؔ࿈ʣ πʔϧͷݺͼग़͠Λߏ੒͢Δ΋ͷ΍Ͱ • Ϣʔβ͔ΒݟͨΒLLVMͷπʔϧ܈ʹΞΫηεͰ͖ΔɺҰͭͷΞΫηεϙΠ ϯτͱͯ͠ৼΔ෣͏΍Ͱ 7

Slide 8

Slide 8 text

llvmc ͷެࣜͷઆ໌ΛಡΉ • The llvmc tool is a configurable compiler driver. As such, it isn't a compiler, op;mizer, or a linker itself but it drives (invokes) other soAware that perform those tasks. If you are familiar with the GNU Compiler Collec;on's gcc tool, llvmc is very similar. • llvmc ࣗମ͸ ίϯύΠϥɾOp;mizerɾϦϯΧࣗ਎ ͡Όͳ͍Ͱ • llvmc ͸υϥΠόͱͯ͠ ίϯύΠϥɾOp;mizerɾϦϯΧࣗ਎ Λಈ͔͢(drivesɾݺͼग़͢)΍Ͱ 8

Slide 9

Slide 9 text

gcc ͷྫ • Έͳ͞Μ͕ίϯύΠϥͩͱࢥ͍ͬͯΔ gcc͸ɺ ࣮͸ɺίϯύΠϥυϥΠό (compiler driver)ͱݺ͹ΕΔϓϩάϥϜͰ͋Γɺ CͳͲͷϓϩάϥϛϯάݴޠͰ ॻ͔ΕͨιʔεϓϩάϥϜ͔Β࣮ߦܗࣜΛ ࡞Γग़ͨ͢ΊͷॲཧΛߦ͏ɻ • gcc͸ɺʮඞཁʹԠͯ͡ίϯύΠϥ΍ ΞηϯϒϥɺϦϯέʔδΤσΟλͳͲͷ ϓϩάϥϜΛݺͼग़͢ʯͱ͍͏ ॲཧΛߦ͍ͬͯΔɻgccίϚϯυࣗମ͕௚઀ί ϯύΠϧΛߦ͍ͬͯΔΘ͚Ͱ͸ͳ͍ɻ • ʮίϯύΠϧʯͱݺ͹Ε͍ͯΔॲཧ͸ cc1 ͱ͍͏ผͷίϚϯυ͕΍͍ͬͯΔ 9

Slide 10

Slide 10 text

͜͜·Ͱઆ໌ͨ͠ͷͰʮίϯύΠϥͷੈքͷυϥΠόʯ ·ͱΊ • υϥΠό͸ɺίϯύΠϥٴͼͦͷؔ࿈πʔϧʢOp$mizerɾϦϯ ΧͳͲʣΛݺͼग़͢πʔϧ • gcc ΍ llvmcɺswift ͱݴͬͨίϚϯυ͸ɺυϥΠόͰ͋ͬ ͯɺίϯύΠϥࣗ਎Ͱ͸ͳ͍ 10

Slide 11

Slide 11 text

Swi$ͷυϥΠόʹ͍ͭͯ • swift-frontend ίϚϯυ͔ΒγϯϘϦοΫϦϯΫͰ swift ͱ swiftc Λ࡞͍ͬͯΔ • ͷͪͷͪɺͱ͋Δ෼ذͰ͜ͷγϯϘϦοΫϦϯΫͷ໊લ͕υϥΠόͱ͠ ͯͷڍಈͷ෼ذʹͳΔ͕ޙड़ • ͪͳΈʹɺυϥΠό͕ݺͼग़͢࢓ࣄͷ୯ҐʢϦϯΫͳͲʣΛδϣϒ ͱݺ ͹ΕΔ • main/lib/Driver ʹυϥΠόͷίʔυ͕༗Δ 11

Slide 12

Slide 12 text

swi$-driver Λ୳ࡧ • ࠓճ͸ C++ Ͱॻ͔Εͨຊମͷ Driver Ͱ͸ͳ͘ɺSwi,Ͱॻ͔Ε ͨ swift-driver ΛݟΔ 12

Slide 13

Slide 13 text

swift-driver ʹ͍ͭͯ • Swi% υϥΠόͷ Swi% ʹΑΔॻ͖׵͑ • AppleͷΤϯδχΞʹΑΔɺSNSͰͷॳग़ͷݴٴ 13

Slide 14

Slide 14 text

swift-driver ͷSwi%PMͰͷར༻ • swi%PM Ͱ --use-integrated-swift-driver ΦϓγϣϯͰ͜ͷdriver͕ར༻Մೳʹͳͬͨ 14

Slide 15

Slide 15 text

swift-driver ͷSwi%PMͰͷར༻ • ϝϦοτ͸͜ͷ Twi&er εϨͰৄ͘͠આ໌͞Ε͍ͯΔ • h&ps:/ /twi&er.com/Javi/status/1260793917563256834 15

Slide 16

Slide 16 text

swift-driver ͷSwi%PMͰͷϝϦοτ • ΞϗΈ͍ͨͳ࣭໰͔΋͠Ε΁Μ͚Ͳɺ͜Ε࢖͏ྑ͍఺Կʁ 16

Slide 17

Slide 17 text

swift-driver ͷSwi%PMͰͷϝϦοτ • ΞϗΈ͍ͨͳ࣭໰͡Όͳ͍ͰɻҰͭͷେ͖ͳར఺͸ɺ͜ͷυϥΠό͸Swi%PMͷ֎ଆͷϏϧυγεςϜ͔Β͸ෆಁ໌ͳɺΠϯΫϦϝϯλϧϏϧυͷͨ Ίͷ಺෦ϏϧυγεςϜΛඋ͍͑ͯΔ΍Ͱ • leading to oversubscribing the machine when (say) building lots of targets in parallel. ͕Α͘Θ͔ΒΜ 17

Slide 18

Slide 18 text

swift-driver ͷSwi%PMͰͷϝϦοτ • ͜ͷυϥΠό࢖͏ͱɺSwi%PM ͸υϥΠόͷϏϧυλεΫΛࣗ਎ͷϏϧυάϥϑʹ౷߹Ͱ͖Δ͠ɺҰͭͷγϯάϧΩϡʔͰฒߦλεΫΛ؅ཧͰ͖Δ΍Ͱɻ • ͜ΕͰɺϚγϯͷίΞΛ࠷௿ݶͷڝ߹Ͱ༗ޮ׆༻Ͱ͖Δ΍Ͱɻ ※ ิ଍: ڝ߹ … CPUͷϦιʔεΛλεΫ͕औΓ߹͏͜ͱΛࢦ͢ 18

Slide 19

Slide 19 text

swift-driver ͷSwi%PMͰͷϝϦοτ • ଞͩͱΞʔΩςΫνϟͷ໘Ͱ΋ϝϦοτ͕͋ΔΜ΍ • ͜ͷυϥΠόͰಈతεέδϡʔϦϯά͕Ͱ͖ΔΜ΍Ͱɺ͜ΕͰɺϫΠ͕ͨͪ৭ʑ΍͖ͬͯͨվળͷ࣮૷͕΍Γ΍͘͢ͳΔΜ΍ɻ 19

Slide 20

Slide 20 text

swift-driver ͷSwi%PMͰͷϝϦοτ • ͋ͱݸਓతʹSwi%Ͱॻ͚Δͷ͕خ͍͠΍Ͱ 20

Slide 21

Slide 21 text

swift-driver Λ৮Δ • ࣮ࡍʹ؀ڥߏஙΛͯ͠ಈ͔ͯ͠ΈΑ͏ 21

Slide 22

Slide 22 text

swift-driver ͷ؀ڥߏஙʹඞཁͳ΋ͷ • Xcode 12 (ࢼͨ͠؀ڥ) • swift-driver ͷίʔυ • h-ps:/ /github.com/apple/swi<-driver • ͳΔ΂͘৽͠Ίͷ Swi< Trunk ToolChain(SnapShot) • h-ps:/ /swi<.org/download/#snapshots 22

Slide 23

Slide 23 text

swift-driver ΛϏϧυ͢Δ • Clone ͢Δ $ git clone https://github.com/apple/swift-driver $ cd swift-driver 23

Slide 24

Slide 24 text

swift-driver ΛϏϧυ͢Δ (swift build) • swift build ͰϏϧυ͢Δ # swift-driver ʹͯ $ swift build 24

Slide 25

Slide 25 text

swift-driver ΛϏϧυ͢Δ (swift build) • Ϗϧυ͞Εͨ swift-driver Λ swift swiftc ͱ͍͏໊લͰ γϯϘϦοΫϦϯΫΛషΔ $ ln -s .build/debug/swift-driver swift $ ln -s .build/debug/swift-driver swiftc 25

Slide 26

Slide 26 text

swift-driver Λىಈ͢Δ (swift build) • ࢼ͠ʹ swift Λಈ͔͢ $ ./swift error: failed to retrieve frontend target info • ಈ͔ͳ͍ 26

Slide 27

Slide 27 text

swift-driver Λىಈ͢Δ (swift build) • ಈ͔͢ʹ͸ swi&-frontend ͷ৘ใ͕ඞཁ $ /Library/Developer/Toolchains/{ઌఔΠϯετʔϧͨ͠ToolChainͷύε}/usr/bin/swift-frontend -frontend -print-target-info { "compilerVersion": "Apple Swift version 5.3-dev (LLVM 2685951d827b16e, Swift ec72db1d8ab63fa)", "target": { "triple": "x86_64-apple-macosx10.15", "unversionedTriple": "x86_64-apple-macosx", "moduleTriple": "x86_64-apple-macos", "swiftRuntimeCompatibilityVersion": "5.1", "compatibilityLibraries": [ { "libraryName": "swiftCompatibility51", "filter": "all" } ], "librariesRequireRPath": false }, "paths": { "runtimeLibraryPaths": [ "/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-09-22-a.xctoolchain/usr/lib/swift/macosx", "/usr/lib/swift" ], "runtimeLibraryImportPaths": [ "/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-09-22-a.xctoolchain/usr/lib/swift/macosx" ], "runtimeResourcePath": "/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-09-22-a.xctoolchain/usr/lib/swift" } } 27

Slide 28

Slide 28 text

swi$-frontend ͷ৘ใ • Xcode 12 ಉ෧ͷ Swi- ͩͱɺswift -frontend -print- target-info Ͱಉ༷ͷ΋ͷ͕ग़ͯ͘Δ • ͨͩ͠ɺͪ͜Β͸ swift-driver Ͱ͸ಈ͔ͳ͍ 28

Slide 29

Slide 29 text

swift-driver Λىಈ͢Δ (swift build) • ಈ͔͢ʹ͸ swift-frontend ͷ৘ใ͕ඞཁ • -> ؀ڥม਺ SWIFT_DRIVER_SWIFT_FRONTEND_EXEC Ͱઌఔ ͷ swift-frontend Λࢦఆͯ͠ run ͢Ε͹ྑ͍ 29

Slide 30

Slide 30 text

swift-driver Λىಈ͢Δ (swift build) $ export SWIFT_DRIVER_SWIFT_FRONTEND_EXEC=/Library/Developer/Toolchains/{ToolChainͷύε}/usr/bin/swift-frontend $ ./swift Type :help for assistance. 1> • ͜ΕͰREPL͕ىಈ͢Δ • swiftc ΋ಈ͘ $ ./swift test.swift 30

Slide 31

Slide 31 text

swift-driver Λ Debug ͢Δ • Package.swi, Λ௚઀։͍ͯ࡞ۀͯ͠΋ɺͳ͔ͥ Break Point ͕ main.swift ͚ͩޮ͔ͳ͍ • ๻ͷ؀ڥ͚͔ͩ΋஌Εͳ͍ɾɾɾɾ • ͜ΕͰ΋ແཧͩͬͨɻଞͷؔ਺Ͱ͸ߦ͚Δ • swift package generate-xcodeprojͰ xcodeproj ্Ͱ࡞ۀ + ্هઃఆͩͱ͏·͘ޮ͘ 31

Slide 32

Slide 32 text

swift-frontend ͸ͳͥඞཁʁ • ग़ྗ͞Εͨ΋ͷͷ͏ͪɺpathsͷ৘ใʹϑΥʔΧεͯ͠ΈΔ { "runtimeLibraryPaths": [ "/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-09-22-a.xctoolchain/usr/lib/swift/macosx", "/usr/lib/swift" ], "runtimeLibraryImportPaths": [ "/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-09-22-a.xctoolchain/usr/lib/swift/macosx" ], "runtimeResourcePath": "/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-09-22-a.xctoolchain/usr/lib/swift" } 32

Slide 33

Slide 33 text

swift-frontend ͸ͳͥඞཁʁ • runtimeLibraryImportPaths • "/Library/Developer/Toolchains/swi6-DEVELOPMENT-SNAPSHOT-2020-09-22-a.xctoolchain/usr/lib/swi6/macosx" • CoreGraphics ͱ͔ FoundaNon ͱ͔ͷ dylib ͕͋Δ 33

Slide 34

Slide 34 text

swift-frontend ͸ͳͥඞཁʁ • ཁ͢ΔʹɺCoreGraphics ͱ͔ Founda2on ͱ͔ͷ dylib ͷύε ΛूΊͨΓ͍ͯ͠Δ • ϦϯΧͱ͔ͷδϣϒΛੜ੒͢Δͱ͖ʹɺదٓҾ͖౉͢ • LinkJob.swi9 ͷͱ͖ʹઆ໌ 34

Slide 35

Slide 35 text

swift-driver ͷδϣϒʹ͍ͭͯ • Sources/Swi,Driver/Jobs Ͱఆٛ͞Ε͍ͯΔ 35

Slide 36

Slide 36 text

swift-driver ͷδϣϒʹ͍ͭͯ • ࠓ೔ݟΔͷ͸ ... • Job.swi* • LinkJob.swi* • Planning.swi* 36

Slide 37

Slide 37 text

Job.swi( • Ͳ͏͍͏δϣϒ͔Λද͢ Job ߏ଄ମ͕ఆٛ͞Ε͍ͯΔ 37

Slide 38

Slide 38 text

LinkJob.swi+ • ϥΠϒϥϦͷϦϯΫͷδϣϒ Λฦؔ͢਺ • ***Job.swi+ ͱ͍͏ϑΝΠϧ͸͍͍ͩͨͦͷδϣϒΛฦؔ͢਺ͷ ࣮૷ 38

Slide 39

Slide 39 text

Planning.swi* • υϥΠό (Driver ܕ) ͷঢ়ଶ͔Βɺద੾ͳδϣϒ܈Λฦ͢ planBuild() ͷ࣮૷͕͋Δ • Driver ͷ extension • ***Job.swi- ͷதͷؔ਺Λదٓݺͼग़ͯ͠JobΛ࡞ͬͨΓ 39

Slide 40

Slide 40 text

͜͜·Ͱͷ·ͱΊ • planBuild() ؔ਺͕ Driver ͷঢ়ଶ͔Βద੾ͳδϣϒ܈Λฦ ͢ • Job ํ͸ɺδϣϒΛද͢ߏ଄ମ͕ఆٛ͞Ε͍ͯΔ • ***Job.swi+ ͱ͍͏ϑΝΠϧ͸͍͍ͩͨͦͷδϣϒΛฦؔ͢਺ͷ ࣮૷ 40

Slide 41

Slide 41 text

planBuild() ؔ਺͕ݺ͹ΕΔͷ͸ʁ • ςετΛআ͘ͱ main.swift ͷΈ͔Βݺͼग़͞Ε͍ͯΔ 41

Slide 42

Slide 42 text

main.swift • ͋Δఔ౓ಡΉࡐྉ͕੔ͬͨͷͰɺmain.swift Λ೷͘ • swift-driver ͷ ϓϩάϥϜͷ࢝·Γ • ͜͜Λͬ͟ͱಡΉͱɺυϥΠόͷ໾ׂ͕Կͱͳ͘෼͔Δ 42

Slide 43

Slide 43 text

main.swift import SwiftDriverExecution import SwiftDriver import TSCLibc import TSCBasic import TSCUtility var intHandler: InterruptHandler? let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler]) do { let processSet = ProcessSet() intHandler = try InterruptHandler { processSet.terminate() } let (mode, arguments) = try Driver.invocationRunMode(forArgs: CommandLine.arguments) if case .subcommand(let subcommand) = mode { // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. let subcommandPath = Process.findExecutable(arguments[0])?.parentDirectory.appending(component: subcommand) ?? Process.findExecutable(subcommand) if subcommandPath == nil || !localFileSystem.exists(subcommandPath!) { fatalError("cannot find subcommand executable '\(subcommand)'") } // Execute the subcommand. try exec(path: subcommandPath?.pathString ?? "", args: arguments) } let executor = try SwiftDriverExecutor(diagnosticsEngine: diagnosticsEngine, processSet: processSet, fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() try driver.run(jobs: jobs) if driver.diagnosticEngine.hasErrors { exit(EXIT_FAILURE) } } catch Diagnostics.fatalError { exit(EXIT_FAILURE) } catch let diagnosticData as DiagnosticData { diagnosticsEngine.emit(.error(diagnosticData)) exit(EXIT_FAILURE) } catch { print("error: \(error)") exit(EXIT_FAILURE) } 43

Slide 44

Slide 44 text

main.swift • ൺֱత୹͍ʂ • ্͔ΒಡΜͰ͍͘ 44

Slide 45

Slide 45 text

main.swift • ·ͣ͸͸͡Ί͔Β var intHandler: InterruptHandler? let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler]) do { let processSet = ProcessSet() intHandler = try InterruptHandler { processSet.terminate() } ... 45

Slide 46

Slide 46 text

DiagnosticsEngine var intHandler: InterruptHandler? let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler]) // ͜Ε do { let processSet = ProcessSet() intHandler = try InterruptHandler { processSet.terminate() } ... • DiagnosticsEngine • ݟͨײ͡ɺerror ΍ warning ͱ͍ͬͨ਍அͷ݁ՌΛϋϯυϦϯά͢Δ • main.swift ͩͱ Driver.stderrDiagnosticsHandler Λ౉͍ͯ͠Δ • swift-driver ͷίʔυͰ͸ͳ͘ɺapple/swi/-tools-support-core ͷίʔυ 46

Slide 47

Slide 47 text

Driver.stderrDiagnosticsHandler public static let stderrDiagnosticsHandler: DiagnosticsEngine.DiagnosticsHandler = { diagnostic in let stream = stderrStream if !(diagnostic.location is UnknownLocation) { stream <<< diagnostic.location.description <<< ": " } switch diagnostic.message.behavior { case .error: stream <<< "error: " case .warning: stream <<< "warning: " ... • error ͱ͔ warning Λ ඪ४Τϥʔग़ྗͱͯ͠ग़͢Α͏ʹϋϯυϦ ϯά͍ͯ͠Δ 47

Slide 48

Slide 48 text

ProcessSet ͱ InterruptHandler var intHandler: InterruptHandler? // ͜Ε let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler]) do { let processSet = ProcessSet() intHandler = try InterruptHandler { // ͜Ε processSet.terminate() } ... • InterruptHandler • ׂΓࠐΈγάφϧ (Ctrl + C) ౳ͷγάφϧ͕૸ͬͨͱ͖ͷϋϯυϥ • main.swift Ͱ͸ ProcessSet Λ terminate ͢ΔΑ͏ʹϋϯυϧ͍ͯ͠Δ • swift-driver ͷίʔυͰ͸ͳ͘ɺapple/swi1-tools-support-core ͷίʔυ 48

Slide 49

Slide 49 text

ProcessSet ͱ InterruptHandler var intHandler: InterruptHandler? let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler]) do { let processSet = ProcessSet() // ͜Ε intHandler = try InterruptHandler { processSet.terminate() // ͜Ε } ... • ProcessSet • ؆୯ʹݴ͑͹ϓϩηεͷίϨΫγϣϯ • Job ͸࠷ऴతʹ͜ͷίϨΫγϣϯʹϓϩηεͱͯ͠ొ࿥͞ΕΔ • swift-driver ͷίʔυͰ͸ͳ͘ɺapple/swi+-tools-support-core ͷίʔυ 49

Slide 50

Slide 50 text

͜͜·Ͱͷ·ͱΊ • δϣϒͷϓϩηεͱͯ͠ͷϋϯυϦϯά • errorɺwarning ౳ʑ ΛΤϥʔඪ४ग़ྗͱͯ͠ϋϯυϦϯά • ্هͷલॲཧͷΑ͏ͳ͜ͱΛ΍͍ͬͯΔ 50

Slide 51

Slide 51 text

Driver.invocationRunMode ~ try exec(... • ࣍͸͔͜͜ΒಡΉ ... let (mode, arguments) = try Driver.invocationRunMode(forArgs: CommandLine.arguments) if case .subcommand(let subcommand) = mode { // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. let subcommandPath = Process.findExecutable(arguments[0])?.parentDirectory.appending(component: subcommand) ?? Process.findExecutable(subcommand) if subcommandPath == nil || !localFileSystem.exists(subcommandPath!) { fatalError("cannot find subcommand executable '\(subcommand)'") } // Execute the subcommand. try exec(path: subcommandPath?.pathString ?? "", args: arguments) } ... 51

Slide 52

Slide 52 text

Driver.invocationRunMode(forArgs:) ... let (mode, arguments) = try Driver.invocationRunMode(forArgs: CommandLine.arguments) // ͜͜ if case .subcommand(let subcommand) = mode { // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. let subcommandPath = Process.findExecutable(arguments[0])?.parentDirectory.appending(component: subcommand) ?? Process.findExecutable(subcommand) if subcommandPath == nil || !localFileSystem.exists(subcommandPath!) { fatalError("cannot find subcommand executable '\(subcommand)'") } // Execute the subcommand. try exec(path: subcommandPath?.pathString ?? "", args: arguments) } ... 52

Slide 53

Slide 53 text

Driver.invocationRunMode(forArgs:) • swift ͔ swiftc Ͱݺͼग़͍ͯ͠Δͷ͔ɺͲΜͳΦϓγϣϯ͕ ෇͍͍ͯΔ͔ɺͳͲͰ Driver ͷϞʔυΛมԽ • ྫ͑͹ɺ͜͜Ͱ REPL ͔Ͳ͏͔΋൑ఆ͍ͯ͠Δ • αϒίϚϯυΛݟΔϞʔυΛฦ͢͜ͱ΋͋Δ • ྫ) swift build ͱ͔͸αϒίϚϯυΛݟΔର৅ʹͳΔ 53

Slide 54

Slide 54 text

if case .subcommand(let subcommand) = ... ... let (mode, arguments) = try Driver.invocationRunMode(forArgs: CommandLine.arguments) if case .subcommand(let subcommand) = mode { // ͜͜ // We are running as a subcommand, try to find the subcommand adjacent to the executable we are running as. // If we didn't find the tool there, let the OS search for it. let subcommandPath = Process.findExecutable(arguments[0])?.parentDirectory.appending(component: subcommand) ?? Process.findExecutable(subcommand) if subcommandPath == nil || !localFileSystem.exists(subcommandPath!) { fatalError("cannot find subcommand executable '\(subcommand)'") } // Execute the subcommand. try exec(path: subcommandPath?.pathString ?? "", args: arguments) } ... 54

Slide 55

Slide 55 text

if case .subcommand(let subcommand) = ... • αϒίϚϯυΛ୳ࡧ͢Δɻ • ݟ͔ͭΒͳ͚Ε͹ error • fatalError("cannot find subcommand ... • ݟ͔ͭͬͨΒαϒίϚϯυΛݺͼग़͢ • try exec(path:, args:) 55

Slide 56

Slide 56 text

͜͜·Ͱͷ·ͱΊ • swift-driver ͕ͲͷΑ͏ʹݺ͹ΕΔ͔ௐ΂Δ • swift or swiftc or swift + αϒίϚϯυ • αϒίϚϯυ͕͋Ε͹ɺͦͷαϒίϚϯυΛ୳ͯ͠ݺͼग़͢ 56

Slide 57

Slide 57 text

࠷ޙͷ͜͜ͷ෦෼ ... let executor = try SwiftDriverExecutor(diagnosticsEngine: diagnosticsEngine, processSet: processSet, fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() try driver.run(jobs: jobs) ... 57

Slide 58

Slide 58 text

࠷ޙͷ͜͜ͷ෦෼ ... // ͜͜ let executor = try SwiftDriverExecutor(diagnosticsEngine: diagnosticsEngine, processSet: processSet, fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() try driver.run(jobs: jobs) ... 58

Slide 59

Slide 59 text

SwiftDriverExecutor • DriverExecutor ϓϩτίϧʹ४ڌͯ͠Δ • δϣϒΛಈ͔͢͜ͱ͕ϝΠϯͷಇ͖ • ͖ͬ͞ͷ ProcessSet ͱ͔ DiagnosticsEngineɺ؀ڥม਺ͷ σʔλͳͲΛ౉͍ͯ͠Δ • δϣϒΛϓϩηεʹͯ͠ ProcessSet ʹ౉ͨ͠Γɺerror Λ DiagnosticsEngine Ͱ ϋϯυϦϯάͨ͠Γ͍ͯ͠ΔͬΆ͍ 59

Slide 60

Slide 60 text

࠷ޙͷ͜͜ͷ෦෼ ... let executor = try SwiftDriverExecutor(diagnosticsEngine: diagnosticsEngine, processSet: processSet, fileSystem: localFileSystem, env: ProcessEnv.vars) // ͜͜ var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() try driver.run(jobs: jobs) ... 60

Slide 61

Slide 61 text

Driver • ݴΘͣ΋͕ͳυϥΠόຊମ • ΠχγϟϥΠβͰɺδϣϒ࣮ߦʹඞཁͳ ProcessSet ΍ error ϋϯυϦϯάͷͨΊͷ DiagnosticsEngine Λ౉͢ • υϥΠόʹ౉͞ΕͨΦϓγϣϯ΋౉͢ (arguments) 61

Slide 62

Slide 62 text

࠷ޙͷ͜͜ͷ෦෼ ... let executor = try SwiftDriverExecutor(diagnosticsEngine: diagnosticsEngine, processSet: processSet, fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } // ͜͜ let jobs = try driver.planBuild() try driver.run(jobs: jobs) ... 62

Slide 63

Slide 63 text

planBuild() • ౉͞ΕͨΦϓγϣϯ(ΠχγϟϥΠβͰ౉ͨ͠arguments)Λ΋ ͱʹɺ͖ͬ͞આ໌ͨ͠ planBuild() Ͱδϣϒ܈Λੜ੒͢Δ 63

Slide 64

Slide 64 text

࠷ޙͷ͜͜ͷ෦෼ ... let executor = try SwiftDriverExecutor(diagnosticsEngine: diagnosticsEngine, processSet: processSet, fileSystem: localFileSystem, env: ProcessEnv.vars) var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine, executor: executor) // FIXME: The following check should be at the end of Driver.init, but current // usage of the DiagnosticVerifier in tests makes this difficult. guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError } let jobs = try driver.planBuild() // ͜͜ try driver.run(jobs: jobs) ... 64

Slide 65

Slide 65 text

[try driver.run(jobs: jobs)] • ੜ੒͞ΕͨδϣϒΛ࣮ߦ͢Δ 65

Slide 66

Slide 66 text

͜͜·Ͱͷ·ͱΊ • Swi% ͷυϥΠό͸ΦϓγϣϯͰͲ͏͍͏δϣϒΛ࣮ߦ͢Δ͔Λ ܾΊΔ • δϣϒ͸ϓϩηεͱͯ͠ಈ͔͞ΕΔ 66

Slide 67

Slide 67 text

main.swift ΄΅શ෦ಡΊͨʂ if driver.diagnosticEngine.hasErrors { exit(EXIT_FAILURE) } } catch Diagnostics.fatalError { exit(EXIT_FAILURE) } catch let diagnosticData as DiagnosticData { diagnosticsEngine.emit(.error(diagnosticData)) exit(EXIT_FAILURE) } catch { print("error: \(error)") exit(EXIT_FAILURE) } • ޙ͸ try catch ͷΤϥʔϋϯυϦϯά͚ͩͰ͢ • આ໌͠ͳͯ͘΋͍͍ͩͨΘ͔Δͱࢥ͍·͢ 67

Slide 68

Slide 68 text

͓͔ͭΕ͞·Ͱͨ͠ • ͱΓ͋͑ͣ޷ධͩͬͨΒ Vol.2 ΍Γ·͢ 68

Slide 69

Slide 69 text

Special Thanks • @kateinoigakukun san • ͪͳΈʹ൴͸͢ͰʹContribute͍ͯ͠·͢ 69

Slide 70

Slide 70 text

ࢀߟจݙ • What is a driver, for example, a compiler driver? - Quora • h9ps:/ /www.quora.com/What-is-a-driver-for-example-a-compiler-driver • IntroducAon - The LLVM Compiler Driver (llvmc) • h9ps:/ /releases.llvm.org/1.8/docs/CompilerDriver.html • ίϯύΠϥ͸ԿΛ͍ͯ͠Δͷ͔ - େ୍ ݚڀࣨ Ἒ৓େֶ • h9p:/ /nenya.cis.ibaraki.ac.jp/TIPS/compiler.html 70

Slide 71

Slide 71 text

ࢀߟจݙ • apple/swi*-driver • h0ps:/ /github.com/apple/swi*-driver • Harlan Haskins - Twi0er • h0ps:/ /twi0er.com/harlanhaskins/status/1182325909220556800 • Javi - Twi0er • h0ps:/ /twi0er.com/Javi/status/1260793917563256834 71