Skip to content

Commit 4c5a1d9

Browse files
msanderstaku0
authored andcommitted
Add support for running on device via ios-deploy
1 parent dca378a commit 4c5a1d9

File tree

1 file changed

+180
-106
lines changed

1 file changed

+180
-106
lines changed

swift-mode-repl.el

Lines changed: 180 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ The string is splitted by spaces, then unquoted."
7474
:group 'swift-mode:repl
7575
:safe 'stringp)
7676

77+
(defcustom swift-mode:ios-deploy-executable
78+
"ios-deploy"
79+
"Path to ios-deploy command.
80+
The string is splitted by spaces, then unquoted."
81+
:type '(choice string (list string))
82+
:group 'swift-mode:repl
83+
:safe 'stringp)
84+
7785
(defcustom swift-mode:simulator-controller-executable
7886
"xcrun simctl"
7987
"Path to the simulator controller command.
@@ -116,8 +124,12 @@ cdr is used as a command. If its car is a function, it is called to search
116124
prompt. It should return non-nil when a prompt is found and return nil
117125
otherwise.")
118126

119-
(defvar swift-mode:ios-simulator-device-identifier nil
120-
"Device identifier of iOS simulator for building/debugging.")
127+
(defvar swift-mode:ios-device-identifier nil
128+
"Identifier of iOS device used for building/debugging.")
129+
130+
(defconst swift-mode:ios-local-device-identifier
131+
"00000000-0000-0000-0000-000000000000"
132+
"Identifier of local iOS device.")
121133

122134
(defvar swift-mode:ios-project-scheme nil
123135
"Scheme to use in Xcode project for building/debugging.")
@@ -412,33 +424,48 @@ or its ancestors."
412424
flattened)))
413425
available-devices))
414426

415-
(defun swift-mode:read-ios-simulator-device-identifier ()
427+
(defun swift-mode:read-ios-device-identifier ()
416428
"Read a iOS simulator device identifier from the minibuffer."
417429
(let* ((devices (swift-mode:list-ios-simulator-devices))
418-
(items (seq-map
419-
(lambda (device)
420-
(cons (cdr (assoc 'name device))
421-
(cdr (assoc 'udid device))))
422-
devices)))
430+
(items (append (list (cons "Local device"
431+
swift-mode:ios-local-device-identifier))
432+
(seq-map
433+
(lambda (device)
434+
(cons (cdr (assoc 'name device))
435+
(cdr (assoc 'udid device))))
436+
devices))))
423437
(widget-choose "Choose a device" items)))
424438

425439
(defun swift-mode:read-xcode-build-settings (project-directory
426-
device-identifier
427-
scheme)
440+
scheme
441+
sdk
442+
device-identifier)
428443
"Read Xcode build settings in PROJECT-DIRECTORY.
429444
430-
DEVICE-IDENTIFIER is used as the destination parameter for xcodebuild.
431-
SCHEME is the name of the project scheme in Xcode."
445+
SCHEME is the name of the project scheme in Xcode.
446+
SDK is the name of the SDK build against.
447+
DEVICE-IDENTIFIER is used as the destination parameter for xcodebuild. If
448+
identifier is equal to `swift-mode:ios-local-device-identifier', it is not
449+
passed as a destination to xcodebuild."
432450
(with-temp-buffer
433-
(let ((default-directory project-directory))
434-
(unless (zerop (swift-mode:call-process
435-
swift-mode:xcodebuild-executable
436-
"-configuration" "Debug"
437-
"-destination"
438-
(concat "platform=iOS Simulator,id=" device-identifier)
439-
"-sdk" "iphonesimulator"
440-
"-scheme" scheme
441-
"-showBuildSettings"))
451+
(let ((default-directory project-directory)
452+
(arglist `(,swift-mode:xcodebuild-executable
453+
"-configuration"
454+
"Debug"
455+
"-sdk"
456+
,sdk
457+
"-scheme"
458+
,scheme
459+
"-showBuildSettings")))
460+
(when (and device-identifier
461+
(not (eql device-identifier
462+
swift-mode:ios-local-device-identifier)))
463+
(setq arglist
464+
(append arglist
465+
`("-destination"
466+
,(concat "platform=iOS Simulator,id=" device-identifier)
467+
))))
468+
(unless (zerop (apply #'swift-mode:call-process arglist))
442469
(error "%s %s" "Cannot read Xcode build settings" (buffer-string))))
443470
(goto-char (point-min))
444471
(let ((settings nil))
@@ -524,12 +551,11 @@ An list ARGS are appended for builder command line arguments."
524551
device-identifier
525552
scheme)
526553
"Build an iOS app in the PROJECT-DIRECTORY.
527-
528-
Build it for iOS simulator device DEVICE-IDENTIFIER for the given SCHEME.
554+
Build it for iOS device DEVICE-IDENTIFIER for the given SCHEME.
529555
If PROJECT-DIRECTORY is nil or omitted, it is searched from `default-directory'
530556
or its ancestors.
531557
DEVICE-IDENTIFIER is the device identifier of the iOS simulator. If it is nil
532-
or omitted, the value of `swift-mode:ios-simulator-device-identifier' is used.
558+
or omitted, the value of `swift-mode:ios-device-identifier' is used.
533559
SCHEME is the name of the project scheme in Xcode. If it is nil or omitted,
534560
the value of `swift-mode:ios-project-scheme' is used."
535561
(interactive
@@ -539,8 +565,8 @@ the value of `swift-mode:ios-project-scheme' is used."
539565
(list
540566
project-directory
541567
(if current-prefix-arg
542-
(swift-mode:read-ios-simulator-device-identifier)
543-
swift-mode:ios-simulator-device-identifier)
568+
(swift-mode:read-ios-device-identifier)
569+
swift-mode:ios-device-identifier)
544570
(if current-prefix-arg
545571
(swift-mode:read-project-scheme project-directory)
546572
swift-mode:ios-project-scheme))))
@@ -549,9 +575,9 @@ the value of `swift-mode:ios-project-scheme' is used."
549575
(unless device-identifier
550576
(setq device-identifier
551577
(or
552-
swift-mode:ios-simulator-device-identifier
553-
(swift-mode:read-ios-simulator-device-identifier))))
554-
(setq swift-mode:ios-simulator-device-identifier device-identifier)
578+
swift-mode:ios-device-identifier
579+
(swift-mode:read-ios-device-identifier))))
580+
(setq swift-mode:ios-device-identifier device-identifier)
555581
(unless scheme
556582
(setq scheme
557583
(or
@@ -562,17 +588,21 @@ the value of `swift-mode:ios-project-scheme' is used."
562588
(with-current-buffer (get-buffer-create "*swift-mode:compilation*")
563589
(fundamental-mode)
564590
(setq buffer-read-only nil)
565-
(let ((progress-reporter (make-progress-reporter "Building...")))
566-
(unless
591+
(let ((progress-reporter (make-progress-reporter "Building..."))
592+
(xcodebuild-args `(,swift-mode:xcodebuild-executable
593+
"-configuration" "Debug"
594+
"-scheme" ,scheme)))
595+
(if (eql device-identifier swift-mode:ios-local-device-identifier)
596+
(setq xcodebuild-args (append xcodebuild-args '("-sdk" "iphoneos")))
597+
(setq xcodebuild-args
598+
(append xcodebuild-args
599+
`("-destination"
600+
,(concat "platform=iOS Simulator,id=" device-identifier)
601+
"-sdk" "iphonesimulator"))))
602+
(unless
567603
(zerop
568604
(let ((default-directory project-directory))
569-
(swift-mode:call-process
570-
swift-mode:xcodebuild-executable
571-
"-configuration" "Debug"
572-
"-scheme" scheme
573-
"-destination"
574-
(concat "platform=iOS Simulator,id=" device-identifier)
575-
"-sdk" "iphonesimulator")))
605+
(apply 'swift-mode:call-process xcodebuild-args)))
576606
(compilation-mode)
577607
(goto-char (point-min))
578608
(pop-to-buffer (current-buffer))
@@ -751,17 +781,104 @@ PROCESS-IDENTIFIER is the process ID."
751781
(goto-char comint-last-input-end)
752782
(search-forward expected-output nil t)))
753783

784+
;;;###autoload
785+
(defun swift-mode:debug-ios-app-on-device (project-directory
786+
scheme
787+
codesigning-folder-path)
788+
"Run debugger on an iOS app in the PROJECT-DIRECTORY.
789+
Run it for the iOS local device DEVICE-IDENTIFIER for the given SCHEME.
790+
CODESIGNING-FOLDER-PATH is the path of the codesigning folder in Xcode
791+
build settings."
792+
(swift-mode:build-ios-app project-directory
793+
swift-mode:ios-local-device-identifier
794+
scheme)
795+
(swift-mode:run-repl
796+
(append
797+
(swift-mode:command-string-to-list swift-mode:ios-deploy-executable)
798+
(list "--debug" "--no-wifi" "--bundle" codesigning-folder-path))
799+
nil t))
800+
801+
;;;###autoload
802+
(defun swift-mode:debug-ios-app-on-simulator (project-directory
803+
device-identifier
804+
scheme
805+
codesigning-folder-path
806+
product-bundle-identifier)
807+
"Run debugger on an iOS app in the PROJECT-DIRECTORY.
808+
Run it for the iOS simulator DEVICE-IDENTIFIER for the given SCHEME.
809+
DEVICE-IDENTIFIER is the device identifier of the iOS simulator.
810+
SCHEME is the name of the project scheme in Xcode.
811+
CODESIGNING-FOLDER-PATH is the path of the codesigning folder used in Xcode
812+
build settings.
813+
PRODUCT-BUNDLE-IDENTIFIER is the name of the product bundle identifier used
814+
in Xcode build settings."
815+
(swift-mode:build-ios-app project-directory device-identifier scheme)
816+
(let* ((devices (swift-mode:list-ios-simulator-devices))
817+
(target-device
818+
(seq-find
819+
(lambda (device)
820+
(string-equal (cdr (assoc 'udid device)) device-identifier))
821+
devices))
822+
(active-devices
823+
(seq-filter
824+
(lambda (device)
825+
(string-equal (cdr (assoc 'state device)) "Booted"))
826+
devices))
827+
(target-booted
828+
(string-equal (cdr (assoc 'state target-device)) "Booted"))
829+
(simulator-running (consp active-devices))
830+
(progress-reporter
831+
(make-progress-reporter "Waiting for simulator...")))
832+
(cond
833+
(target-booted
834+
;; The target device is already booted. Does nothing.
835+
t)
836+
(simulator-running
837+
(swift-mode:kill-ios-simulator)
838+
(swift-mode:open-ios-simulator device-identifier))
839+
(t (swift-mode:open-ios-simulator device-identifier)))
840+
841+
(swift-mode:wait-for-ios-simulator device-identifier)
842+
843+
(progress-reporter-done progress-reporter)
844+
845+
(let ((progress-reporter (make-progress-reporter "Installing app...")))
846+
(swift-mode:install-ios-app device-identifier codesigning-folder-path)
847+
(progress-reporter-done progress-reporter))
848+
849+
(let ((progress-reporter (make-progress-reporter "Launching app..."))
850+
(process-identifier
851+
(swift-mode:launch-ios-app
852+
device-identifier product-bundle-identifier t)))
853+
(progress-reporter-done progress-reporter)
854+
(swift-mode:run-repl
855+
(append
856+
(swift-mode:command-string-to-list swift-mode:debugger-executable)
857+
(list "--" codesigning-folder-path))
858+
nil t)
859+
(swift-mode:enqueue-repl-commands
860+
"platform select ios-simulator"
861+
(concat "platform connect " device-identifier)
862+
(concat "process attach --pid " (number-to-string process-identifier))
863+
"breakpoint set --one-shot true --name UIApplicationMain"
864+
"cont"
865+
(cons
866+
(lambda (_string)
867+
(swift-mode:search-process-stopped-message process-identifier))
868+
"repl")))))
869+
754870
;;;###autoload
755871
(defun swift-mode:debug-ios-app (&optional project-directory
756872
device-identifier
757873
scheme)
758874
"Run debugger on an iOS app in the PROJECT-DIRECTORY.
759-
760-
Run it for iOS simulator device DEVICE-IDENTIFIER for the given SCHEME.
875+
Run it for the iOS simulator devie DEVICE-IDENTIFIER for the given SCHEME.
761876
If PROJECT-DIRECTORY is nil or omitted, it is searched from `default-directory'
762877
or its ancestors.
763-
DEVICE-IDENTIFIER is the device identifier of the iOS simulator. If it is nil
764-
or omitted, the value of `swift-mode:ios-simulator-device-identifier' is used.
878+
DEVICE-IDENTIFIER is the device identifier of the iOS simulator. If it is
879+
nil or omitted, the value of `swift-mode:ios-device-identifier' is used. If
880+
it is equal to `swift-mode:ios-local-device-identifier', a local build via
881+
`ios-deploy' is generated instead.
765882
SCHEME is the name of the project scheme in Xcode. If it is nil or omitted,
766883
the value of `swift-mode:ios-project-scheme' is used."
767884
(interactive
@@ -771,8 +888,8 @@ the value of `swift-mode:ios-project-scheme' is used."
771888
(list
772889
project-directory
773890
(if current-prefix-arg
774-
(swift-mode:read-ios-simulator-device-identifier)
775-
swift-mode:ios-simulator-device-identifier)
891+
(swift-mode:read-ios-device-identifier)
892+
swift-mode:ios-device-identifier)
776893
(if current-prefix-arg
777894
(swift-mode:read-project-scheme project-directory)
778895
swift-mode:ios-project-scheme))))
@@ -781,20 +898,24 @@ the value of `swift-mode:ios-project-scheme' is used."
781898
(unless device-identifier
782899
(setq device-identifier
783900
(or
784-
swift-mode:ios-simulator-device-identifier
785-
(swift-mode:read-ios-simulator-device-identifier))))
786-
(setq swift-mode:ios-simulator-device-identifier device-identifier)
901+
swift-mode:ios-device-identifier
902+
(swift-mode:read-ios-device-identifier))))
903+
(setq swift-mode:ios-device-identifier device-identifier)
787904
(unless scheme
788905
(setq scheme
789906
(or
790907
swift-mode:ios-project-scheme
791908
(swift-mode:read-project-scheme project-directory))))
792909
(setq swift-mode:ios-project-scheme scheme)
793-
(let* ((build-settings
910+
(let* ((local-device-build (eql device-identifier
911+
swift-mode:ios-local-device-identifier))
912+
(sdk (if local-device-build "iphoneos" "iphonesimulator"))
913+
(build-settings
794914
(swift-mode:read-xcode-build-settings
795915
project-directory
796-
device-identifier
797-
scheme))
916+
scheme
917+
sdk
918+
device-identifier))
798919
(codesigning-folder-path
799920
(cdr (assoc "CODESIGNING_FOLDER_PATH" build-settings)))
800921
(product-bundle-identifier
@@ -803,63 +924,16 @@ the value of `swift-mode:ios-project-scheme' is used."
803924
(error "Cannot get codesigning folder path"))
804925
(unless product-bundle-identifier
805926
(error "Cannot get product bundle identifier"))
806-
(swift-mode:build-ios-app project-directory
807-
device-identifier
808-
scheme)
809-
810-
(let* ((devices (swift-mode:list-ios-simulator-devices))
811-
(target-device
812-
(seq-find
813-
(lambda (device)
814-
(string-equal (cdr (assoc 'udid device)) device-identifier))
815-
devices))
816-
(active-devices
817-
(seq-filter
818-
(lambda (device)
819-
(string-equal (cdr (assoc 'state device)) "Booted"))
820-
devices))
821-
(target-booted
822-
(string-equal (cdr (assoc 'state target-device)) "Booted"))
823-
(simulator-running (consp active-devices))
824-
(progress-reporter
825-
(make-progress-reporter "Waiting for simulator...")))
826-
(cond
827-
(target-booted
828-
;; The target device is already booted. Does nothing.
829-
t)
830-
(simulator-running
831-
(swift-mode:kill-ios-simulator)
832-
(swift-mode:open-ios-simulator device-identifier))
833-
(t (swift-mode:open-ios-simulator device-identifier)))
834-
835-
(swift-mode:wait-for-ios-simulator device-identifier)
836-
837-
(progress-reporter-done progress-reporter)
838927

839-
(let ((progress-reporter (make-progress-reporter "Installing app...")))
840-
(swift-mode:install-ios-app device-identifier codesigning-folder-path)
841-
(progress-reporter-done progress-reporter))
842-
843-
(let ((progress-reporter (make-progress-reporter "Launching app..."))
844-
(process-identifier
845-
(swift-mode:launch-ios-app
846-
device-identifier product-bundle-identifier t)))
847-
(progress-reporter-done progress-reporter)
848-
(swift-mode:run-repl
849-
(append
850-
(swift-mode:command-string-to-list swift-mode:debugger-executable)
851-
(list "--" codesigning-folder-path))
852-
nil t)
853-
(swift-mode:enqueue-repl-commands
854-
"platform select ios-simulator"
855-
(concat "platform connect " device-identifier)
856-
(concat "process attach --pid " (number-to-string process-identifier))
857-
"breakpoint set --one-shot true --name UIApplicationMain"
858-
"cont"
859-
(cons
860-
(lambda (_string)
861-
(swift-mode:search-process-stopped-message process-identifier))
862-
"repl"))))))
928+
(if local-device-build
929+
(swift-mode:debug-ios-app-on-device project-directory
930+
scheme
931+
codesigning-folder-path)
932+
(swift-mode:debug-ios-app-on-simulator project-directory
933+
device-identifier
934+
scheme
935+
codesigning-folder-path
936+
product-bundle-identifier))))
863937

864938
(provide 'swift-mode-repl)
865939

0 commit comments

Comments
 (0)