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

今日から始めるswift-driver

 今日から始めるswift-driver

at わいわいswiftc #22

1405a601755e5fcbfdc93a2560368bb1?s=128

freddi(Yuki Aki)

September 25, 2020
Tweet

Transcript

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

  2. ຊ೔ͷ࿩ͷྲྀΕɾझࢫ • ίϯύΠϥͷʮυϥΠόʯʹ͍ͭͯ஌Δ • swift-driver ͷৄࡉʹ͍ͭͯ஌Δ • ࣮ࡍʹ ίʔυಡ·ͤͳ͕Βਐߦ͠·͢ɻ •

    Θ͔Μͳ͘ͳͬͨΒԕྀͤͣɺదٓࢭΊ͍ͯͩ͘͞ 2
  3. ʮυϥΠόʯͱ͸ʁ • ͏·͘આ໌Ͱ͖ͳ͍ͷͰͱΓ͋͑ͣάάͬͨΒͳΜ͔͍͍ճ౴ ग़͖ͯͨ • What is a driver, for

    example, a compiler driver? at Quora • Ken Gregg (Founder and CEO, Bytellect LLC) ͞Μ͕આ໌ 3
  4. υϥΠόͷΘ͔Γ΍͔ͬͨ͢આ໌ at Quora • There are several uses of the

    term “driver” in the world of computer so8ware and hardware. • ίϯϐϡʔλͷੈք΍ͱɺϋʔυ΢ΣΞͱιϑτ΢ΣΞʢ։ ൃʣͷੈքͰҧ͏Μ΍Ͱ 4
  5. υϥΠόͷΘ͔Γ΍͔ͬͨ͢આ໌ ϋʔυ΢ΣΞฤ • 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
  6. υϥΠόͷΘ͔Γ΍͔ͬͨ͢આ໌ ιϑτ΢ΣΞฤ • 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
  7. υϥΠόͷΘ͔Γ΍͔ͬͨ͢આ໌ ιϑτ΢ΣΞฤ 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
  8. 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
  9. gcc ͷྫ • Έͳ͞Μ͕ίϯύΠϥͩͱࢥ͍ͬͯΔ gcc͸ɺ ࣮͸ɺίϯύΠϥυϥΠό (compiler driver)ͱݺ͹ΕΔϓϩάϥϜͰ͋Γɺ CͳͲͷϓϩάϥϛϯάݴޠͰ ॻ͔ΕͨιʔεϓϩάϥϜ͔Β࣮ߦܗࣜΛ

    ࡞Γग़ͨ͢ΊͷॲཧΛߦ͏ɻ • gcc͸ɺʮඞཁʹԠͯ͡ίϯύΠϥ΍ ΞηϯϒϥɺϦϯέʔδΤσΟλͳͲͷ ϓϩάϥϜΛݺͼग़͢ʯͱ͍͏ ॲཧΛߦ͍ͬͯΔɻgccίϚϯυࣗମ͕௚઀ί ϯύΠϧΛߦ͍ͬͯΔΘ͚Ͱ͸ͳ͍ɻ • ʮίϯύΠϧʯͱݺ͹Ε͍ͯΔॲཧ͸ cc1 ͱ͍͏ผͷίϚϯυ͕΍͍ͬͯΔ 9
  10. ͜͜·Ͱઆ໌ͨ͠ͷͰʮίϯύΠϥͷੈքͷυϥΠόʯ ·ͱΊ • υϥΠό͸ɺίϯύΠϥٴͼͦͷؔ࿈πʔϧʢOp$mizerɾϦϯ ΧͳͲʣΛݺͼग़͢πʔϧ • gcc ΍ llvmcɺswift ͱݴͬͨίϚϯυ͸ɺυϥΠόͰ͋ͬ

    ͯɺίϯύΠϥࣗ਎Ͱ͸ͳ͍ 10
  11. Swi$ͷυϥΠόʹ͍ͭͯ • swift-frontend ίϚϯυ͔ΒγϯϘϦοΫϦϯΫͰ swift ͱ swiftc Λ࡞͍ͬͯΔ • ͷͪͷͪɺͱ͋Δ෼ذͰ͜ͷγϯϘϦοΫϦϯΫͷ໊લ͕υϥΠόͱ͠

    ͯͷڍಈͷ෼ذʹͳΔ͕ޙड़ • ͪͳΈʹɺυϥΠό͕ݺͼग़͢࢓ࣄͷ୯ҐʢϦϯΫͳͲʣΛδϣϒ ͱݺ ͹ΕΔ • main/lib/Driver ʹυϥΠόͷίʔυ͕༗Δ 11
  12. swi$-driver Λ୳ࡧ • ࠓճ͸ C++ Ͱॻ͔Εͨຊମͷ Driver Ͱ͸ͳ͘ɺSwi,Ͱॻ͔Ε ͨ swift-driver

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

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

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

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

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

    machine when (say) building lots of targets in parallel. ͕Α͘Θ͔ΒΜ 17
  18. swift-driver ͷSwi%PMͰͷϝϦοτ • ͜ͷυϥΠό࢖͏ͱɺSwi%PM ͸υϥΠόͷϏϧυλεΫΛࣗ਎ͷϏϧυάϥϑʹ౷߹Ͱ͖Δ͠ɺҰͭͷγϯάϧΩϡʔͰฒߦλεΫΛ؅ཧͰ͖Δ΍Ͱɻ • ͜ΕͰɺϚγϯͷίΞΛ࠷௿ݶͷڝ߹Ͱ༗ޮ׆༻Ͱ͖Δ΍Ͱɻ ※ ิ଍: ڝ߹

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

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

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

  22. swift-driver ͷ؀ڥߏஙʹඞཁͳ΋ͷ • Xcode 12 (ࢼͨ͠؀ڥ) • swift-driver ͷίʔυ •

    h-ps:/ /github.com/apple/swi<-driver • ͳΔ΂͘৽͠Ίͷ Swi< Trunk ToolChain(SnapShot) • h-ps:/ /swi<.org/download/#snapshots 22
  23. swift-driver ΛϏϧυ͢Δ • Clone ͢Δ $ git clone https://github.com/apple/swift-driver $

    cd swift-driver 23
  24. swift-driver ΛϏϧυ͢Δ (swift build) • swift build ͰϏϧυ͢Δ # swift-driver

    ʹͯ $ swift build 24
  25. swift-driver ΛϏϧυ͢Δ (swift build) • Ϗϧυ͞Εͨ swift-driver Λ swift swiftc

    ͱ͍͏໊લͰ γϯϘϦοΫϦϯΫΛషΔ $ ln -s .build/debug/swift-driver swift $ ln -s .build/debug/swift-driver swiftc 25
  26. swift-driver Λىಈ͢Δ (swift build) • ࢼ͠ʹ swift Λಈ͔͢ $ ./swift

    error: failed to retrieve frontend target info • ಈ͔ͳ͍ 26
  27. 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
  28. swi$-frontend ͷ৘ใ • Xcode 12 ಉ෧ͷ Swi- ͩͱɺswift -frontend -print-

    target-info Ͱಉ༷ͷ΋ͷ͕ग़ͯ͘Δ • ͨͩ͠ɺͪ͜Β͸ swift-driver Ͱ͸ಈ͔ͳ͍ 28
  29. swift-driver Λىಈ͢Δ (swift build) • ಈ͔͢ʹ͸ swift-frontend ͷ৘ใ͕ඞཁ • ->

    ؀ڥม਺ SWIFT_DRIVER_SWIFT_FRONTEND_EXEC Ͱઌఔ ͷ swift-frontend Λࢦఆͯ͠ run ͢Ε͹ྑ͍ 29
  30. 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
  31. swift-driver Λ Debug ͢Δ • Package.swi, Λ௚઀։͍ͯ࡞ۀͯ͠΋ɺͳ͔ͥ Break Point ͕

    main.swift ͚ͩޮ͔ͳ͍ • ๻ͷ؀ڥ͚͔ͩ΋஌Εͳ͍ɾɾɾɾ • ͜ΕͰ΋ແཧͩͬͨɻଞͷؔ਺Ͱ͸ߦ͚Δ • swift package generate-xcodeprojͰ xcodeproj ্Ͱ࡞ۀ + ্هઃఆͩͱ͏·͘ޮ͘ 31
  32. 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
  33. swift-frontend ͸ͳͥඞཁʁ • runtimeLibraryImportPaths • "/Library/Developer/Toolchains/swi6-DEVELOPMENT-SNAPSHOT-2020-09-22-a.xctoolchain/usr/lib/swi6/macosx" • CoreGraphics ͱ͔ FoundaNon

    ͱ͔ͷ dylib ͕͋Δ 33
  34. swift-frontend ͸ͳͥඞཁʁ • ཁ͢ΔʹɺCoreGraphics ͱ͔ Founda2on ͱ͔ͷ dylib ͷύε ΛूΊͨΓ͍ͯ͠Δ

    • ϦϯΧͱ͔ͷδϣϒΛੜ੒͢Δͱ͖ʹɺదٓҾ͖౉͢ • LinkJob.swi9 ͷͱ͖ʹઆ໌ 34
  35. swift-driver ͷδϣϒʹ͍ͭͯ • Sources/Swi,Driver/Jobs Ͱఆٛ͞Ε͍ͯΔ 35

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

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

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

  39. Planning.swi* • υϥΠό (Driver ܕ) ͷঢ়ଶ͔Βɺద੾ͳδϣϒ܈Λฦ͢ planBuild() ͷ࣮૷͕͋Δ • Driver

    ͷ extension • ***Job.swi- ͷதͷؔ਺Λదٓݺͼग़ͯ͠JobΛ࡞ͬͨΓ 39
  40. ͜͜·Ͱͷ·ͱΊ • planBuild() ؔ਺͕ Driver ͷঢ়ଶ͔Βద੾ͳδϣϒ܈Λฦ ͢ • Job ํ͸ɺδϣϒΛද͢ߏ଄ମ͕ఆٛ͞Ε͍ͯΔ

    • ***Job.swi+ ͱ͍͏ϑΝΠϧ͸͍͍ͩͨͦͷδϣϒΛฦؔ͢਺ͷ ࣮૷ 40
  41. planBuild() ؔ਺͕ݺ͹ΕΔͷ͸ʁ • ςετΛআ͘ͱ main.swift ͷΈ͔Βݺͼग़͞Ε͍ͯΔ 41

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

    42
  43. 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
  44. main.swift • ൺֱత୹͍ʂ • ্͔ΒಡΜͰ͍͘ 44

  45. main.swift • ·ͣ͸͸͡Ί͔Β var intHandler: InterruptHandler? let diagnosticsEngine = DiagnosticsEngine(handlers:

    [Driver.stderrDiagnosticsHandler]) do { let processSet = ProcessSet() intHandler = try InterruptHandler { processSet.terminate() } ... 45
  46. 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
  47. 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
  48. 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
  49. 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
  50. ͜͜·Ͱͷ·ͱΊ • δϣϒͷϓϩηεͱͯ͠ͷϋϯυϦϯά • errorɺwarning ౳ʑ ΛΤϥʔඪ४ग़ྗͱͯ͠ϋϯυϦϯά • ্هͷલॲཧͷΑ͏ͳ͜ͱΛ΍͍ͬͯΔ 50

  51. 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
  52. 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
  53. Driver.invocationRunMode(forArgs:) • swift ͔ swiftc Ͱݺͼग़͍ͯ͠Δͷ͔ɺͲΜͳΦϓγϣϯ͕ ෇͍͍ͯΔ͔ɺͳͲͰ Driver ͷϞʔυΛมԽ •

    ྫ͑͹ɺ͜͜Ͱ REPL ͔Ͳ͏͔΋൑ఆ͍ͯ͠Δ • αϒίϚϯυΛݟΔϞʔυΛฦ͢͜ͱ΋͋Δ • ྫ) swift build ͱ͔͸αϒίϚϯυΛݟΔର৅ʹͳΔ 53
  54. 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
  55. if case .subcommand(let subcommand) = ... • αϒίϚϯυΛ୳ࡧ͢Δɻ • ݟ͔ͭΒͳ͚Ε͹

    error • fatalError("cannot find subcommand ... • ݟ͔ͭͬͨΒαϒίϚϯυΛݺͼग़͢ • try exec(path:, args:) 55
  56. ͜͜·Ͱͷ·ͱΊ • swift-driver ͕ͲͷΑ͏ʹݺ͹ΕΔ͔ௐ΂Δ • swift or swiftc or swift

    + αϒίϚϯυ • αϒίϚϯυ͕͋Ε͹ɺͦͷαϒίϚϯυΛ୳ͯ͠ݺͼग़͢ 56
  57. ࠷ޙͷ͜͜ͷ෦෼ ... 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
  58. ࠷ޙͷ͜͜ͷ෦෼ ... // ͜͜ 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
  59. SwiftDriverExecutor • DriverExecutor ϓϩτίϧʹ४ڌͯ͠Δ • δϣϒΛಈ͔͢͜ͱ͕ϝΠϯͷಇ͖ • ͖ͬ͞ͷ ProcessSet ͱ͔

    DiagnosticsEngineɺ؀ڥม਺ͷ σʔλͳͲΛ౉͍ͯ͠Δ • δϣϒΛϓϩηεʹͯ͠ ProcessSet ʹ౉ͨ͠Γɺerror Λ DiagnosticsEngine Ͱ ϋϯυϦϯάͨ͠Γ͍ͯ͠ΔͬΆ͍ 59
  60. ࠷ޙͷ͜͜ͷ෦෼ ... 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
  61. Driver • ݴΘͣ΋͕ͳυϥΠόຊମ • ΠχγϟϥΠβͰɺδϣϒ࣮ߦʹඞཁͳ ProcessSet ΍ error ϋϯυϦϯάͷͨΊͷ DiagnosticsEngine

    Λ౉͢ • υϥΠόʹ౉͞ΕͨΦϓγϣϯ΋౉͢ (arguments) 61
  62. ࠷ޙͷ͜͜ͷ෦෼ ... 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
  63. planBuild() • ౉͞ΕͨΦϓγϣϯ(ΠχγϟϥΠβͰ౉ͨ͠arguments)Λ΋ ͱʹɺ͖ͬ͞આ໌ͨ͠ planBuild() Ͱδϣϒ܈Λੜ੒͢Δ 63

  64. ࠷ޙͷ͜͜ͷ෦෼ ... 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
  65. [try driver.run(jobs: jobs)] • ੜ੒͞ΕͨδϣϒΛ࣮ߦ͢Δ 65

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

  67. 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
  68. ͓͔ͭΕ͞·Ͱͨ͠ • ͱΓ͋͑ͣ޷ධͩͬͨΒ Vol.2 ΍Γ·͢ 68

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

  70. ࢀߟจݙ • 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
  71. ࢀߟจݙ • 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