BundleIdentifier
BundleIdentifier
#Overview
name: BundleIdentifier
The value of this variable can be defined or overridden in .ini config files. 2
.ini config files referencing this setting variable.
It is referenced in 11
C++ source files. Also referenced in 10
C# build files meaning it may affect the build system logic.
#Summary
#Usage in the C++ source code
The purpose of BundleIdentifier is to provide a unique identifier for iOS applications. It is a crucial component in the iOS app development and deployment process, used to distinguish one app from another in the Apple ecosystem.
BundleIdentifier is primarily used in the iOS target platform and Xcode project settings within Unreal Engine 5. It’s a part of the bundle information category in the iOS Runtime Settings and is also used in the Xcode project settings for Mac target platforms.
The value of this variable is typically set in the project settings, specifically in the iOS Runtime Settings. It can be modified through the Unreal Engine editor or directly in the configuration files.
Several other variables interact with BundleIdentifier, including BundleDisplayName, BundleName, and VersionInfo. These are all part of the bundle information used to identify and version the iOS app.
Developers must be aware of the following when using this variable:
- The BundleIdentifier must be unique for each app in the Apple App Store.
- It should follow Apple’s naming conventions, typically in reverse domain name notation (e.g., com.companyname.appname).
- It’s used in various processes, including code signing, provisioning profile matching, and app installation.
Best practices when using this variable include:
- Use a consistent naming scheme across your organization’s apps.
- Avoid using placeholder or generic identifiers in production builds.
- Ensure the BundleIdentifier matches the one used in your Apple Developer account and provisioning profiles.
- Be cautious when changing the BundleIdentifier, as it can affect app updates and user data persistence.
#Usage in the C# source code and build system
The purpose of BundleIdentifier is to provide a unique identifier for iOS, tvOS, and macOS applications. This identifier is used by the operating system to recognize the app and is required for app distribution through the App Store.
The BundleIdentifier is primarily used in the iOS, tvOS, and macOS build systems of Unreal Engine. It’s referenced in various build scripts related to these platforms, including:
- IOSPlatform.Automation.cs
- UEBuildIOS.cs
- UEDeployIOS.cs
- MacToolChain.cs
- UEDeployMac.cs
- UEDeployTVOS.cs
- XcodeFrameworkWrapperProject.cs
- XcodeProject.cs
- XcodeProjectLegacy.cs
- RemoteMac.cs
The value of this variable is typically set in the engine configuration file, specifically in the “/Script/IOSRuntimeSettings.IOSRuntimeSettings” section. It can be overridden programmatically or through command-line arguments in some cases.
The BundleIdentifier interacts with other variables such as ProjectName, GameName, and BundleID. It often includes a placeholder “[PROJECT_NAME]” which is replaced with the actual project name during the build process.
Developers must be aware that:
- The BundleIdentifier must be unique for each application.
- It should follow Apple’s naming conventions (reverse-domain name style, e.g., com.companyname.appname).
- It’s used across different platforms (iOS, tvOS, macOS), so changes may affect multiple build targets.
Best practices when using this variable include:
- Use a consistent naming scheme across all your applications.
- Avoid changing the BundleIdentifier once your app is published, as it’s used to identify app updates.
- Ensure it’s properly set in the engine configuration to avoid build issues.
- Be cautious when manually overriding it in build scripts, as it may lead to inconsistencies.
The associated variable BundleID is used in some scripts to override the BundleIdentifier. It serves as an alternative way to set the bundle identifier, typically used for command-line builds or automated processes. The same considerations and best practices apply to BundleID as to BundleIdentifier.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEngine.ini:2999, section: [/Script/IOSRuntimeSettings.IOSRuntimeSettings]
- INI Section:
/Script/IOSRuntimeSettings.IOSRuntimeSettings
- Raw value:
com.YourCompany.[PROJECT_NAME]
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:3189, section: [/Script/MacTargetPlatform.XcodeProjectSettings]
- INI Section:
/Script/MacTargetPlatform.XcodeProjectSettings
- Raw value:
$(UE_SIGNING_PREFIX).$(UE_PRODUCT_NAME_STRIPPED)
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/Experimental/BackChannel/Source/BackChannel/Private/Protocol/BackChannelOSCPacket.cpp:15
Scope (from outer to inner):
file
function OSCPacketType FBackChannelOSCPacket::GetType
Source code excerpt:
}
const ANSICHAR* BundleIdentifier = "#bundle";
const ANSICHAR* MessageIdentifier = ""; // need to check whether "" is valid or it requires at least /
const int32 MessageIdentifierLen = FCStringAnsi::Strlen(MessageIdentifier);
if (DataLength >= FCStringAnsi::Strlen(BundleIdentifier))
{
if (FCStringAnsi::Stricmp(CharData, BundleIdentifier) == 0) //-V575
{
return OSCPacketType::Bundle;
}
}
if (DataLength >= MessageIdentifierLen)
#Loc: <Workspace>/Engine/Plugins/Online/EOSShared/Source/EOSShared/Private/IOS/IOSEOSSDKManager.cpp:19
Scope (from outer to inner):
file
function FString FIOSEOSSDKManager::GetCacheDirBase
Source code excerpt:
FString FIOSEOSSDKManager::GetCacheDirBase() const
{
NSString* BundleIdentifier = [[NSBundle mainBundle]bundleIdentifier];
NSString* CacheDirectory = NSTemporaryDirectory(); // Potentially use NSCachesDirectory
CacheDirectory = [CacheDirectory stringByAppendingPathComponent : BundleIdentifier];
const char* CStrCacheDirectory = [CacheDirectory UTF8String];
return FString(UTF8_TO_TCHAR(CStrCacheDirectory));
};
#endif // WITH_EOS_SDK
#Loc: <Workspace>/Engine/Source/Developer/IOS/IOSPlatformEditor/Private/IOSTargetSettingsCustomization.cpp:798
Scope: file
Source code excerpt:
SETUP_PLIST_PROP(BundleDisplayName, BundleCategory);
SETUP_PLIST_PROP(BundleName, BundleCategory);
SETUP_STATUS_PROP(BundleIdentifier, BundleCategory);
SETUP_PLIST_PROP(VersionInfo, BundleCategory);
SETUP_PLIST_PROP(bSupportsPortraitOrientation, OrientationCategory);
SETUP_PLIST_PROP(bSupportsUpsideDownOrientation, OrientationCategory);
SETUP_PLIST_PROP(bSupportsLandscapeLeftOrientation, OrientationCategory);
SETUP_PLIST_PROP(bSupportsLandscapeRightOrientation, OrientationCategory);
SETUP_PLIST_PROP(PreferredLandscapeOrientation, OrientationCategory);
#Loc: <Workspace>/Engine/Source/Developer/IOS/IOSPlatformEditor/Private/IOSTargetSettingsCustomization.cpp:1370
Scope (from outer to inner):
file
function void FIOSTargetSettingsCustomization::FindRequiredFiles
Source code excerpt:
{
const UIOSRuntimeSettings& Settings = *GetDefault<UIOSRuntimeSettings>();
FString BundleIdentifier = Settings.BundleIdentifier.Replace(*gProjectNameText, FApp::GetProjectName());
BundleIdentifier = BundleIdentifier.Replace(TEXT("_"), TEXT(""));
#if PLATFORM_MAC
FString CmdExe = TEXT("/bin/sh");
FString ScriptPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Build/BatchFiles/RunDotnet.sh"));
FString IPPPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/IOS/IPhonePackager.exe"));
FString CommandLine = FString::Printf(TEXT("\"%s\" \"%s\" certificates Engine -bundlename \"%s\""), *ScriptPath, *IPPPath, *(BundleIdentifier));
#else
FString CmdExe = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/IOS/IPhonePackager.exe"));
FString CommandLine = FString::Printf(TEXT("certificates Engine -bundlename \"%s\""), *(BundleIdentifier));
#endif
IPPProcess = MakeShareable(new FMonitoredProcess(CmdExe, CommandLine, true));
OutputMessage = TEXT("");
IPPProcess->OnOutput().BindStatic(&OnOutput);
IPPProcess->Launch();
TickerHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateRaw(this, &FIOSTargetSettingsCustomization::UpdateStatusDelegate), 1.0f);
#Loc: <Workspace>/Engine/Source/Developer/IOS/IOSPlatformEditor/Private/IOSTargetSettingsCustomization.cpp:1450
Scope (from outer to inner):
file
function FReply FIOSTargetSettingsCustomization::OnInstallProvisionClicked
Source code excerpt:
const UIOSRuntimeSettings& Settings = *GetDefault<UIOSRuntimeSettings>();
FString BundleIdentifier = Settings.BundleIdentifier.Replace(*gProjectNameText, FApp::GetProjectName());
BundleIdentifier = BundleIdentifier.Replace(TEXT("_"), TEXT(""));
#if PLATFORM_MAC
FString CmdExe = TEXT("/bin/sh");
FString ScriptPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Build/BatchFiles/RunDotnet.sh"));
FString IPPPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/IOS/IPhonePackager.exe"));
FString CommandLine = FString::Printf(TEXT("\"%s\" \"%s\" Install Engine -project \"%s\" -provision \"%s\" -bundlename \"%s\""), *ScriptPath, *IPPPath, *ProjectPath, *ProvisionPath, *BundleIdentifier);
#else
FString CmdExe = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/IOS/IPhonePackager.exe"));
FString CommandLine = FString::Printf(TEXT("Install Engine -project \"%s\" -provision \"%s\" -bundlename \"%s\""), *ProjectPath, *ProvisionPath, *BundleIdentifier);
#endif
IPPProcess = MakeShareable(new FMonitoredProcess(CmdExe, CommandLine, true));
OutputMessage = TEXT("");
IPPProcess->OnOutput().BindStatic(&OnOutput);
IPPProcess->Launch();
TickerHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateRaw(this, &FIOSTargetSettingsCustomization::UpdateStatusDelegate), 10.0f);
#Loc: <Workspace>/Engine/Source/Developer/IOS/IOSPlatformEditor/Private/IOSTargetSettingsCustomization.cpp:1564
Scope (from outer to inner):
file
function FReply FIOSTargetSettingsCustomization::OnInstallCertificateClicked
Source code excerpt:
{
const UIOSRuntimeSettings& Settings = *GetDefault<UIOSRuntimeSettings>();
FString BundleIdentifier = Settings.BundleIdentifier.Replace(*gProjectNameText, FApp::GetProjectName());
BundleIdentifier = BundleIdentifier.Replace(TEXT("_"), TEXT(""));
CertPath = FPaths::ConvertRelativePathToFull(OpenFilenames[0]);
#if PLATFORM_MAC
FString CmdExe = TEXT("/bin/sh");
FString ScriptPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Build/BatchFiles/RunDotnet.sh"));
FString IPPPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/IOS/IPhonePackager.exe"));
FString CommandLine = FString::Printf(TEXT("\"%s\" \"%s\" Install Engine -project \"%s\" -certificate \"%s\" -bundlename \"%s\""), *ScriptPath, *IPPPath, *ProjectPath, *CertPath, *BundleIdentifier);
#else
FString CmdExe = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/IOS/IPhonePackager.exe"));
FString CommandLine = FString::Printf(TEXT("Install Engine -project \"%s\" -certificate \"%s\" -bundlename \"%s\""), *ProjectPath, *CertPath, *BundleIdentifier);
#endif
IPPProcess = MakeShareable(new FMonitoredProcess(CmdExe, CommandLine, false));
OutputMessage = TEXT("");
IPPProcess->OnOutput().BindStatic(&OnOutput);
IPPProcess->Launch();
TickerHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateRaw(this, &FIOSTargetSettingsCustomization::UpdateStatusDelegate), 10.0f);
#Loc: <Workspace>/Engine/Source/Developer/IOS/IOSTargetPlatform/Private/IOSTargetPlatform.cpp:264
Scope (from outer to inner):
file
function int32 FIOSTargetPlatform::CheckRequirements
Source code excerpt:
GConfig->GetBool(TEXT("/Script/UnrealEd.ProjectPackagingSettings"), TEXT("ForDistribution"), bForDistribtion, GGameIni);
FString BundleIdentifier;
GConfig->GetString(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("BundleIdentifier"), BundleIdentifier, GEngineIni);
BundleIdentifier = BundleIdentifier.Replace(TEXT("[PROJECT_NAME]"), FApp::GetProjectName());
BundleIdentifier = BundleIdentifier.Replace(TEXT("_"), TEXT(""));
bool bAutomaticSigning = false;
GConfig->GetBool(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("bAutomaticSigning"), bAutomaticSigning, GEngineIni);
FString TeamID;
GConfig->GetString(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("IOSTeamID"), TeamID, GEngineIni);
#Loc: <Workspace>/Engine/Source/Developer/IOS/IOSTargetPlatform/Private/IOSTargetPlatform.cpp:280
Scope (from outer to inner):
file
function int32 FIOSTargetPlatform::CheckRequirements
Source code excerpt:
FString ScriptPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Build/BatchFiles/RunDotnet.sh"));
FString IPPPath = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/IOS/IPhonePackager.exe"));
FString CommandLine = FString::Printf(TEXT("\"%s\" \"%s\" Validate Engine -project \"%s\" -bundlename \"%s\" -teamID \"%s\" %s %s"), *ScriptPath, *IPPPath, *ProjectPath, *(BundleIdentifier), *(TeamID), (bForDistribtion ? TEXT("-distribution") : TEXT("")), bAutomaticSigning ? TEXT("-autosigning") : TEXT(""));
#else
FString CmdExe = FPaths::ConvertRelativePathToFull(FPaths::EngineDir() / TEXT("Binaries/DotNET/IOS/IPhonePackager.exe"));
FString CommandLine = FString::Printf(TEXT("Validate Engine -project \"%s\" -bundlename \"%s\" %s"), *ProjectPath, *(BundleIdentifier), (bForDistribtion ? TEXT("-distribution") : TEXT("")) );
FString RemoteServerName;
FString SecondaryRemoteServerName;
FString RSyncUsername;
FString SecondaryRSyncUsername;
GConfig->GetString(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("RemoteServerName"), RemoteServerName, GEngineIni);
GConfig->GetString(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("RSyncUsername"), RSyncUsername, GEngineIni);
#Loc: <Workspace>/Engine/Source/Developer/Mac/MacTargetPlatform/Classes/XcodeProjectSettings.h:58
Scope (from outer to inner):
file
class class UXcodeProjectSettings : public UObject
Source code excerpt:
*/
UPROPERTY(EditAnywhere, config, Category=Xcode, meta = (EditCondition="bUseModernXcode", DisplayName = "Bundle ID"))
FString BundleIdentifier;
/**
* Bundle ID prefix used for native Xcode code signing. This is only needed if you use the default, pieced-together Bundle ID above. If you specify a full Bundle ID, you can ignore this field.
*/
UPROPERTY(EditAnywhere, config, Category=Xcode, meta = (EditCondition="bUseModernXcode", DisplayName = "Bundle ID Prefix"))
FString CodeSigningPrefix;
#Loc: <Workspace>/Engine/Source/Runtime/IOS/IOSRuntimeSettings/Classes/IOSRuntimeSettings.h:400
Scope (from outer to inner):
file
class class UIOSRuntimeSettings : public UObject
Source code excerpt:
// Specifies the bundle identifier for the application.
UPROPERTY(GlobalConfig, EditAnywhere, Category = BundleInformation)
FString BundleIdentifier;
// Specifies the version for the application.
UPROPERTY(GlobalConfig, EditAnywhere, Category = BundleInformation)
FString VersionInfo;
/**
#Loc: <Workspace>/Engine/Source/Runtime/IOS/IOSRuntimeSettings/Private/IOSRuntimeSettings.cpp:33
Scope (from outer to inner):
file
function UIOSRuntimeSettings::UIOSRuntimeSettings
Source code excerpt:
BundleDisplayName = TEXT("UnrealGame");
BundleName = TEXT("MyUnrealGame");
BundleIdentifier = TEXT("com.YourCompany.GameNameNoSpaces");
VersionInfo = TEXT("1.0.0");
FrameRateLock = EPowerUsageFrameRateLock::PUFRL_30;
bEnableDynamicMaxFPS = false;
bSupportsIPad = true;
bSupportsIPhone = true;
bEnableSplitView = false;
#References in C# build files
This variable is referenced in the following C# build files:
Location: <Workspace>/Engine/Source/Programs/AutomationTool/IOS/IOSPlatform.Automation.cs:246
// fall back to ini for anything else
if (string.IsNullOrEmpty(CodeSigningIdentity)) EngineConfig.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "DevCodeSigningIdentity", out CodeSigningIdentity);
if (string.IsNullOrEmpty(BundleId)) EngineConfig.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleId);
if (string.IsNullOrEmpty(Team)) EngineConfig.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "IOSTeamID", out Team);
if (string.IsNullOrEmpty(Account)) EngineConfig.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "DevCenterUsername", out Account);
if (string.IsNullOrEmpty(Password)) EngineConfig.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "DevCenterPassword", out Password);
if (string.IsNullOrEmpty(Provision)) EngineConfig.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "MobileProvision", out Provision);
BundleId = BundleId.Replace("[PROJECT_NAME]", ProjectName);
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/Platform/IOS/UEBuildIOS.cs:308
/// The bundle identifier
/// </summary>
[ConfigFile(ConfigHierarchyType.Engine, "/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier")]
public readonly string BundleIdentifier = "";
/// <summary>
/// true if using Xcode managed provisioning, else false
/// </summary>
[ConfigFile(ConfigHierarchyType.Engine, "/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bAutomaticSigning")]
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/Platform/IOS/UEDeployIOS.cs:611
// bundle identifier
string BundleIdentifier;
Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier);
if (!String.IsNullOrEmpty(BundleID))
{
BundleIdentifier = BundleID; // overriding bundle ID
}
// bundle name
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/Platform/Mac/MacToolChain.cs:553
string BundleIdentifier;
IOSIni.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier!);
string ProjectName = GameName;
FileReference? UProjectFilePath = ProjectFile;
if (UProjectFilePath != null)
{
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/Platform/Mac/UEDeployMac.cs:45
string BundleIdentifier;
Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier);
string BundleVersion = MacToolChain.LoadEngineDisplayVersion();
// duplicating some logic in MacToolchain for the BundleID
string[] ExeNameParts = ExeName.Split('-');
bool bBuildingEditor = ExeNameParts[0].EndsWith("Editor");
string FinalBundleID = bBuildingEditor ? $"com.epicgames.{ExeNameParts[0]}" : BundleIdentifier.Replace("[PROJECT_NAME]", ProjectName);
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/Platform/TVOS/UEDeployTVOS.cs:51
// bundle identifier
string BundleIdentifier;
Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier);
if (!String.IsNullOrEmpty(BundleID))
{
BundleIdentifier = BundleID;
}
// bundle name
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/ProjectFiles/Xcode/XcodeFrameworkWrapperProject.cs:280
ConfigHierarchy Ini = GetIni(ProjectDirectory);
string BundleId;
Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleId);
BundleId = BundleId.Replace("[PROJECT_NAME]", ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UnrealGame")).Replace("_", "");
return BundleId;
}
public static string GetBundleName(DirectoryReference ProjectDirectory, FileReference? ProjectFile)
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/ProjectFiles/Xcode/XcodeProject.cs:512
{
ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ConfigDirectory, UnrealTargetPlatform.Mac);
Ini.GetString($"/Script/MacTargetPlatform.XcodeProjectSettings", "BundleIdentifier", out BundleIdentifier);
}
if (String.IsNullOrEmpty(BundleIdentifier))
{
BundleIdentifier = "$(UE_SIGNING_PREFIX).$(UE_PRODUCT_NAME_STRIPPED)";
}
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/ProjectFiles/Xcode/XcodeProjectLegacy.cs:1086
ConfigHierarchy IOSIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectFile?.Directory, UnrealTargetPlatform.IOS);
string IOSBundleIdentifier;
IOSIni.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out IOSBundleIdentifier!);
// we are going to load/sign the UnrealEditor.app when doing modular editor builds, so reuse the shared identifier
bool bBuildingEditor = Config.ProjectTarget!.TargetRules!.Type == TargetType.Editor && Config.ProjectTarget!.TargetRules!.LinkType == TargetLinkType.Modular;
string MacBundleIdentifier = bBuildingEditor ? ("com.epicgames.UnrealEditor") : (IOSBundleIdentifier.Replace("[PROJECT_NAME]", TargetName).Replace("_", ""));
// Xcode 14 wants this to match what is in the final plist
Content.Append("\t\t\t\t\"PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]\" = " + MacBundleIdentifier + ";" + ProjectFileGenerator.NewLine);
Location: <Workspace>/Engine/Source/Programs/UnrealBuildTool/ToolChain/RemoteMac.cs:210
}
Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out IniBundleIdentifier);
// If it's not set, look in the standard locations. If that fails, spawn the batch file to generate one.
if (SshPrivateKey == null && !TryGetSshPrivateKey(out SshPrivateKey))
{
Logger.LogWarning("No SSH private key found for {UserName}@{ServerName}. Launching SSH to generate one.", UserName, ServerName);