Skip to content

Commit b05b3ca

Browse files
committed
Workaround mingw-gcc LTO ICE by re-adding some dead code...
Not my finest work, but without that code removed in godotengine#102179, mingw-gcc 14.2.1 on Fedora 41 (but also confirmed with versions on macOS and WSL) crashes when linking with LTO. We need to dig deeper to understand the bug, report it upstream and work it around in a cleaner way. But for now this unblocks building Windows binaries with LTO, and should be harmless.
1 parent f0f5319 commit b05b3ca

File tree

2 files changed

+239
-0
lines changed

2 files changed

+239
-0
lines changed

platform/ios/export/export_plugin.cpp

+237
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,167 @@ struct ExportLibsData {
12561256
String dest_dir;
12571257
};
12581258

1259+
bool EditorExportPlatformIOS::_archive_has_arm64(const String &p_path, uint32_t *r_cputype, uint32_t *r_cpusubtype) const {
1260+
bool has_arm64_image = false;
1261+
if (FileAccess::exists(p_path)) {
1262+
if (LipO::is_lipo(p_path)) {
1263+
// LipO.
1264+
Ref<LipO> lipo;
1265+
lipo.instantiate();
1266+
if (lipo->open_file(p_path)) {
1267+
for (int i = 0; i < lipo->get_arch_count(); i++) {
1268+
if (lipo->get_arch_cputype(i) == 0x100000c && lipo->get_arch_cpusubtype(i) == 0) {
1269+
has_arm64_image = true;
1270+
break;
1271+
}
1272+
}
1273+
}
1274+
lipo->close();
1275+
} else {
1276+
// Single architecture archive.
1277+
Ref<FileAccess> sim_f = FileAccess::open(p_path, FileAccess::READ);
1278+
if (sim_f.is_valid()) {
1279+
char magic[9] = {};
1280+
sim_f->get_buffer((uint8_t *)&magic[0], 8);
1281+
if (String(magic) == String("!<arch>\n")) {
1282+
while (!sim_f->eof_reached()) {
1283+
// Read file metadata.
1284+
char name_short[17] = {};
1285+
char size_short[11] = {};
1286+
sim_f->get_buffer((uint8_t *)&name_short[0], 16);
1287+
sim_f->seek(sim_f->get_position() + 12 + 6 + 6 + 8); // Skip modification time, owner ID, group ID, file mode.
1288+
sim_f->get_buffer((uint8_t *)&size_short[0], 10);
1289+
sim_f->seek(sim_f->get_position() + 2); // Skip end marker.
1290+
1291+
int64_t file_size = String(size_short).to_int();
1292+
int64_t next_off = sim_f->get_position() + file_size;
1293+
1294+
String name = String(name_short); // Skip extended name.
1295+
if (name.is_empty() || file_size == 0) {
1296+
break;
1297+
}
1298+
if (name.begins_with("#1/")) {
1299+
int64_t name_len = String(name_short).replace("#1/", "").to_int();
1300+
sim_f->seek(sim_f->get_position() + name_len);
1301+
}
1302+
1303+
// Read file content.
1304+
uint32_t obj_magic = sim_f->get_32();
1305+
1306+
bool swap = (obj_magic == 0xcffaedfe || obj_magic == 0xcefaedfe);
1307+
if (obj_magic == 0xcefaedfe || obj_magic == 0xfeedface || obj_magic == 0xcffaedfe || obj_magic == 0xfeedfacf) {
1308+
uint32_t cputype = sim_f->get_32();
1309+
uint32_t cpusubtype = sim_f->get_32();
1310+
if (swap) {
1311+
cputype = BSWAP32(cputype);
1312+
cpusubtype = BSWAP32(cpusubtype);
1313+
}
1314+
if (r_cputype) {
1315+
*r_cputype = cputype;
1316+
}
1317+
if (r_cpusubtype) {
1318+
*r_cpusubtype = cpusubtype;
1319+
}
1320+
if (cputype == 0x100000c && cpusubtype == 0) {
1321+
has_arm64_image = true;
1322+
}
1323+
break;
1324+
}
1325+
sim_f->seek(next_off);
1326+
}
1327+
}
1328+
sim_f->close();
1329+
}
1330+
}
1331+
}
1332+
return has_arm64_image;
1333+
}
1334+
1335+
int EditorExportPlatformIOS::_archive_convert_to_simulator(const String &p_path) const {
1336+
int commands_patched = 0;
1337+
Ref<FileAccess> sim_f = FileAccess::open(p_path, FileAccess::READ_WRITE);
1338+
if (sim_f.is_valid()) {
1339+
char magic[9] = {};
1340+
sim_f->get_buffer((uint8_t *)&magic[0], 8);
1341+
if (String(magic) == String("!<arch>\n")) {
1342+
while (!sim_f->eof_reached()) {
1343+
// Read file metadata.
1344+
char name_short[17] = {};
1345+
char size_short[11] = {};
1346+
sim_f->get_buffer((uint8_t *)&name_short[0], 16);
1347+
sim_f->seek(sim_f->get_position() + 12 + 6 + 6 + 8); // Skip modification time, owner ID, group ID, file mode.
1348+
sim_f->get_buffer((uint8_t *)&size_short[0], 10);
1349+
sim_f->seek(sim_f->get_position() + 2); // Skip end marker.
1350+
1351+
int64_t file_size = String(size_short).to_int();
1352+
int64_t next_off = sim_f->get_position() + file_size;
1353+
1354+
String name = String(name_short); // Skip extended name.
1355+
if (name.is_empty() || file_size == 0) {
1356+
break;
1357+
}
1358+
if (name.begins_with("#1/")) {
1359+
int64_t name_len = String(name_short).replace("#1/", "").to_int();
1360+
sim_f->seek(sim_f->get_position() + name_len);
1361+
}
1362+
1363+
// Read file content.
1364+
uint32_t obj_magic = sim_f->get_32();
1365+
1366+
bool swap = (obj_magic == 0xcffaedfe || obj_magic == 0xcefaedfe);
1367+
if (obj_magic == 0xcefaedfe || obj_magic == 0xfeedface || obj_magic == 0xcffaedfe || obj_magic == 0xfeedfacf) {
1368+
uint32_t cputype = sim_f->get_32();
1369+
uint32_t cpusubtype = sim_f->get_32();
1370+
uint32_t filetype = sim_f->get_32();
1371+
uint32_t ncmds = sim_f->get_32();
1372+
sim_f->get_32(); // Commands total size.
1373+
sim_f->get_32(); // Commands flags.
1374+
if (obj_magic == 0xcffaedfe || obj_magic == 0xfeedfacf) {
1375+
sim_f->get_32(); // Reserved, 64-bit only.
1376+
}
1377+
if (swap) {
1378+
ncmds = BSWAP32(ncmds);
1379+
cputype = BSWAP32(cputype);
1380+
cpusubtype = BSWAP32(cpusubtype);
1381+
filetype = BSWAP32(filetype);
1382+
}
1383+
if (cputype == 0x100000C && cpusubtype == 0 && filetype == 1) {
1384+
// ARM64, object file.
1385+
for (uint32_t i = 0; i < ncmds; i++) {
1386+
int64_t cmdofs = sim_f->get_position();
1387+
uint32_t cmdid = sim_f->get_32();
1388+
uint32_t cmdsize = sim_f->get_32();
1389+
if (swap) {
1390+
cmdid = BSWAP32(cmdid);
1391+
cmdsize = BSWAP32(cmdsize);
1392+
}
1393+
if (cmdid == MachO::LoadCommandID::LC_BUILD_VERSION) {
1394+
int64_t platform = sim_f->get_32();
1395+
if (swap) {
1396+
platform = BSWAP32(platform);
1397+
}
1398+
if (platform == MachO::PlatformID::PLATFORM_IOS) {
1399+
sim_f->seek(cmdofs + 4 + 4);
1400+
uint32_t new_id = MachO::PlatformID::PLATFORM_IOSSIMULATOR;
1401+
if (swap) {
1402+
new_id = BSWAP32(new_id);
1403+
}
1404+
sim_f->store_32(new_id);
1405+
commands_patched++;
1406+
}
1407+
}
1408+
sim_f->seek(cmdofs + cmdsize);
1409+
}
1410+
}
1411+
}
1412+
sim_f->seek(next_off);
1413+
}
1414+
}
1415+
sim_f->close();
1416+
}
1417+
return commands_patched;
1418+
}
1419+
12591420
void EditorExportPlatformIOS::_check_xcframework_content(const String &p_path, int &r_total_libs, int &r_static_libs, int &r_dylibs, int &r_frameworks) const {
12601421
Ref<PList> plist;
12611422
plist.instantiate();
@@ -2260,6 +2421,82 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
22602421
return ERR_FILE_NOT_FOUND;
22612422
}
22622423

2424+
// HACK: We don't want to run the simulator library generation code anymore after GH-102179, but removing it
2425+
// triggers an internal compiler error with latest mingw-gcc... For now we bring it back as a workaround
2426+
// with a condition that should never be true (that project setting doesn't exist).
2427+
2428+
// Check and generate missing ARM64 simulator library.
2429+
if (ProjectSettings::get_singleton()->has_setting("ios_generate_simulator_library_if_missing")) {
2430+
String sim_lib_path = dest_dir + String(binary_name + ".xcframework").path_join("ios-arm64_x86_64-simulator").path_join("libgodot.a");
2431+
String dev_lib_path = dest_dir + String(binary_name + ".xcframework").path_join("ios-arm64").path_join("libgodot.a");
2432+
String tmp_lib_path = EditorPaths::get_singleton()->get_temp_dir().path_join(binary_name + "_lipo_");
2433+
uint32_t cputype = 0;
2434+
uint32_t cpusubtype = 0;
2435+
if (!_archive_has_arm64(sim_lib_path, &cputype, &cpusubtype) && _archive_has_arm64(dev_lib_path) && FileAccess::exists(dev_lib_path)) {
2436+
add_message(EXPORT_MESSAGE_INFO, TTR("Export"), TTR("ARM64 simulator library, generating from device library."));
2437+
2438+
Vector<String> tmp_lib_files;
2439+
Vector<Vector2i> tmp_lib_cputypes;
2440+
// Extract/copy simulator lib.
2441+
if (FileAccess::exists(sim_lib_path)) {
2442+
if (LipO::is_lipo(sim_lib_path)) {
2443+
Ref<LipO> lipo;
2444+
lipo.instantiate();
2445+
if (lipo->open_file(sim_lib_path)) {
2446+
for (int i = 0; i < lipo->get_arch_count(); i++) {
2447+
const String &f_name = tmp_lib_path + itos(tmp_lib_files.size());
2448+
lipo->extract_arch(i, f_name);
2449+
tmp_lib_files.push_back(f_name);
2450+
tmp_lib_cputypes.push_back(Vector2i(lipo->get_arch_cputype(i), lipo->get_arch_cpusubtype(i)));
2451+
}
2452+
}
2453+
} else {
2454+
const String &f_name = tmp_lib_path + itos(tmp_lib_files.size());
2455+
tmp_app_path->copy(sim_lib_path, f_name);
2456+
tmp_lib_files.push_back(f_name);
2457+
tmp_lib_cputypes.push_back(Vector2i(cputype, cpusubtype));
2458+
}
2459+
}
2460+
// Copy device lib.
2461+
if (LipO::is_lipo(dev_lib_path)) {
2462+
Ref<LipO> lipo;
2463+
lipo.instantiate();
2464+
if (lipo->open_file(dev_lib_path)) {
2465+
for (int i = 0; i < lipo->get_arch_count(); i++) {
2466+
if (lipo->get_arch_cputype(i) == 0x100000c && lipo->get_arch_cpusubtype(i) == 0) {
2467+
const String &f_name = tmp_lib_path + itos(tmp_lib_files.size());
2468+
lipo->extract_arch(i, f_name);
2469+
tmp_lib_files.push_back(f_name);
2470+
tmp_lib_cputypes.push_back(Vector2i(0x100000c, 0)); // ARM64.
2471+
break;
2472+
}
2473+
}
2474+
}
2475+
} else {
2476+
const String &f_name = tmp_lib_path + itos(tmp_lib_files.size());
2477+
tmp_app_path->copy(dev_lib_path, f_name);
2478+
tmp_lib_files.push_back(f_name);
2479+
tmp_lib_cputypes.push_back(Vector2i(0x100000c, 0)); // ARM64.
2480+
}
2481+
2482+
// Patch device lib.
2483+
int patch_count = _archive_convert_to_simulator(tmp_lib_path + itos(tmp_lib_files.size() - 1));
2484+
if (patch_count == 0) {
2485+
add_message(EXPORT_MESSAGE_WARNING, TTR("Export"), TTR("Unable to generate ARM64 simulator library."));
2486+
} else {
2487+
// Repack.
2488+
Ref<LipO> lipo;
2489+
lipo.instantiate();
2490+
lipo->create_file(sim_lib_path, tmp_lib_files, tmp_lib_cputypes);
2491+
}
2492+
2493+
// Cleanup.
2494+
for (const String &E : tmp_lib_files) {
2495+
tmp_app_path->remove(E);
2496+
}
2497+
}
2498+
}
2499+
22632500
// Generate translations files.
22642501

22652502
Dictionary appnames = GLOBAL_GET("application/config/name_localized");

platform/ios/export/export_plugin.h

+2
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
136136
Vector<ExportArchitecture> _get_supported_architectures() const;
137137
Vector<String> _get_preset_architectures(const Ref<EditorExportPreset> &p_preset) const;
138138

139+
bool _archive_has_arm64(const String &p_path, uint32_t *r_cputype = nullptr, uint32_t *r_cpusubtype = nullptr) const;
140+
int _archive_convert_to_simulator(const String &p_path) const;
139141
void _check_xcframework_content(const String &p_path, int &r_total_libs, int &r_static_libs, int &r_dylibs, int &r_frameworks) const;
140142
Error _convert_to_framework(const String &p_source, const String &p_destination, const String &p_id) const;
141143

0 commit comments

Comments
 (0)