Skip to content

Commit c272051

Browse files
authored
fix: ios17/xcode 15 changes (#81)
1 parent a8b3bde commit c272051

File tree

6 files changed

+207
-45
lines changed

6 files changed

+207
-45
lines changed

IOSDeviceLib.xcodeproj/project.pbxproj

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
709A6CD21E435D11006F76C7 /* Printing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 709A6CCE1E435D11006F76C7 /* Printing.cpp */; };
2222
709A6CD31E435D11006F76C7 /* windows_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 709A6CD01E435D11006F76C7 /* windows_impl.cpp */; };
2323
70DFE7601E72ACCC000317B3 /* ServerHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70DFE75E1E72ACCC000317B3 /* ServerHelper.cpp */; };
24+
71538F602AC374AF00AF6E91 /* DevicectlHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71538F5E2AC374AF00AF6E91 /* DevicectlHelper.cpp */; };
2425
E0F67C12232591AE00D3E0C2 /* SetTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E0F67C11232591AE00D3E0C2 /* SetTimeout.cpp */; };
2526
/* End PBXBuildFile section */
2627

@@ -338,6 +339,8 @@
338339
70DFE75F1E72ACCC000317B3 /* ServerHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerHelper.h; sourceTree = "<group>"; };
339340
70F5F4281E13EE02005196BF /* configuration.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = configuration.xcconfig; path = IOSDeviceLib/configuration.xcconfig; sourceTree = "<group>"; };
340341
70F6ADAB1DEEB71300DD4722 /* ios-device-lib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ios-device-lib"; sourceTree = BUILT_PRODUCTS_DIR; };
342+
71538F5E2AC374AF00AF6E91 /* DevicectlHelper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DevicectlHelper.cpp; sourceTree = "<group>"; };
343+
71538F5F2AC374AF00AF6E91 /* DevicectlHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DevicectlHelper.h; sourceTree = "<group>"; };
341344
E0F67C102325919600D3E0C2 /* SetTimeout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SetTimeout.h; sourceTree = "<group>"; };
342345
E0F67C11232591AE00D3E0C2 /* SetTimeout.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SetTimeout.cpp; sourceTree = "<group>"; };
343346
/* End PBXFileReference section */
@@ -384,6 +387,8 @@
384387
2E98D5F9251CFE3B00C833E5 /* SocketIncludes.h */,
385388
E0F67C102325919600D3E0C2 /* SetTimeout.h */,
386389
E0F67C11232591AE00D3E0C2 /* SetTimeout.cpp */,
390+
71538F5E2AC374AF00AF6E91 /* DevicectlHelper.cpp */,
391+
71538F5F2AC374AF00AF6E91 /* DevicectlHelper.h */,
387392
);
388393
path = IOSDeviceLib;
389394
sourceTree = "<group>";
@@ -1192,6 +1197,7 @@
11921197
7038CB3E1DEEDB4C00A3D335 /* PlistDate.cpp in Sources */,
11931198
709A6CD31E435D11006F76C7 /* windows_impl.cpp in Sources */,
11941199
70DFE7601E72ACCC000317B3 /* ServerHelper.cpp in Sources */,
1200+
71538F602AC374AF00AF6E91 /* DevicectlHelper.cpp in Sources */,
11951201
7038CB3D1DEEDB4C00A3D335 /* Plist.cpp in Sources */,
11961202
709A6CD21E435D11006F76C7 /* Printing.cpp in Sources */,
11971203
7024956F1E4080B8009A6EBF /* GDBHelper.cpp in Sources */,

IOSDeviceLib/CommonFunctions.h

+4
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,7 @@ std::string get_device_property_value(std::string &device_identifier,
2222
int start_session(std::string &device_identifier);
2323
void stop_session(std::string &device_identifier);
2424
CFStringRef create_CFString(const char *str);
25+
26+
int get_product_version(std::string &device_identifier);
27+
std::string exec(const char *cmd);
28+
int get_xcode_major_version();

IOSDeviceLib/DevicectlHelper.cpp

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "DevicectlHelper.h"
2+
#include "FileHelper.h"
3+
#include "json.hpp"
4+
#include "CommonFunctions.h"
5+
#include <fstream>
6+
#include "Constants.h"
7+
8+
using json = nlohmann::json;
9+
10+
11+
json run_devicectl(std::string command){
12+
char templatea[] = "/tmp/mytempfile-XXXXXX";
13+
char* tempFileDir = mkdtemp(templatea);
14+
std::string outputFile = std::string(tempFileDir) + "tempFileName";
15+
std::string commandWithJson = command + " --quiet --json-output "+outputFile;
16+
std::string cmdResult = exec(commandWithJson.c_str());
17+
FileInfo result = get_file_info(outputFile, true);
18+
std::remove(outputFile.c_str());
19+
if(result.size > 0){
20+
std::string jsonString(result.contents.begin(), result.contents.end());
21+
json jsonResult = json::parse(jsonString);
22+
return jsonResult;
23+
}
24+
nlohmann::json exception;
25+
exception[kError][kCode] = -1;
26+
return exception;
27+
}
28+
29+
bool json_ok(json message){
30+
if(message.find(kError) != message.end()){
31+
return false;
32+
}
33+
return true;
34+
}
35+
bool devicectl_signal_application(int signal, int pid, std::string &device_identifier) {
36+
37+
std::string command = "xcrun devicectl device process signal --device " + device_identifier + " --pid " + std::to_string(pid) + " --signal " +std::to_string(signal);
38+
39+
json result = run_devicectl(command);
40+
if(!json_ok(result)) {
41+
json error = result.value(kError, json());
42+
int errorValue = error.value(kCode, -1);
43+
if(errorValue != 3){
44+
return false;
45+
}
46+
}
47+
return true;
48+
}
49+
bool devicectl_stop_application(std::string &executable, std::string &device_identifier) {
50+
51+
std::string command = "xcrun devicectl device info processes --device " + device_identifier + " --filter \"executable.path == '"+ executable + "'\"";
52+
53+
json result = run_devicectl(command);
54+
if(json_ok(result)){
55+
json actualResult = result.value("result", json());
56+
json pids = actualResult.value("runningProcesses", json::array());
57+
if(pids.size()>0){
58+
json matchingApp = pids.at(0);
59+
int pid = matchingApp.value("processIdentifier", -1);
60+
if(!devicectl_signal_application(3, pid, device_identifier)){
61+
return false;
62+
}
63+
}
64+
}
65+
return true;
66+
}
67+
68+
69+
bool devicectl_start_application(std::string &bundle_id, std::string &device_identifier, bool wait_for_debugger) {
70+
71+
std::string command = "xcrun devicectl device process launch --device " + device_identifier + " --terminate-existing " + bundle_id + (wait_for_debugger?" --start-stopped":"");
72+
73+
json result = run_devicectl(command);
74+
if(json_ok(result)){
75+
return true;
76+
}
77+
return false;
78+
}

IOSDeviceLib/DevicectlHelper.h

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
#include "Declarations.h"
3+
4+
bool devicectl_stop_application(std::string &executable, std::string &device_identifier);
5+
bool devicectl_start_application(std::string &bundle_id, std::string &device_identifier, bool wait_for_debugger);

IOSDeviceLib/IOSDeviceLib.cpp

+94-45
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <thread>
1212

1313
#include "CommonFunctions.h"
14+
#include "DevicectlHelper.h"
15+
1416
#include "Constants.h"
1517
#include "Declarations.h"
1618
#include "FileHelper.h"
@@ -530,6 +532,7 @@ ServiceInfo start_debug_server(std::string device_identifier, std::string ddi,
530532
method_id, false, false);
531533

532534
#ifndef _WIN32
535+
533536
// mount_image is not available on Windows
534537
if (!info.socket && mount_image(device_identifier, ddi, method_id)) {
535538
info = start_secure_service(device_identifier, kNewDebugServer, method_id,
@@ -1425,6 +1428,23 @@ bool validate_device_id_and_attrs(const json &j, std::string method_id,
14251428
return true;
14261429
}
14271430

1431+
bool check_xcode_major_version(int version, std::string device_identifier, std::string method_id){
1432+
#ifdef _WIN32
1433+
print_error("Not supported on windows", device_identifier, method_id,
1434+
kApplicationsCustomError);
1435+
return false;
1436+
#else
1437+
if(get_xcode_major_version()>=version){
1438+
return true;
1439+
} else {
1440+
std::string message = "Xcode version of at least " + std::to_string(version) + " is required";
1441+
print_error(message.c_str(), device_identifier, method_id,
1442+
kApplicationsCustomError);
1443+
return false;
1444+
}
1445+
#endif
1446+
}
1447+
14281448
void stop_app(std::string device_identifier, std::string application_identifier,
14291449
std::string ddi, std::string method_id) {
14301450
if (!devices.count(device_identifier)) {
@@ -1434,37 +1454,54 @@ void stop_app(std::string device_identifier, std::string application_identifier,
14341454
}
14351455

14361456
std::map<std::string, std::map<std::string, std::string>> map;
1437-
if (get_all_apps(device_identifier, map)) {
1438-
if (map.count(application_identifier) == 0) {
1439-
print_error("Application not installed", device_identifier, method_id,
1440-
kApplicationsCustomError);
1441-
return;
1442-
}
1443-
1444-
long service_count = devices[device_identifier].services.size();
1445-
ServiceInfo gdb = start_debug_server(device_identifier, ddi, method_id);
1446-
if (!gdb.socket) {
1447-
print_error("Unable to start gdb server", device_identifier, method_id,
1448-
kUnexpectedError);
1449-
return;
1457+
if (get_all_apps(device_identifier, map)) {
1458+
if (map.count(application_identifier) == 0) {
1459+
print_error("Application not installed", device_identifier, method_id,
1460+
kApplicationsCustomError);
1461+
return;
1462+
}
1463+
if(get_product_version(device_identifier) < 17){
1464+
long service_count = devices[device_identifier].services.size();
1465+
ServiceInfo gdb = start_debug_server(device_identifier, ddi, method_id);
1466+
if (!gdb.socket) {
1467+
print_error("Unable to start gdb server", device_identifier, method_id,
1468+
kUnexpectedError);
1469+
return;
1470+
}
1471+
1472+
std::string executable = map[application_identifier][kPathPascalCase];
1473+
if (devices[device_identifier].services.size() == service_count ||
1474+
stop_application(executable, gdb, application_identifier,
1475+
devices[device_identifier].apps_cache))
1476+
print(json({{kResponse, "Successfully stopped application"},
1477+
{kId, method_id},
1478+
{kDeviceId, device_identifier}}));
1479+
else
1480+
print_error("Could not stop application", device_identifier, method_id,
1481+
kApplicationsCustomError);
1482+
1483+
detach_connection(gdb, &devices[device_identifier]);
1484+
} else {
1485+
if(check_xcode_major_version(15, device_identifier, method_id)){
1486+
std::string executable = map[application_identifier][kPathPascalCase];
1487+
std::string CFBundleExecutableString =map[application_identifier]["CFBundleExecutable"];
1488+
1489+
std::string fullPidPath =executable + "/" + CFBundleExecutableString;
1490+
if(devicectl_stop_application(fullPidPath, device_identifier)){
1491+
1492+
print(json({{kResponse, "Successfully stopped application"},
1493+
{kId, method_id},
1494+
{kDeviceId, device_identifier}}));
1495+
} else {
1496+
print_error("Could not stop application", device_identifier, method_id,
1497+
kApplicationsCustomError);
1498+
}
1499+
}
1500+
}
1501+
} else {
1502+
print_error("Lookup applications failed", device_identifier, method_id,
1503+
kApplicationsCustomError);
14501504
}
1451-
1452-
std::string executable = map[application_identifier][kPathPascalCase];
1453-
if (devices[device_identifier].services.size() == service_count ||
1454-
stop_application(executable, gdb, application_identifier,
1455-
devices[device_identifier].apps_cache))
1456-
print(json({{kResponse, "Successfully stopped application"},
1457-
{kId, method_id},
1458-
{kDeviceId, device_identifier}}));
1459-
else
1460-
print_error("Could not stop application", device_identifier, method_id,
1461-
kApplicationsCustomError);
1462-
1463-
detach_connection(gdb, &devices[device_identifier]);
1464-
} else {
1465-
print_error("Lookup applications failed", device_identifier, method_id,
1466-
kApplicationsCustomError);
1467-
}
14681505
}
14691506

14701507
void start_app(std::string device_identifier,
@@ -1483,23 +1520,34 @@ void start_app(std::string device_identifier,
14831520
kApplicationsCustomError);
14841521
return;
14851522
}
1486-
1487-
ServiceInfo gdb = start_debug_server(device_identifier, ddi, method_id);
1488-
if (!gdb.socket) {
1489-
return;
1490-
}
1491-
1492-
std::string executable = map[application_identifier][kPathPascalCase] +
1493-
"/" +
1494-
map[application_identifier]["CFBundleExecutable"];
1495-
if (run_application(executable, gdb, application_identifier,
1496-
&devices[device_identifier], wait_for_debugger))
1497-
print(json({{kResponse, "Successfully started application"},
1523+
if(get_product_version(device_identifier) < 17){
1524+
ServiceInfo gdb = start_debug_server(device_identifier, ddi, method_id);
1525+
if (!gdb.socket) {
1526+
return;
1527+
}
1528+
1529+
std::string executable = map[application_identifier][kPathPascalCase] +
1530+
"/" +
1531+
map[application_identifier]["CFBundleExecutable"];
1532+
if (run_application(executable, gdb, application_identifier,
1533+
&devices[device_identifier], wait_for_debugger))
1534+
print(json({{kResponse, "Successfully started application"},
14981535
{kId, method_id},
14991536
{kDeviceId, device_identifier}}));
1500-
else
1501-
print_error("Could not start application", device_identifier, method_id,
1502-
kApplicationsCustomError);
1537+
else
1538+
print_error("Could not start application", device_identifier, method_id,
1539+
kApplicationsCustomError);
1540+
} else {
1541+
if(check_xcode_major_version(15, device_identifier, method_id)){
1542+
if(devicectl_start_application(application_identifier, device_identifier, wait_for_debugger))
1543+
print(json({{kResponse, "Successfully started application"},
1544+
{kId, method_id},
1545+
{kDeviceId, device_identifier}}));
1546+
else
1547+
print_error("Could not start application", device_identifier, method_id,
1548+
kApplicationsCustomError);
1549+
}
1550+
}
15031551
} else {
15041552
print_error("Lookup applications failed", device_identifier, method_id,
15051553
kApplicationsCustomError);
@@ -1576,6 +1624,7 @@ void connect_to_port(std::string device_identifier, int port,
15761624
}
15771625
}
15781626

1627+
15791628
int main() {
15801629
#ifdef _WIN32
15811630
_setmode(_fileno(stdout), _O_BINARY);

IOSDeviceLib/mac_impl.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "dirent.h"
77
#include <array>
88
#include <map>
9+
#include <regex>
910

1011
extern std::map<std::string, DeviceData> devices;
1112

@@ -24,6 +25,25 @@ std::string exec(const char *cmd) {
2425
return result;
2526
}
2627

28+
int get_product_version(std::string &device_identifier){
29+
std::string product_version =
30+
get_device_property_value(device_identifier, kProductVersion);
31+
return std::stoi(product_version);
32+
}
33+
34+
int get_xcode_major_version(){
35+
std::string cmd_result = exec("xcodebuild -version");
36+
if(cmd_result.length()>0){
37+
std::regex versionRegex("Xcode (\\d+)");
38+
std::smatch match;
39+
if (std::regex_search(cmd_result, match, versionRegex)) {
40+
std::string xcodeVersion = match[1].str();
41+
return std::stoi(xcodeVersion);
42+
}
43+
}
44+
return -1;
45+
}
46+
2747
std::string
2848
get_developer_disk_image_directory_path(std::string &device_identifier) {
2949
if (!devices.count(device_identifier)) {

0 commit comments

Comments
 (0)