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

Hacking Xcode Behaviors / macOS native symposium #08

Hacking Xcode Behaviors / macOS native symposium #08

プロジェクトのBuild PhasesにRun Scriptを追加することでターゲットのビルド時に特定の処理を挟み込むことができますが、Xcode Behaviorsはプロジェクト単位ではなくXcode全般でのイベントに処理を挟み込むことができます。そんなBehaviorsをハックして、ビルドやテストのイベントを別アプリから監視する仕組みを実現するまでの試行錯誤について紹介します。

Kyome (Takuto Nakamura)

August 27, 2022
Tweet

More Decks by Kyome (Takuto Nakamura)

Other Decks in Programming

Transcript

  1. Kyome
    macOS native Symposium #08

    2022/08/27 (Sat)
    Hacking Xcode Behaviors

    View Slide

  2. ࣗݾ঺հ
    IUUQTLZPNFJP
    ,ZPNF
    ,ZPNFTVLF
    macOS޲͚ͷϢʔςΟϦςΟΞϓϦ։ൃऀʢझຯ݉෭ۀʣ

    ϝχϡʔόʔৗறܕΞϓϦɺApp Extension ͕ಘҙ෼໺

    OSSϓϩδΣΫτӡӦʹνϟϨϯδத

    View Slide

  3. ࣗݾ঺հ
    RunCat
    activity indicator
    HandyPalette
    color picker
    ScreenPointer
    presentation tool
    ShiftWindow
    window organizer

    View Slide

  4. Xcode Behaviors

    View Slide

  5. Xcode Behaviors
    Build PhasesͷRun ScriptsͰ͸
    TARGETͷϏϧυ࣌ʹShell ScriptͰ
    ॲཧΛڬΈࠐΉ͜ͱ͕Մೳ

    Linter΍FormatterΛ࣮ߦͨ͠Γɺ

    Ϧιʔε༻ͷSwiftίʔυΛੜ੒ͨ͠
    ΓɺϏϧυલͷԼॲཧʹར༻Մೳ

    ϓϩδΣΫτ͝ͱʹݸผʹࢦఆ͢Δ
    ΋ͷ
    Run Scripts

    View Slide

  6. Xcode Behaviors
    Behaviors͸ϓϩδΣΫτ୯ҐͰ͸

    ͳ͘ɺXcodeͰ։͘͢΂ͯͷϓϩ
    δΣΫτʹରͯ͠ɺ֤छΠϕϯτΛ

    τϦΨʔͱ༷ͨ͠ʑͳઃఆ͕Մೳ

    RunʹShell ScriptΛొ࿥͢Δ͜ͱ
    ͰɺΠϕϯτͷ։࢝ɾ੒ޭɾࣦഊɾ
    ग़ྗͳͲͷλΠϛϯάʹ೚ҙͷॲཧ
    Λ࣮ߦՄೳ Behaviors
    😀

    View Slide

  7. Xcode Behaviors
    ݱঢ়ҎԼͷΠϕϯτΛαϙʔτ

    #VJME
    5FTUJOH
    3VOOJOH
    (16'SBNF$BQUVSF
    4FBSDI
    9DPEF4FSWFS 9DPEFͰαϙʔτऴྃʁ

    $* 9DPEF$MPVE

    'JMF 6OMPDL

    1MBZHSPVOET
    $PSF.- 9DPEF͔Β

    Behaviors

    View Slide

  8. Xcode Behaviors
    Swift Package Managerʹؔ͢Δ

    Πϕϯτ͸αϙʔτ͞Ε͍ͯͳ͍

    ͷ͕࢒೦

    Reset Package Caches

    Resolve Package Versions

    Update to Latest Package Versions

    Behaviors
    🫤

    View Slide

  9. Xcode Behaviors
    Behaviors
    🤔
    Կ͔ʹ࢖͑ͦ͏

    View Slide

  10. XCHook & XCMonitor

    View Slide

  11. XCHook & XCMonitor
    XCHook͸Xcode BehaviorsͷBuildͱTestingΛϑοΫͯ͠ɺ

    ֎෦ΞϓϦʹ௨஌Λૹ৴Ͱ͖ΔΑ͏ʹ͢ΔSwift Package੡ϥΠϒϥϦ
    Swift Packageͱͯ͠ར༻Մೳɿhttps://github.com/kyome22/XCHook
    􀐛
    XcodeͷPreferencesΛॻ͖׵͑ͯɺBehaviorsΠϕϯτʹScriptΛࢦఆ

    ΠϕϯτΛղऍͯ͠৘ใ੔ܗˍ֎෦ΞϓϦʹ޲͚ͯ௨஌ૹ৴

    ௨஌ͷड৴पΓΛ؆୯ʹ͢Δ֎෦ΞϓϦ޲͚ͷAPI

    View Slide

  12. XCHook & XCMonitor
    XCMonitor͸XcodeͷϏϧυͱςετͷΠϕϯτΛ؂ࢹͯ͠

    ϩάΛऩूͰ͖Δϝχϡʔόʔৗறܕπʔϧ
    GitHub͔ΒΞϓϦΛΠϯετʔϧՄೳɿhttps://github.com/kyome22/XCMonitor
    􁓵
    ɹ
    ঢ়ଶΛϦΞϧλΠϜʹ൓ө

    View Slide

  13. XCHook & XCMonitor
    ऴ͓ྃͯ͘͠
    􀐛
    XCHook
    XCMonitor
    Xcode
    XcodeͷPreferencesΛ্ॻ͖ͯ͠

    ScriptΛ֤ΠϕϯτͷRun߲໨ʹࢦఆ͢Δ
    ؀ڥઃఆ͔ΒXCHookΛ༗ޮʹ͢Δ
    ಋೖฤ
    Scriptͷ࣮ߦʹඞཁͳԼ४උΛ͢Δ

    View Slide

  14. XCHook & XCMonitor
    BehaviorsͷΠϕϯτൃՐ
    􀐛
    XCHook
    XCMonitor
    Xcode
    Script͕ΠϕϯτΛղऍͯ͠৘ใΛ੔ܗ
    ৘ใΛ֎෦ΞϓϦʹ௨஌ͱͯ͠ૹ৴
    Xcodeͷىಈঢ়ଶΛ؂ࢹͭͭ͠ɺ௨஌Λৗ࣌଴ػ
    ड৴࣍ୈɺදࣔΛߋ৽ˍΠϕϯτͷϩάΛஷΊΔ
    ར༻ฤ

    View Slide

  15. vs App Sandboxͷน

    View Slide

  16. vs App Sandboxͷน
    XCMonitor
    Xcode
    􀙦
    App Sandbox
    App Sandbox͸ɺΞϓϦ͕ΞΫηεՄೳͳྖҬΛ੍ݶ͢Δ͜ͱͰɺ

    γεςϜͷϦιʔεͱϢʔβʔͷσʔλΛอޢ͢ΔͨΊͷ΋ͷ

    ֎෦ΞϓϦΛૢ࡞ͨ͠Γঢ়ଶΛऔಘ͢Δ͜ͱ͸௨ৗෆՄೳ

    ࣗ࡞ΞϓϦͷ৔߹ɺApp Sandboxͷ༗ޮ/ແޮ͸։ൃऀʹҕͶΒΕ͍ͯΔ

    Xcode͸App Sandboxʹอޢ͞Ε͍ͯΔͨΊɺ֎෦͔ΒΞΫηεͰ͖ͳ͍

    View Slide

  17. vs App Sandboxͷน
    Xcodeଆ͔Β֎෦ΞϓϦʹ޲͚ͯ߹๏తʹσʔλΛૹ৴͢Δ࢓૊Έ͕ඞཁ

    BehaviorsͷRun ScriptͰShell ScriptΛ࣮ߦ

    ͞ΒʹShell Script಺ͰSwiftͷεΫϦϓτΛ࣮ߦ͠

    DistributedNoti
    fi
    cationCenterͰ֎෦ΞϓϦʹ޲͚৘ใΛൃ৴
    XCMonitor
    Xcode
    􀙦
    App Sandbox
    􀐕
    Behaviors
    >_
    Shell Script Swift Script
    􀫊

    View Slide

  18. vs App Sandboxͷน
    XCMonitor
    Xcode
    􀙦
    App Sandbox
    􀐕
    Behaviors
    >_
    Shell Script Swift Script
    􀫊
    ~/.xchook
    BehaviorsͷRun ScriptͰεΫϦϓτΛಈ͔͢৔߹ɺ

    Shell ScriptͱSwiftͷεΫϦϓτʹ͸࣮ߦݖݶΛ෇༩͢Δ chmod 744

    ͜ΕΒͷεΫϦϓτ͸ϗʔϜσΟϨΫτϦ௚Լʹ .xchook σΟϨΫτϦΛ

    ࡞੒ͯͦ͜͠ʹ഑ஔ

    View Slide

  19. vs App Sandboxͷน
    XCMonitor
    Xcode
    􀙦
    App Sandbox Plist App Sandbox
    􀞡
    ಋೖϋʔυϧΛԼ͛ΔͨΊɺBehaviorsͷRun ScriptΛࣗಈͰࢦఆ͢Δ

    ࢓૊Έ͕ཉ͍͠

    Preferencesͷ಺༰͸ ~/Library/Preferences/com.apple.dt.Xcode.plist 

    ʹอଘ͞ΕΔ

    App SandboxΛແޮʹ͢Ε͹ɺ֎෦ΞϓϦ͔ΒϑΝΠϧΛಡΈॻ͖Մೳ

    View Slide

  20. vs App Sandboxͷน
    ಋೖϋʔυϧΛԼ͛ΔͨΊɺBehaviorsͷRun ScriptΛࣗಈͰࢦఆ͢Δ

    ࢓૊Έ͕ཉ͍͠

    Preferencesͷ಺༰͸ ~/Library/Preferences/com.apple.dt.Xcode.plist 

    ʹอଘ͞ΕΔ

    App SandboxΛແޮʹ͢Ε͹ɺ֎෦ΞϓϦ͔ΒϑΝΠϧΛಡΈॻ͖Մೳ
    XCMonitor
    Xcode
    􀙦
    App Sandbox Plist App Sandbox
    􀞡
    Full Access

    View Slide

  21. ϓϩδΣΫτύεͷऔಘ

    View Slide

  22. ϓϩδΣΫτύεͷऔಘ
    ϓϩδΣΫτ໊ͱύεΛޙͰར༻͢ΔͨΊɺRun ScriptͷதͰऔಘ͍ͨ͠

    XcodeͰ։͘ϓϩδΣΫτܗࣜʹ͸ɺXcode Projectʢ .xcodeproj ʣͱ

    Xcode Workspaceʢ .xcworkspace ʣͱ Swift Package ͷ̏छྨ͕͋Δ

    Run ScriptͷதͰར༻Մೳͳ؀ڥม਺Λ׆༻ͯ͠ύεΛղੳ

    View Slide

  23. ϓϩδΣΫτύεͷऔಘ
    Run ScriptΛ࣮ߦͨ͠ࡍͷ؀ڥม਺

    Xcode Projectͷ৔߹
    ؀ڥม਺ ஋
    XcodeProject PROJECT_NAME.xcodeproj
    XcodeProjectPath PROJECT_ROOT/PROJECT_NAME.xcodeproj
    XcodeWorkspacePath PROJECT_ROOT/PROJECT_NAME.xcodeproj/project.xcworkspace
    PWD PROJECT_ROOT
    * PROJECT_ROOT = ϓϩδΣΫτͷϧʔτͷઈରύε


    * PROJECT_NAME = ϓϩδΣΫτ໊

    View Slide

  24. ϓϩδΣΫτύεͷऔಘ
    Run ScriptΛ࣮ߦͨ͠ࡍͷ؀ڥม਺

    Xcode Workspaceͷ৔߹ʢCocoaPodsΛ࢖͍ͬͯΔͳͲʣ
    ؀ڥม਺ ஋
    XcodeWorkspace PROJECT_NAME.xcworkspace
    XcodeWorkspacePath PROJECT_ROOT/PROJECT_NAME.xcworkspace
    PWD PROJECT_ROOT
    * PROJECT_ROOT = ϓϩδΣΫτͷϧʔτͷઈରύε


    * PROJECT_NAME = ϓϩδΣΫτ໊

    View Slide

  25. ϓϩδΣΫτύεͷऔಘ
    Run ScriptΛ࣮ߦͨ͠ࡍͷ؀ڥม਺

    Swift Packageܗࣜͷ৔߹
    ؀ڥม਺ ஋
    XcodeWorkspace package.xcworkspace
    XcodeWorkspacePath PROJECT_ROOT/.swiftpm/xcode/package.xcworkspace
    PWD PROJECT_ROOT/.swiftpm/xcode
    * PROJECT_ROOT = ϓϩδΣΫτͷϧʔτͷઈରύε

    View Slide

  26. ϓϩδΣΫτύεͷऔಘ
    if (؀ڥม਺XcodeProject͕औಘՄೳ) {


    Xcode Project


    } else if (xcworkspaceϑΝΠϧͷ໊લ͕package.xcworkspace) {


    Swift Package


    } else {


    Xcode Workspace


    }
    Run ScriptΛ࣮ߦͨ͠ࡍͷ؀ڥม਺ͷಛ௃

    ؀ڥม਺ XcodeProject ͕औಘͰ͖Δͷ͸Xcode Projectܗࣜͷ৔߹ͷΈ

    Swift Packageܗࣜͷ৔߹ɺxcworkspaceϑΝΠϧͷ໊લ͸

    package.xcworkspace Ͱݻఆ

    View Slide

  27. ϓϩδΣΫτύεͷऔಘ
    ҎԼͷShell ScriptͰϓϩδΣΫτ໊ͱύε͕औಘͰ͖Δ
    #!/bin/sh -


    if [ "$XcodeProject" ]; then


    # Normal Xcode Project


    PROJECT_NAME=`basename "$XcodeProject" .xcodeproj`


    PROJECT_PATH=$XcodeProjectPath


    elif [ "$XcodeWorkspace" = "package.xcworkspace" ]; then


    # Swift Package Library


    PROJECT_NAME=`basename $(dirname "$XcodeWorkspacePath" | sed -r "s/\.swiftpm.+//")`


    PROJECT_PATH=$XcodeWorkspacePath


    else


    # XCWorkspace (Probably using CocoaPods.)


    PROJECT_NAME=`basename "$XcodeWorkspace" .xcworkspace`


    PROJECT_PATH=$XcodeWorkspacePath


    fi
    ࢀরɿhttps://github.com/Kyome22/XCHook/blob/main/Sources/XCHook/run_scripts/build_start.sh

    View Slide

  28. XcodeͷPreferencesΛ


    ॻ͖׵͑Δ

    View Slide

  29. XcodeͷPreferencesΛॻ͖׵͑Δ
    Preferencesͷσʔλ͸ ~/Library/Preferences/com.apple.dt.Xcode.plist ʹ

    อଘ͞Ε͓ͯΓɺ͜ΕʹखΛՃ͑Ε͹ྑ͍

    BinaryܗࣜͷProperty ListͷͨΊɺςΩετΤσΟλͰ։͍ͯ΋ಡΊͳ͍

    XcodeͰ։͘ͱಡΈॻ͖͕Ͱ͖Δ͕ɺ਺ेඵʹҰ౓ͷස౓ͰϦϩʔυ͞Ε

    දࣔߏ଄͕มΘΔͷͰखಈͰฤू͢Δͷ͸ࠔ೉

    ʢࣙॻܕ͸ॱংΛอূ͠ͳ͍ͨΊϩʔυͷͨͼʹॱং͕มΘΓಘΔʣ

    View Slide

  30. XcodeͷPreferencesΛॻ͖׵͑Δ
    {


    "Xcode.AlertEvents.4_1": {


    "Xcode.AlertEvents.BuildStart": {


    "Xcode.Alert.RunScript": {


    "enabled": boolean,


    "path": "Shell Scriptͷύε"


    }


    },


    "Xcode.AlertEvents.TestingSucceeds": {


    "Xcode.Alert.RunScript": {


    "enabled": boolean,


    "path": "Shell Scriptͷύε"


    }


    }


    }


    }
    Plist ͷ಺༰ΛJSONܗࣜͰൈਮͨ͠΋ͷ
    BehaviorsʹRun ScriptΛઃఆ͢Δʹ͸ɺ
    Xcode.AlertEvents ͱ Xcode.AlertEvents.4_1
    ͷ಺༰Λॻ͖׵͑Ε͹ྑ͍

    ྫ͑͹ɺXcode.AlertEvent.BuildStart ͷத
    ͷ Xcode.Alert.RunScript ʹ࣮ߦ͍ͨ͠

    Shell ScriptͷύεΛॻ͖ࠐΉ

    View Slide

  31. XcodeͷPreferencesΛॻ͖׵͑Δ
    {


    "Xcode.AlertEvents.4_1": {


    "Xcode.AlertEvents.BuildStart": {


    "Xcode.Alert.RunScript": {


    "enabled": boolean,


    "path": "Shell Scriptͷύε"


    }


    },


    "Xcode.AlertEvents.TestingSucceeds": {


    "Xcode.Alert.RunScript": {


    "enabled": boolean,


    "path": "Shell Scriptͷύε"


    }


    }


    }


    }
    Plist ͷ಺༰ΛJSONܗࣜͰൈਮͨ͠΋ͷ
    BehaviorsʹRun ScriptΛઃఆ͢Δʹ͸ɺ
    Xcode.AlertEvents ͱ Xcode.AlertEvents.4_1
    ͷ಺༰Λॻ͖׵͑Ε͹ྑ͍

    ྫ͑͹ɺXcode.AlertEvent.BuildStart ͷத
    ͷ Xcode.Alert.RunScript ʹ࣮ߦ͍ͨ͠

    Shell ScriptͷύεΛॻ͖ࠐΉ

    ֊૚ߏ଄ͷਂ͍෦෼ͷॻ͖׵͕͑ඞཁ

    ଞͷ෦෼͸ͦͷ··อ͍ͪͨ

    View Slide

  32. XcodeͷPreferencesΛॻ͖׵͑Δ
    4_1 ͬͯͳΜͩʁ 🧐
    Xcode.AlertEvents ͱ Xcode.AlertEvents.4_1 ͸΄΅ಉ͡σʔλߏ଄͕ͩɺ

    ͓ͦΒ͘໾ׂ͕ҧ͏

    Xcode.AlertEvents.4_1 ͸Ϣʔβʔ͕ࢦఆͨ͠શͯͷઃఆ͕ೖΔͷͰຊମ

    Xcode.AlertEvents ͸4_1ͷόοΫΞοϓʁʢҰ෦ͷઃఆ͚͕ͩೖΔʣ

    View Slide

  33. XcodeͷPreferencesΛॻ͖׵͑Δ
    Command LineͰProperty ListΛॻ͖׵͑Δ৔߹ɺplutil ΍ PlistBuddy Λ

    ࢖༻͢Δ͜ͱ͕ଟ͍

    plutil ͸̍֊૚໨·Ͱ͔͠௚઀ૢ࡞Ͱ͖ͳ͍ 😩 → ࿦֎

    PlistBuddy ͸̎֊૚Ҏ্͋ͬͯ΋ૢ࡞͕Մೳ 😃

    อଘܗ͕ࣜXMLʹͳͬͯ͠·͏ ☹

    ্ॻ͖͍ͨ͠ՕॴͷΈΛॻ͖׵͑ΔΑ͏ͳϚʔδ͕Ͱ͖ͳ͍ 🤯

    ʢ߲̍໨ͣͭͷॻ͖׵͑ͱ·ͩଘࡏ͍ͯ͠ͳ͍σʔλͷ௥Ճ͸Ͱ͖Δʣ

    View Slide

  34. ্ॻ͖͍ͨ͠ՕॴͷΈΛॻ͖׵͑ΔΑ͏ͳϚʔδ͕Ͱ͖ͳ͍ͷҙຯ
    XcodeͷPreferencesΛॻ͖׵͑Δ
    {


    "Apple": {


    "Price": 100,


    "Color": "Green"


    },


    "Banana": {


    "Price": 100,


    "Color": "Yellow"


    },


    "Cherry": {


    "Price": 100,


    "Color": "Red"


    }


    }
    {


    "Apple": {


    "Price": 150


    },


    "Banana": {


    "Price": 150


    },


    "Cherry": {


    "Price": 150


    }


    }
    {


    "Apple": {


    "Price": 150,


    "Color": "Green"


    },


    "Banana": {


    "Price": 150,


    "Color": "Yellow"


    },


    "Cherry": {


    "Price": 150,


    "Color": "Red"


    }


    }
    ΦϦδφϧ ॻ͖׵͍͑ͨ಺༰ ཧ૝ͷϚʔδ݁Ռ

    View Slide

  35. ্ॻ͖͍ͨ͠ՕॴͷΈΛॻ͖׵͑ΔΑ͏ͳϚʔδ͕Ͱ͖ͳ͍ͷҙຯ
    XcodeͷPreferencesΛॻ͖׵͑Δ
    {


    "Apple": {


    "Price": 100,


    "Color": "Green"


    },


    "Banana": {


    "Price": 100,


    "Color": "Yellow"


    },


    "Cherry": {


    "Price": 100,


    "Color": "Red"


    }


    }
    {


    "Apple": {


    "Price": 150


    },


    "Banana": {


    "Price": 150


    },


    "Cherry": {


    "Price": 150


    }


    }
    ΦϦδφϧ ॻ͖׵͍͑ͨ಺༰
    طʹಉ໊ͷΩʔ͕ଘࡏͯ͠

    ͍Δ৔߹Ϛʔδ͕Ͱ͖ͳ͍
    PlistBuddyͰͷϚʔδ݁Ռ

    View Slide

  36. XcodeͷPreferencesΛॻ͖׵͑Δ
    let saveURL = URL(fileURLWithPath: "sample.plist")


    var dict: [String: Any] = [:]


    // dictΛฤूʢதུʣ


    let data = try! PropertyListSerialization.data(fromPropertyList: dict,


    format: .binary,


    options: .zero)


    try! data.write(to: saveURL, options: .atomic)
    طଘͷCommand LineπʔϧΛ࢖ΘͣSwiftͰࣗલ࣮૷͢Δ

    SwiftͰProperty ListΛॻ͖׵͑Δ৔߹ɺPropertyListSerialization Λ࢖͑͹

    BinaryܗࣜͷProperty ListΛฤूՄೳ

    View Slide

  37. ҆શͷͨΊɺProperty Listͷॻ͖׵͑͸Xcodeඇىಈ࣌ʹߦ͏

    Xcodeͷىಈதʹॻ͖׵͑ͯ΋ଈ࣌൓ө͞Εͳ͍

    Ұ౓ऴྃͯ͠࠶ىಈ͢Δͱ൓ө͞ΕΔ
    XcodeͷPreferencesΛॻ͖׵͑Δ

    View Slide

  38. ΠϕϯτͷώετϦʔΛ

    ਖ਼͍͠ॱংͰऔಘ͢Δ

    View Slide

  39. ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    ͍͟ɺXcodeͷΠϕϯτΛ؂ࢹͯ͠ϩάΛऩूͯ͠ΈΔͱɺ

    ͨ·ʹΠϕϯτͷಧ͘ॱং͕લޙͯ͠͠·͏͜ͱʹؾ͍ͮͨ
    􀙄
    􀊄
    Ϗϧυ։࢝
    􀙄
    Ϗϧυ੒ޭ
    􁁛
    ςετ੒ޭ
    􀙄
    􀊄
    Ϗϧυ։࢝
    􀙄
    Ϗϧυ੒ޭ
    􁁛
    ςετ੒ޭ
    ٯॱʹͳ͍ͬͯΔ😫
    ςετ։࢝
    􁁚
    􀊄
    ςετ։࢝
    􁁚
    􀊄

    View Slide

  40. ςετ։࢝
    􁁚
    􀊄
    ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    Run Scriptͷ࣮ߦ͸ΠϕϯτͷൃՐ࣌Ͱ͸͋Δ͕ɺஞ࣍ॲཧͰ͸ͳ͘ฒྻॲཧ
    ͞ΕΔͨΊɺRun Scriptͷ࣮ߦ׬ྃΛ଴ͨͣʹΠϕϯτ͕ਐΉ
    􀙄
    􀊄
    Ϗϧυ։࢝
    ஞ࣍ॲཧͷΠϝʔδ
    􀙄
    Ϗϧυ੒ޭ
    􀙄
    Ϗϧυ
    Run Script A
    >_
    Run Script B
    >_

    View Slide

  41. ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    Run Scriptͷ࣮ߦ͸ΠϕϯτͷൃՐ࣌Ͱ͸͋Δ͕ɺஞ࣍ॲཧͰ͸ͳ͘ฒྻॲཧ
    ͞ΕΔͨΊɺRun Scriptͷ࣮ߦ׬ྃΛ଴ͨͣʹΠϕϯτ͕ਐΉ
    􀙄
    􀊄
    Ϗϧυ։࢝
    􀙄
    Ϗϧυ੒ޭ
    Run Script A
    ςετ։࢝
    􁁚
    􀊄
    􀙄
    Ϗϧυ
    Run Script B
    ฒྻॲཧͷΠϝʔδ
    ࣍ͷॲཧʹॏͳ͍ͬͯΔ

    View Slide

  42. Run Scriptͷ࣮ߦ͸ΠϕϯτͷൃՐ࣌Ͱ͸͋Δ͕ɺஞ࣍ॲཧͰ͸ͳ͘ฒྻॲཧ
    ͞ΕΔͨΊɺRun Scriptͷ࣮ߦ׬ྃΛ଴ͨͣʹΠϕϯτ͕ਐΉ

    ͠͹͠͹Πϕϯτͷॱং͕લޙ͢Δݱ৅͕ى͖ಘΔ

    ʢApple Silicon MacͷϏϧυ͕ߴ଎͗ͯ͢௨஌ॲཧͷํ͕ෛ͚Δʁʣ
    ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    􀙄
    􀊄
    Ϗϧυ։࢝
    􀙄
    Ϗϧυ੒ޭ
    Run Script A
    ςετ։࢝
    􁁚
    􀊄
    􀙄
    Ϗϧυ
    Run Script B ॲཧͷ׬͕ྃٯస

    View Slide

  43. ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    Πϕϯτͷ௨஌ॱংΛอূ͢ΔͨΊɺಧ͍ͨॱ͸৴༻ͤͣɺ

    λΠϜελϯϓΛجʹ౎౓ฒͼସ͑Δ

    ࣮ߦ͢ΔShell Scriptͷ๯಄Ͱ date ίϚϯυΛ࢖ͬͯλΠϜελϯϓΛ

    औಘͯ͠Έͨ

    View Slide

  44. ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    Πϕϯτͷ௨஌ॱংΛอূ͢ΔͨΊɺಧ͍ͨॱ͸৴༻ͤͣɺ

    λΠϜελϯϓΛجʹ౎౓ฒͼସ͑Δ

    ࣮ߦ͢ΔShell Scriptͷ๯಄Ͱ date ίϚϯυΛ࢖ͬͯλΠϜελϯϓΛ

    औಘͯ͠Έͨ

    ҰॠͰϏϧυ͕׬ྃ͢Δ৔߹ɺ໰୊ΛղফͰ͖ͳ͔ͬͨ 😧

    macOS ͷ date ίϚϯυ͸ϛϦඵϨϕϧ·ͰऔಘͰ͖ͳ͍͜ͱ͕൑໌

    View Slide

  45. ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    ϛϦඵϨϕϧͷλΠϜελϯϓΛऔಘ͍ͨ͠

    1. HomebrewͰcoreutilsΛΠϯετʔϧͯ͠ gdate ίϚϯυΛ࢖͏

    XCHook͸Swift PackageϥΠϒϥϦͳͷͰHomebrewʹཔΓͨ͘ͳ͍ 🙅

    View Slide

  46. ϛϦඵϨϕϧͷλΠϜελϯϓΛऔಘ͍ͨ͠

    2. macOSʹϓϦΠϯετʔϧ͞Ε͍ͯΔPerlΛ࢖ͬͯϛϦඵ·Ͱग़ྗ͢Δ

    কདྷతʹPerlɺPythonɺRuby͕macOSͷϓϦΠϯετʔϧର৅͔Β

    ֎ΕΔͱ͍͏࿩͕͋ΔͷͰආ͚͍ͨ 🙅
    ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    ࢀরɿhttps://developer.apple.com/documentation/macos-release-notes/macos-catalina-10_15-

    ɹɹɹrelease-notes#Scripting-Language-Runtims

    View Slide

  47. ϛϦඵϨϕϧͷλΠϜελϯϓΛऔಘ͍ͨ͠

    3. CݴޠͰϛϦඵ·Ͱग़ྗ͢ΔίʔυΛ༻ҙ͓͍ͯͯ͠ɺ

    ؀ڥ͝ͱʹϏϧυ͠ɺ࣮ߦϑΝΠϧΛར༻͢Δ

    CݴޠͳΒϓϦΠϯετʔϧ͔Β֎͞Εͳ͍ʢ͸ͣ

    ࣮֬ʹϛϦඵ·ͰऔಘͰ͖Δ

    ϓϩηοα͕ҟͳΔͱ࣮ߦϑΝΠϧ͕ಈ࡞͠ͳ͍ͨΊಋೖ࣌ʹϏϧυ͢Δ

    ʢApple Silicon MacͰϏϧυ࣮ͨ͠ߦϑΝΠϧ͸Intel MacͰಈ͔ͳ͍ʣ
    ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    👌

    View Slide

  48. ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    func run(_ args: String...) {


    let task = Process()


    task.launchPath = "/bin/sh"


    task.arguments = ["-c", args.joined(separator: " ")]


    task.launch()


    task.waitUntilExit()


    }


    run("gcc", "timestamp.c", "-o", "ts")
    CݴޠͰϛϦඵϨϕϧͷλΠϜελϯϓΛऔಘ͢ΔʢϏϧυฤʣ

    Process() Λ࢖ͬͯSwift͔ΒShellΛୟ͘

    ༻ҙ͓͍ͯͨ͠CݴޠͷίʔυΛ gcc ͰίϯύΠϧ͢Δ

    View Slide

  49. CݴޠͰϛϦඵϨϕϧͷλΠϜελϯϓΛऔಘ͢Δʢ࣮ߦฤʣ

    ίϯύΠϧ࣮ͨ͠ߦϑΝΠϧΛ ~/.xchook ʹஔ͍͓ͯ͘

    Run Scriptͷ࣮ߦ࣌ʹShell Scriptͷ๯಄Ͱ࣮ߦϑΝΠϧΛ࢖͏
    ΠϕϯτͷώετϦʔΛਖ਼͍͠ॱংͰऔಘ͢Δ
    XCMonitor
    Xcode
    􀙦
    App Sandbox
    􀐕
    Behaviors
    >_
    Shell Script Swift Script
    􀫊
    ~/.xchook
    $
    C
    fi
    le
    &

    View Slide

  50. ೚ҙͷϓϩδΣΫτ΢Πϯυ΢Λ

    ࠷લ໘ʹදࣔͤ͞Δ

    View Slide

  51. ೚ҙͷϓϩδΣΫτ΢Πϯυ΢Λ࠷લ໘ʹදࣔͤ͞Δ
    Ϗϧυ͕׬ྃͨ͜͠ͱ΍ςετ͕ऴΘͬͨ͜ͱΛXCMonitorͰ஌ͬͨޙʹ

    ͦͷϓϩδΣΫτͷ΢Πϯυ΢Λ࠷લ໘ʹදࣔͤ͞Δػೳ͕ཉ͘͠ͳͬͨ

    ֎෦ΞϓϦͷ΢Πϯυ΢͸؅׋֎ͷͨΊ௨ৗ͸੍ޚͰ͖ͳ͍

    ʢApp SandboxΛແޮʹͯ͠Accessibility APIΛ࢖ͬͯ΋ͳ͓೉͍͠ʣ

    View Slide

  52. ೚ҙͷϓϩδΣΫτ΢Πϯυ΢Λ࠷લ໘ʹදࣔͤ͞Δ
    Ϗϧυ͕׬ྃͨ͜͠ͱ΍ςετ͕ऴΘͬͨ͜ͱΛXCMonitorͰ஌ͬͨޙʹ

    ͦͷϓϩδΣΫτͷ΢Πϯυ΢Λ࠷લ໘ʹදࣔͤ͞Δػೳ͕ཉ͘͠ͳͬͨ

    ֎෦ΞϓϦͷ΢Πϯυ΢͸؅׋֎ͷͨΊ௨ৗ͸੍ޚͰ͖ͳ͍

    ʢApp SandboxΛແޮʹͯ͠Accessibility APIΛ࢖ͬͯ΋ͳ͓೉͍͠ʣ

    ൃ૝Λม͑ͯɺϓϩδΣΫτϑΝΠϧΛXcodeͰ։͘͜ͱͰ

    ࠷લ໘ʹ΢Πϯυ΢Λදࣔͤ͞Δ͜ͱʹͨ͠

    ʢ೚ҙͷϑΝΠϧΛ೚ҙͷΞϓϦͰ։͘ͷ͸App Sandbox؀ڥͰ΋Մೳ)

    View Slide

  53. ೚ҙͷϓϩδΣΫτ΢Πϯυ΢Λ࠷લ໘ʹදࣔͤ͞Δ
    ϓϩδΣΫτϑΝΠϧΛXcodeͰ։͘

    NSWorkspace.shared.openApplication(at:con
    fi
    guration:) Ͱ͸

    XcodeΛ։͚ͩ͘Ͱ೚ҙͷϑΝΠϧ͸։͚ͳ͍

    NSWorkspace.shared.open(_:withApplicationAt:con
    fi
    guration:) Ͱ

    ϑΝΠϧͷύεͱΞϓϦͷύε૒ํΛࢦఆͯ͠։͘

    ͜ͷ࣌ͷͨΊʹRun ScriptͰϓϩδΣΫτϑΝΠϧͷύεΛऔಘ͍ͯͨ͠

    View Slide

  54. Run Scriptͷσόοάํ๏

    View Slide

  55. Run Scriptͷσόοάํ๏
    BehaviorsͷRun Scriptʹ͓͍ͯඪ४ग़ྗ͸֬ೝͷํ๏͕ͳ͍

    cat ΍ echo ίϚϯυɺSwift.print() Λ࢖ͬͯ΋֬ೝͰ͖Δ৔ॴʹग़ྗ͞Εͳ͍

    Console.appͰϩάϝοηʔδΛ֬ೝ͢Δ

    Shell ScriptͰ͸ logger -s Λ࢖͏

    SwiftͷεΫϦϓτͰ͸ NSLog() Λ࢖͏
    Console.app

    View Slide

  56. Run Scriptͷσόοάํ๏
    Console.appͰϩάϝοηʔδΛ֬ೝ͢Δ ֆจࣈΛ࢖͏ͱߜΓࠐΈ΍͍͢😋

    View Slide

  57. ·ͱΊ
    XcodeͷϏϧυͱςετͷΠϕϯτΛϑοΫͯ͠௨஌͢Δ࢓૊ΈΛ

    Swift PackageͰ࡞ͬͨΑʙ

    👆ͷσϞΞϓϦͱͯ͠ϏϧυͱςετͷϩάΛ؂ࢹ͢Δ

    ϝχϡʔόʔৗறܕΞϓϦΛ࡞ͬͯ഑෍͍ͯ͠ΔΑʙ

    App SandboxͷนΛճආͨ͠ΓɺProperty ListΛॻ͖׵͑ͨΓɺ

    ΠϕϯτऔಘͷॱংΛอূ͢ΔͷʹςΫχοΫ͕ඞཁͩͬͨΑʙ
    Thank you!

    View Slide