Add iOS app exporting

This commit is contained in:
Wojtek Figat
2023-06-10 23:05:52 +02:00
parent 1fdc91255b
commit 621d408078
5 changed files with 74 additions and 21 deletions

View File

@@ -34,6 +34,18 @@ namespace
return productName;
}
const Char* GetExportMethod(iOSPlatformSettings::ExportMethods method)
{
switch (method)
{
case iOSPlatformSettings::ExportMethods::AppStore: return TEXT("app-store");
case iOSPlatformSettings::ExportMethods::Development: return TEXT("development");
case iOSPlatformSettings::ExportMethods::AdHoc: return TEXT("ad-hoc");
case iOSPlatformSettings::ExportMethods::Enterprise: return TEXT("enterprise");
default: return TEXT("");
}
}
String GetUIInterfaceOrientation(iOSPlatformSettings::UIInterfaceOrientations orientations)
{
String result;
@@ -196,6 +208,7 @@ bool iOSPlatformTools::OnPostProcess(CookingData& data)
configReplaceMap[TEXT("${ProjectName}")] = gameSettings->ProductName;
configReplaceMap[TEXT("${ProjectVersion}")] = projectVersion;
configReplaceMap[TEXT("${HeaderSearchPaths}")] = Globals::StartupFolder;
configReplaceMap[TEXT("${ExportMethod}")] = GetExportMethod(platformSettings->ExportMethod);
configReplaceMap[TEXT("${UISupportedInterfaceOrientations_iPhone}")] = GetUIInterfaceOrientation(platformSettings->SupportedInterfaceOrientationsiPhone);
configReplaceMap[TEXT("${UISupportedInterfaceOrientations_iPad}")] = GetUIInterfaceOrientation(platformSettings->SupportedInterfaceOrientationsiPad);
{
@@ -232,13 +245,6 @@ bool iOSPlatformTools::OnPostProcess(CookingData& data)
configReplaceMap[TEXT("${PBXFileReference}")] += String::Format(TEXT("\t\t{0} /* {1} */ = {{isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = \"{1}\"; path = \"FlaxGame/Data/{2}\"; sourceTree = \"<group>\"; }};\n"), fileId, name, projectPath);
configReplaceMap[TEXT("${PBXFrameworksBuildPhase}")] += String::Format(TEXT("\t\t\t\t{0} /* {1} in Frameworks */,\n"), frameworkId, name);
configReplaceMap[TEXT("${PBXFrameworksGroup}")] += String::Format(TEXT("\t\t\t\t{0} /* {1} */,\n"), fileId, name);
// Fix rpath id
// TODO: run this only for dylibs during AOT process (other libs are fine)
CreateProcessSettings proc;
proc.FileName = TEXT("install_name_tool");
proc.Arguments = String::Format(TEXT("-id \"@rpath/{0}\" \"{1}\""), name, file);
Platform::CreateProcess(proc);
}
else
{
@@ -251,6 +257,7 @@ bool iOSPlatformTools::OnPostProcess(CookingData& data)
}
bool failed = false;
failed |= EditorUtilities::ReplaceInFile(data.OriginalOutputPath / TEXT("FlaxGame.xcodeproj/project.pbxproj"), configReplaceMap);
failed |= EditorUtilities::ReplaceInFile(data.OriginalOutputPath / TEXT("ExportOptions.plist"), configReplaceMap);
if (failed)
{
LOG(Error, "Failed to format XCode project");
@@ -275,19 +282,26 @@ bool iOSPlatformTools::OnPostProcess(CookingData& data)
if (buildSettings->SkipPackaging)
return false;
GameCooker::PackageFiles();
LOG(Info, "Building app package...");
// TODO: run XCode archive and export
#if 0
const String ipaPath = data.OriginalOutputPath / appName + TEXT(".ipa");
const String ipaCommand = String::Format(TEXT("zip -r -X {0}.ipa Payload iTunesArtwork"), appName);
const int32 result = Platform::RunProcess(ipaCommand, data.OriginalOutputPath);
if (result != 0)
{
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
return true;
LOG(Info, "Building app package...");
const Char* configuration = data.Configuration == BuildConfiguration::Release ? TEXT("Release") : TEXT("Debug");
String command = String::Format(TEXT("xcodebuild -project FlaxGame.xcodeproj -configuration {} -scheme FlaxGame -archivePath FlaxGame.xcarchive archive"), configuration);
int32 result = Platform::RunProcess(command, data.OriginalOutputPath);
if (result != 0)
{
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
return true;
}
command = TEXT("xcodebuild -exportArchive -archivePath FlaxGame.xcarchive -allowProvisioningUpdates -exportPath . -exportOptionsPlist ExportOptions.plist");
result = Platform::RunProcess(command, data.OriginalOutputPath);
if (result != 0)
{
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
return true;
}
const String ipaPath = data.OriginalOutputPath / TEXT("FlaxGame.ipa");
LOG(Info, "Output application package: {0} (size: {1} MB)", ipaPath, FileSystem::GetFileSize(ipaPath) / 1024 / 1024);
}
LOG(Info, "Output application package: {0} (size: {1} MB)", ipaPath, FileSystem::GetFileSize(ipaPath) / 1024 / 1024);
#endif
return false;
}

View File

@@ -34,6 +34,7 @@ void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
File::ReadAllText(aotModeCacheFilePath, cachedData);
if (cachedData != aotModeCacheValue)
{
LOG(Info, "AOT cache invalidation");
FileSystem::DeleteDirectory(data.ManagedCodeOutputPath);
}
}

View File

@@ -13,6 +13,21 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
{
DECLARE_SCRIPTING_TYPE_MINIMAL(ApplePlatformSettings);
/// <summary>
/// The app export destination methods.
/// </summary>
API_ENUM() enum class ExportMethods
{
// Distribute using TestFlight or through the App Store.
AppStore,
// Distribute to a limited number of devices you register in App Store Connect.
Development,
// Distribute to a limited number of devices you register in App Store Connect.
AdHoc,
// Distribute to members of your organization if youre a part of the Apple Developer Enterprise Program and are ready to release your app to users in your organization.
Enterprise,
};
/// <summary>
/// The display orientation modes. Can be combined as flags.
/// </summary>
@@ -42,6 +57,12 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
API_FIELD(Attributes="EditorOrder(20), EditorDisplay(\"General\")")
String AppVersion = TEXT("1");
/// <summary>
/// The app export mode (if automatic packaging is not disabled via Build Settings, otherwise export app manually via XCode project).
/// </summary>
API_FIELD(Attributes="EditorOrder(50), EditorDisplay(\"General\")")
ExportMethods ExportMethod = ExportMethods::Development;
/// <summary>
/// The UI interface orientation modes supported on iPhone devices.
/// </summary>
@@ -65,6 +86,7 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
ApplePlatformSettings::Deserialize(stream, modifier);
DESERIALIZE(AppTeamId);
DESERIALIZE(AppVersion);
DESERIALIZE(ExportMethod);
DESERIALIZE(SupportedInterfaceOrientationsiPhone);
DESERIALIZE(SupportedInterfaceOrientationsiPad);
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>${ExportMethod}</string>
<key>teamID</key>
<string>${AppTeamId}</string>
<key>compileBitcode</key>
<false/>
</dict>
</plist>

View File

@@ -51,9 +51,6 @@ namespace Flax.Build.Platforms
options.LinkEnv.InputLibraries.Add("IOKit.framework");
options.LinkEnv.InputLibraries.Add("UIKit.framework");
options.LinkEnv.InputLibraries.Add("QuartzCore.framework");
//options.LinkEnv.InputLibraries.Add("QuartzCore.framework");
//options.LinkEnv.InputLibraries.Add("AudioToolbox.framework");
//options.LinkEnv.InputLibraries.Add("AudioUnit.framework");
}
protected override void AddArgsCommon(BuildOptions options, List<string> args)
@@ -124,6 +121,11 @@ namespace Flax.Build.Platforms
File.Delete(inputFileAsm);
File.Delete(inputFileObj);
// Fix rpath id
result = Utilities.Run("install_name_tool", $"-id \"@rpath/{Path.GetFileName(outputFileDylib)}\" \"{outputFileDylib}\"", null, inputFileFolder, Utilities.RunOptions.ConsoleLogOutput, envVars);
if (result != 0)
return true;
return false;
}
}