You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-11 13:10:58 +00:00
[iOS one-click] Add support for Xcode 15 devicectl.
(cherry picked from commit 33ce138b9b)
This commit is contained in:
@@ -1493,7 +1493,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
|
|||||||
return _export_project_helper(p_preset, p_debug, p_path, p_flags, false, false);
|
return _export_project_helper(p_preset, p_debug, p_path, p_flags, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags, bool p_simulator, bool p_skip_ipa) {
|
Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags, bool p_simulator, bool p_oneclick) {
|
||||||
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
|
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
|
||||||
|
|
||||||
String src_pkg_name;
|
String src_pkg_name;
|
||||||
@@ -1501,6 +1501,9 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
|
|||||||
String binary_name = p_path.get_file().get_basename();
|
String binary_name = p_path.get_file().get_basename();
|
||||||
|
|
||||||
bool export_project_only = p_preset->get("application/export_project_only");
|
bool export_project_only = p_preset->get("application/export_project_only");
|
||||||
|
if (p_oneclick) {
|
||||||
|
export_project_only = false; // Skip for one-click deploy.
|
||||||
|
}
|
||||||
|
|
||||||
EditorProgress ep("export", export_project_only ? TTR("Exporting for iOS (Project Files Only)") : TTR("Exporting for iOS"), export_project_only ? 2 : 5, true);
|
EditorProgress ep("export", export_project_only ? TTR("Exporting for iOS (Project Files Only)") : TTR("Exporting for iOS"), export_project_only ? 2 : 5, true);
|
||||||
|
|
||||||
@@ -1904,7 +1907,7 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
|
|||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_skip_ipa) {
|
if (!p_oneclick) {
|
||||||
if (ep.step("Making .ipa", 4)) {
|
if (ep.step("Making .ipa", 4)) {
|
||||||
return ERR_SKIP;
|
return ERR_SKIP;
|
||||||
}
|
}
|
||||||
@@ -2118,12 +2121,9 @@ void EditorExportPlatformIOS::_check_for_changes_poll_thread(void *ud) {
|
|||||||
// Check for devices updates.
|
// Check for devices updates.
|
||||||
Vector<Device> ldevices;
|
Vector<Device> ldevices;
|
||||||
|
|
||||||
// Enum real devices.
|
// Enum real devices (via ios_deploy, pre Xcode 15).
|
||||||
String idepl = EDITOR_GET("export/ios/ios_deploy");
|
String idepl = EDITOR_GET("export/ios/ios_deploy");
|
||||||
if (idepl.is_empty()) {
|
if (!idepl.is_empty()) {
|
||||||
idepl = "ios-deploy";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
String devices;
|
String devices;
|
||||||
List<String> args;
|
List<String> args;
|
||||||
args.push_back("-c");
|
args.push_back("-c");
|
||||||
@@ -2149,8 +2149,9 @@ void EditorExportPlatformIOS::_check_for_changes_poll_thread(void *ud) {
|
|||||||
Dictionary device_info = device_event["Device"];
|
Dictionary device_info = device_event["Device"];
|
||||||
Device nd;
|
Device nd;
|
||||||
nd.id = device_info["DeviceIdentifier"];
|
nd.id = device_info["DeviceIdentifier"];
|
||||||
nd.name = device_info["DeviceName"].operator String() + " (connected through " + device_event["Interface"].operator String() + ")";
|
nd.name = device_info["DeviceName"].operator String() + " (ios_deploy, " + ((device_event["Interface"] == "WIFI") ? "network" : "wired") + ")";
|
||||||
nd.wifi = device_event["Interface"] == "WIFI";
|
nd.wifi = device_event["Interface"] == "WIFI";
|
||||||
|
nd.use_ios_deploy = true;
|
||||||
nd.simulator = false;
|
nd.simulator = false;
|
||||||
ldevices.push_back(nd);
|
ldevices.push_back(nd);
|
||||||
}
|
}
|
||||||
@@ -2159,8 +2160,46 @@ void EditorExportPlatformIOS::_check_for_changes_poll_thread(void *ud) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enum simulators
|
// Enum simulators.
|
||||||
if (_check_xcode_install() && (FileAccess::exists("/usr/bin/xcrun") || FileAccess::exists("/bin/xcrun"))) {
|
if (_check_xcode_install() && (FileAccess::exists("/usr/bin/xcrun") || FileAccess::exists("/bin/xcrun"))) {
|
||||||
|
{
|
||||||
|
String devices;
|
||||||
|
List<String> args;
|
||||||
|
args.push_back("devicectl");
|
||||||
|
args.push_back("list");
|
||||||
|
args.push_back("devices");
|
||||||
|
args.push_back("-j");
|
||||||
|
args.push_back("-");
|
||||||
|
args.push_back("-q");
|
||||||
|
int ec = 0;
|
||||||
|
Error err = OS::get_singleton()->execute("xcrun", args, &devices, &ec, true);
|
||||||
|
if (err == OK && ec == 0) {
|
||||||
|
Ref<JSON> json;
|
||||||
|
json.instantiate();
|
||||||
|
err = json->parse(devices);
|
||||||
|
if (err == OK) {
|
||||||
|
const Dictionary &data = json->get_data();
|
||||||
|
const Dictionary &result = data["result"];
|
||||||
|
const Array &devices = result["devices"];
|
||||||
|
for (int i = 0; i < devices.size(); i++) {
|
||||||
|
const Dictionary &device_info = devices[i];
|
||||||
|
const Dictionary &conn_props = device_info["connectionProperties"];
|
||||||
|
const Dictionary &dev_props = device_info["deviceProperties"];
|
||||||
|
if (conn_props["pairingState"] == "paired" && dev_props["developerModeStatus"] == "enabled") {
|
||||||
|
Device nd;
|
||||||
|
nd.id = device_info["identifier"];
|
||||||
|
nd.name = dev_props["name"].operator String() + " (devicectl, " + ((conn_props["transportType"] == "localNetwork") ? "network" : "wired") + ")";
|
||||||
|
nd.wifi = conn_props["transportType"] == "localNetwork";
|
||||||
|
nd.simulator = false;
|
||||||
|
ldevices.push_back(nd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enum simulators.
|
||||||
|
{
|
||||||
String devices;
|
String devices;
|
||||||
List<String> args;
|
List<String> args;
|
||||||
args.push_back("simctl");
|
args.push_back("simctl");
|
||||||
@@ -2175,12 +2214,12 @@ void EditorExportPlatformIOS::_check_for_changes_poll_thread(void *ud) {
|
|||||||
json.instantiate();
|
json.instantiate();
|
||||||
err = json->parse(devices);
|
err = json->parse(devices);
|
||||||
if (err == OK) {
|
if (err == OK) {
|
||||||
Dictionary data = json->get_data();
|
const Dictionary &data = json->get_data();
|
||||||
Dictionary devices = data["devices"];
|
const Dictionary &devices = data["devices"];
|
||||||
for (const Variant *key = devices.next(nullptr); key; key = devices.next(key)) {
|
for (const Variant *key = devices.next(nullptr); key; key = devices.next(key)) {
|
||||||
Array os_devices = devices[*key];
|
const Array &os_devices = devices[*key];
|
||||||
for (int i = 0; i < os_devices.size(); i++) {
|
for (int i = 0; i < os_devices.size(); i++) {
|
||||||
Dictionary device_info = os_devices[i];
|
const Dictionary &device_info = os_devices[i];
|
||||||
if (device_info["isAvailable"].operator bool() && device_info["state"] == "Booted") {
|
if (device_info["isAvailable"].operator bool() && device_info["state"] == "Booted") {
|
||||||
Device nd;
|
Device nd;
|
||||||
nd.id = device_info["udid"];
|
nd.id = device_info["udid"];
|
||||||
@@ -2193,6 +2232,7 @@ void EditorExportPlatformIOS::_check_for_changes_poll_thread(void *ud) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update device list.
|
// Update device list.
|
||||||
{
|
{
|
||||||
@@ -2352,6 +2392,7 @@ Error EditorExportPlatformIOS::run(const Ref<EditorExportPreset> &p_preset, int
|
|||||||
List<String> args;
|
List<String> args;
|
||||||
args.push_back("simctl");
|
args.push_back("simctl");
|
||||||
args.push_back("launch");
|
args.push_back("launch");
|
||||||
|
args.push_back("--terminate-running-process");
|
||||||
args.push_back(dev.id);
|
args.push_back(dev.id);
|
||||||
args.push_back(p_preset->get("application/bundle_identifier"));
|
args.push_back(p_preset->get("application/bundle_identifier"));
|
||||||
for (const String &E : cmd_args_list) {
|
for (const String &E : cmd_args_list) {
|
||||||
@@ -2370,8 +2411,8 @@ Error EditorExportPlatformIOS::run(const Ref<EditorExportPreset> &p_preset, int
|
|||||||
add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Running failed, see editor log for details."));
|
add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Running failed, see editor log for details."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (dev.use_ios_deploy) {
|
||||||
// Deploy and run on real device.
|
// Deploy and run on real device (via ios-deploy).
|
||||||
if (ep.step("Installing and running on device...", 4)) {
|
if (ep.step("Installing and running on device...", 4)) {
|
||||||
CLEANUP_AND_RETURN(ERR_SKIP);
|
CLEANUP_AND_RETURN(ERR_SKIP);
|
||||||
} else {
|
} else {
|
||||||
@@ -2409,6 +2450,62 @@ Error EditorExportPlatformIOS::run(const Ref<EditorExportPreset> &p_preset, int
|
|||||||
CLEANUP_AND_RETURN(ERR_UNCONFIGURED);
|
CLEANUP_AND_RETURN(ERR_UNCONFIGURED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Deploy and run on real device.
|
||||||
|
if (ep.step("Installing to device...", 3)) {
|
||||||
|
CLEANUP_AND_RETURN(ERR_SKIP);
|
||||||
|
} else {
|
||||||
|
List<String> args;
|
||||||
|
args.push_back("devicectl");
|
||||||
|
args.push_back("device");
|
||||||
|
args.push_back("install");
|
||||||
|
args.push_back("app");
|
||||||
|
args.push_back("-d");
|
||||||
|
args.push_back(dev.id);
|
||||||
|
args.push_back(EditorPaths::get_singleton()->get_cache_dir().path_join(id).path_join("export.xcarchive/Products/Applications/export.app"));
|
||||||
|
|
||||||
|
String log;
|
||||||
|
int ec;
|
||||||
|
err = OS::get_singleton()->execute("xcrun", args, &log, &ec, true);
|
||||||
|
if (err != OK) {
|
||||||
|
add_message(EXPORT_MESSAGE_WARNING, TTR("Run"), TTR("Could not start device executable."));
|
||||||
|
CLEANUP_AND_RETURN(err);
|
||||||
|
}
|
||||||
|
if (ec != 0) {
|
||||||
|
print_line("device install:\n" + log);
|
||||||
|
add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Installation failed, see editor log for details."));
|
||||||
|
CLEANUP_AND_RETURN(ERR_UNCONFIGURED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ep.step("Running on device...", 4)) {
|
||||||
|
CLEANUP_AND_RETURN(ERR_SKIP);
|
||||||
|
} else {
|
||||||
|
List<String> args;
|
||||||
|
args.push_back("devicectl");
|
||||||
|
args.push_back("device");
|
||||||
|
args.push_back("process");
|
||||||
|
args.push_back("launch");
|
||||||
|
args.push_back("--terminate-existing");
|
||||||
|
args.push_back("-d");
|
||||||
|
args.push_back(dev.id);
|
||||||
|
args.push_back(p_preset->get("application/bundle_identifier"));
|
||||||
|
for (const String &E : cmd_args_list) {
|
||||||
|
args.push_back(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
String log;
|
||||||
|
int ec;
|
||||||
|
err = OS::get_singleton()->execute("xcrun", args, &log, &ec, true);
|
||||||
|
if (err != OK) {
|
||||||
|
add_message(EXPORT_MESSAGE_WARNING, TTR("Run"), TTR("Could not start devicectl executable."));
|
||||||
|
CLEANUP_AND_RETURN(err);
|
||||||
|
}
|
||||||
|
if (ec != 0) {
|
||||||
|
print_line("devicectl launch:\n" + log);
|
||||||
|
add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Running failed, see editor log for details."));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CLEANUP_AND_RETURN(OK);
|
CLEANUP_AND_RETURN(OK);
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
|
|||||||
String name;
|
String name;
|
||||||
bool simulator = false;
|
bool simulator = false;
|
||||||
bool wifi = false;
|
bool wifi = false;
|
||||||
|
bool use_ios_deploy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector<Device> devices;
|
Vector<Device> devices;
|
||||||
@@ -139,7 +140,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
|
|||||||
Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets);
|
Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets);
|
||||||
Error _export_ios_plugins(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector<IOSExportAsset> &r_exported_assets, bool p_debug);
|
Error _export_ios_plugins(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector<IOSExportAsset> &r_exported_assets, bool p_debug);
|
||||||
|
|
||||||
Error _export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags, bool p_simulator, bool p_skip_ipa);
|
Error _export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags, bool p_simulator, bool p_oneclick);
|
||||||
|
|
||||||
bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const;
|
bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user