Skip to content

Commit

Permalink
[iOS export] Automatically generate ARM64 simulator library from devi…
Browse files Browse the repository at this point in the history
…ce library if it's missing.
  • Loading branch information
bruvzg committed Jun 16, 2024
1 parent 71699e0 commit 501c15c
Show file tree
Hide file tree
Showing 10 changed files with 385 additions and 16 deletions.
File renamed without changes.
6 changes: 3 additions & 3 deletions platform/macos/export/codesign.h → editor/export/codesign.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef MACOS_CODESIGN_H
#define MACOS_CODESIGN_H
#ifndef CODESIGN_H
#define CODESIGN_H

// macOS code signature creation utility.
//
Expand Down Expand Up @@ -364,4 +364,4 @@ class CodeSign {

#endif // MODULE_REGEX_ENABLED

#endif // MACOS_CODESIGN_H
#endif // CODESIGN_H
108 changes: 107 additions & 1 deletion platform/macos/export/lipo.cpp → editor/export/lipo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ bool LipO::is_lipo(const String &p_path) {
return (magic == 0xbebafeca || magic == 0xcafebabe || magic == 0xbfbafeca || magic == 0xcafebabf);
}

bool LipO::create_file(const String &p_output_path, const PackedStringArray &p_files) {
bool LipO::create_file(const String &p_output_path, const Vector<String> &p_files) {
close();

fa = FileAccess::open(p_output_path, FileAccess::WRITE);
Expand Down Expand Up @@ -125,6 +125,100 @@ bool LipO::create_file(const String &p_output_path, const PackedStringArray &p_f
return true;
}

bool LipO::create_file(const String &p_output_path, const Vector<String> &p_files, const Vector<Vector2i> &p_cputypes) {
close();

fa = FileAccess::open(p_output_path, FileAccess::WRITE);
ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("LipO: Can't open file: \"%s\".", p_output_path));
ERR_FAIL_COND_V(p_files.size() != p_cputypes.size(), false);

uint64_t max_size = 0;
for (int i = 0; i < p_files.size(); i++) {
Ref<FileAccess> fb = FileAccess::open(p_files[i], FileAccess::READ);
if (fb.is_null()) {
close();
ERR_FAIL_V_MSG(false, vformat("LipO: Can't open file: \"%s\".", p_files[i]));
}

{
FatArch arch;
MachO mh;
if (MachO::is_macho(p_files[i]) && mh.open_file(p_files[i])) {
arch.cputype = mh.get_cputype();
arch.cpusubtype = mh.get_cpusubtype();
arch.offset = 0;
arch.size = mh.get_size();
arch.align = mh.get_align();
ERR_FAIL_V_MSG(arch.cputype != (uint32_t)p_cputypes[i].x || arch.cpusubtype != (uint32_t)p_cputypes[i].y, vformat("Mismatching MachO architecture: \"%s\".", p_files[i]));
} else {
arch.cputype = (uint32_t)p_cputypes[i].x;
arch.cpusubtype = (uint32_t)p_cputypes[i].y;
arch.offset = 0;
arch.size = fb->get_length();
arch.align = 0x03;
}
max_size += arch.size;

archs.push_back(arch);
}
}

// Write header.
bool is_64 = (max_size >= std::numeric_limits<uint32_t>::max());
if (is_64) {
fa->store_32(0xbfbafeca);
} else {
fa->store_32(0xbebafeca);
}
fa->store_32(BSWAP32(archs.size()));
uint64_t offset = archs.size() * (is_64 ? 32 : 20) + 8;
for (int i = 0; i < archs.size(); i++) {
archs.write[i].offset = offset + PAD(offset, uint64_t(1) << archs[i].align);
if (is_64) {
fa->store_32(BSWAP32(archs[i].cputype));
fa->store_32(BSWAP32(archs[i].cpusubtype));
fa->store_64(BSWAP64(archs[i].offset));
fa->store_64(BSWAP64(archs[i].size));
fa->store_32(BSWAP32(archs[i].align));
fa->store_32(0);
} else {
fa->store_32(BSWAP32(archs[i].cputype));
fa->store_32(BSWAP32(archs[i].cpusubtype));
fa->store_32(BSWAP32(archs[i].offset));
fa->store_32(BSWAP32(archs[i].size));
fa->store_32(BSWAP32(archs[i].align));
}
offset = archs[i].offset + archs[i].size;
}

// Write files and padding.
for (int i = 0; i < archs.size(); i++) {
Ref<FileAccess> fb = FileAccess::open(p_files[i], FileAccess::READ);
if (fb.is_null()) {
close();
ERR_FAIL_V_MSG(false, vformat("LipO: Can't open file: \"%s\".", p_files[i]));
}
uint64_t cur = fa->get_position();
for (uint64_t j = cur; j < archs[i].offset; j++) {
fa->store_8(0);
}
int pages = archs[i].size / 4096;
int remain = archs[i].size % 4096;
unsigned char step[4096];
for (int j = 0; j < pages; j++) {
uint64_t br = fb->get_buffer(step, 4096);
if (br > 0) {
fa->store_buffer(step, br);
}
}
uint64_t br = fb->get_buffer(step, remain);
if (br > 0) {
fa->store_buffer(step, br);
}
}
return true;
}

bool LipO::open_file(const String &p_path) {
close();

Expand Down Expand Up @@ -198,6 +292,18 @@ int LipO::get_arch_count() const {
return archs.size();
}

uint32_t LipO::get_arch_cputype(int p_index) const {
ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "LipO: File not opened.");
ERR_FAIL_INDEX_V(p_index, archs.size(), 0);
return archs[p_index].cputype;
}

uint32_t LipO::get_arch_cpusubtype(int p_index) const {
ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "LipO: File not opened.");
ERR_FAIL_INDEX_V(p_index, archs.size(), 0);
return archs[p_index].cpusubtype;
}

bool LipO::extract_arch(int p_index, const String &p_path) {
ERR_FAIL_COND_V_MSG(fa.is_null(), false, "LipO: File not opened.");
ERR_FAIL_INDEX_V(p_index, archs.size(), false);
Expand Down
11 changes: 7 additions & 4 deletions platform/macos/export/lipo.h → editor/export/lipo.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef MACOS_LIPO_H
#define MACOS_LIPO_H
#ifndef LIPO_H
#define LIPO_H

// Universal / Universal 2 fat binary file creator and extractor.

Expand Down Expand Up @@ -57,15 +57,18 @@ class LipO : public RefCounted {
public:
static bool is_lipo(const String &p_path);

bool create_file(const String &p_output_path, const PackedStringArray &p_files);
bool create_file(const String &p_output_path, const Vector<String> &p_files);
bool create_file(const String &p_output_path, const Vector<String> &p_files, const Vector<Vector2i> &p_cputypes);

bool open_file(const String &p_path);
int get_arch_count() const;
uint32_t get_arch_cputype(int p_index) const;
uint32_t get_arch_cpusubtype(int p_index) const;
bool extract_arch(int p_index, const String &p_path);

void close();

~LipO();
};

#endif // MACOS_LIPO_H
#endif // LIPO_H
File renamed without changes.
23 changes: 20 additions & 3 deletions platform/macos/export/macho.h → editor/export/macho.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef MACOS_MACHO_H
#define MACOS_MACHO_H
#ifndef MACHO_H
#define MACHO_H

// Mach-O binary object file format parser and editor.

Expand All @@ -39,6 +39,7 @@
#include "core/object/ref_counted.h"

class MachO : public RefCounted {
public:
struct MachHeader {
uint32_t cputype;
uint32_t cpusubtype;
Expand Down Expand Up @@ -98,6 +99,21 @@ class MachO : public RefCounted {
LC_LINKER_OPTIMIZATION_HINT = 0x0000002e,
LC_VERSION_MIN_TVOS = 0x0000002f,
LC_VERSION_MIN_WATCHOS = 0x00000030,
LC_BUILD_VERSION = 0x00000032,
};

enum PlatformID {
PLATFORM_UNKNOWN = 0,
PLATFORM_MACOS = 1,
PLATFORM_IOS = 2,
PLATFORM_TVOS = 3,
PLATFORM_WATCHOS = 4,
PLATFORM_BRIDGEOS = 5,
PLATFORM_MACCATALYST = 6,
PLATFORM_IOSSIMULATOR = 7,
PLATFORM_TVOSSIMULATOR = 8,
PLATFORM_WATCHOSSIMULATOR = 9,
PLATFORM_DRIVERKIT = 10,
};

struct LoadCommandHeader {
Expand Down Expand Up @@ -158,6 +174,7 @@ class MachO : public RefCounted {
uint32_t reserved3;
};

private:
Ref<FileAccess> fa;
bool swap = false;

Expand Down Expand Up @@ -208,4 +225,4 @@ class MachO : public RefCounted {
bool set_signature_size(uint64_t p_size);
};

#endif // MACOS_MACHO_H
#endif // MACHO_H
3 changes: 3 additions & 0 deletions platform/ios/doc_classes/EditorExportPlatformIOS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<member name="application/export_project_only" type="bool" setter="" getter="">
If [code]true[/code], exports iOS project files without building an XCArchive or [code].ipa[/code] file. If [code]false[/code], exports iOS project files and builds an XCArchive and [code].ipa[/code] file at the same time. When combining Godot with Fastlane or other build pipelines, you may want to set this to [code]true[/code].
</member>
<member name="application/generate_simulator_library_if_missing" type="bool" setter="" getter="">
If [code]true[/code], and ARM64 simulator library is missing from the export template, it is automatically generated from ARM64 device library.
</member>
<member name="application/icon_interpolation" type="int" setter="" getter="">
Interpolation method used to resize application icon.
</member>
Expand Down
Loading

0 comments on commit 501c15c

Please sign in to comment.