public HTML5ToolChain(FileReference InProjectFile) : base(CppPlatform.HTML5) { if (!HTML5SDKInfo.IsSDKInstalled()) { throw new BuildException("HTML5 SDK is not installed; cannot use toolchain."); } // ini configs // - normal ConfigCache w/ UnrealBuildTool.ProjectFile takes all game config ini files // (including project config ini files) // - but, during packaging, if -remoteini is used -- need to use UnrealBuildTool.GetRemoteIniPath() // (note: ConfigCache can take null ProjectFile) string EngineIniPath = UnrealBuildTool.GetRemoteIniPath(); DirectoryReference ProjectDir = !String.IsNullOrEmpty(EngineIniPath) ? new DirectoryReference(EngineIniPath) : DirectoryReference.FromFile(InProjectFile); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectDir, UnrealTargetPlatform.HTML5); // Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableSIMD", out enableSIMD); // Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableMultithreading", out enableMultithreading); Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableTracing", out bEnableTracing); // TODO: remove this "fix" when emscripten supports (SIMD & pthreads) + WASM enableSIMD = false; // TODO: double check Engine/Source/Runtime/Core/Private/HTML5/HTML5PlatformProcess.cpp::SupportsMultithreading() enableMultithreading = false; Log.TraceInformation("HTML5ToolChain: EnableSIMD = " + enableSIMD); Log.TraceInformation("HTML5ToolChain: EnableMultithreading " + enableMultithreading); Log.TraceInformation("HTML5ToolChain: EnableTracing = " + bEnableTracing); PrintOnce = new VerbosePrint(PrintOnceOn); // reset }
public bool PrepForUATPackageOrDeploy(FileReference ProjectFile, string ProjectName, string ProjectDirectory, WindowsArchitecture Architecture, List <UnrealTargetConfiguration> TargetConfigurations, List <string> ExecutablePaths, string EngineDirectory, bool bForDistribution, string CookFlavor, bool bIsDataDeploy) { //@todo need to support dlc and other targets //string LocalizedContentDirectory = Path.Combine(ProjectDirectory, "Content", "Localization", "Game"); string AbsoluteExeDirectory = Path.GetDirectoryName(ExecutablePaths[0]); //bool IsGameSpecificExe = ProjectFile != null && AbsoluteExeDirectory.StartsWith(ProjectDirectory); //string RelativeExeFilePath = Path.Combine(IsGameSpecificExe ? ProjectName : "Engine", "Binaries", "HoloLens", Path.GetFileName(ExecutablePaths[0])); //string TargetDirectory = Path.Combine(ProjectDirectory, "Saved", "HoloLens"); // If using a secure networking manifest, copy it to the output directory. string NetworkManifest = Path.Combine(ProjectDirectory, "Config", "HoloLens", "NetworkManifest.xml"); if (File.Exists(NetworkManifest)) { CopyFile(NetworkManifest, Path.Combine(AbsoluteExeDirectory, "NetworkManifest.xml"), false); } // If using Xbox Live generate the json config file expected by the SDK DirectoryReference ConfigDirRef = DirectoryReference.FromFile(ProjectFile); if (ConfigDirRef == null && !string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath())) { ConfigDirRef = new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()); } //MakeAppXPath = HoloLensExports.GetWindowsSdkToolPath("makeappx.exe"); //SignToolPath = HoloLensExports.GetWindowsSdkToolPath("signtool.exe"); return(true); }
public HTML5ToolChain(FileReference InProjectFile) : base(CppPlatform.HTML5) { if (!HTML5SDKInfo.IsSDKInstalled()) { throw new BuildException("HTML5 SDK is not installed; cannot use toolchain."); } // ini configs // - normal ConfigCache w/ UnrealBuildTool.ProjectFile takes all game config ini files // (including project config ini files) // - but, during packaging, if -remoteini is used -- need to use UnrealBuildTool.GetRemoteIniPath() // (note: ConfigCache can take null ProjectFile) string EngineIniPath = UnrealBuildTool.GetRemoteIniPath(); DirectoryReference ProjectDir = !String.IsNullOrEmpty(EngineIniPath) ? new DirectoryReference(EngineIniPath) : DirectoryReference.FromFile(InProjectFile); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectDir, UnrealTargetPlatform.HTML5); // Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableSIMD", out enableSIMD); Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableMultithreading", out enableMultithreading); Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "OffscreenCanvas", out bMultithreading_UseOffscreenCanvas); Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LLVMWasmBackend", out useLLVMwasmBackend); Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableTracing", out bEnableTracing); if (useLLVMwasmBackend) { libExt = ".a"; // experimental - LLVMWasmBackend } // TODO: remove this "fix" when emscripten supports WASM with SIMD enableSIMD = false; Log.TraceInformation("HTML5ToolChain: EnableSIMD = " + enableSIMD); Log.TraceInformation("HTML5ToolChain: EnableMultithreading " + enableMultithreading); Log.TraceInformation("HTML5ToolChain: OffscreenCanvas " + bMultithreading_UseOffscreenCanvas); Log.TraceInformation("HTML5ToolChain: LLVMWasmBackend " + useLLVMwasmBackend); Log.TraceInformation("HTML5ToolChain: EnableTracing = " + bEnableTracing); PrintOnce = new VerbosePrint(PrintOnceOn); // reset Log.TraceInformation("Setting Emscripten SDK: located in " + HTML5SDKInfo.EMSCRIPTEN_ROOT); string TempDir = HTML5SDKInfo.SetupEmscriptenTemp(); HTML5SDKInfo.SetUpEmscriptenConfigFile(); if (Environment.GetEnvironmentVariable("EMSDK") == null) // If EMSDK is present, Emscripten is already configured by the developer { // If not using preset emsdk, configure our generated .emscripten config, instead of autogenerating one in the user's home directory. Environment.SetEnvironmentVariable("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN); Environment.SetEnvironmentVariable("EM_CACHE", HTML5SDKInfo.EMSCRIPTEN_CACHE); Environment.SetEnvironmentVariable("EMCC_TEMP_DIR", TempDir); } Log.TraceInformation("*** Emscripten Config File: " + Environment.GetEnvironmentVariable("EM_CONFIG")); }
public bool UseVulkan() { DirectoryReference DirRef = (!string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath()) ? new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()) : (ProjectFile != null ? ProjectFile.Directory : null)); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirRef, UnrealTargetPlatform.Lumin); // go by string bool bUseVulkan = true; Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bUseVulkan", out bUseVulkan); return(bUseVulkan); }
/// <summary> /// Find the default architecture for the given project /// </summary> public override string GetDefaultArchitecture(FileReference ProjectFile) { string ActiveArchitecture = DefaultArchitecture; // read settings from the config string EngineIniPath = ProjectFile != null ? ProjectFile.Directory.FullName : null; if (String.IsNullOrEmpty(EngineIniPath)) { // If the project file hasn't been specified, try to get the path from -remoteini command line param EngineIniPath = UnrealBuildTool.GetRemoteIniPath(); } DirectoryReference EngineIniDir = !String.IsNullOrEmpty(EngineIniPath) ? new DirectoryReference(EngineIniPath) : null; ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, EngineIniDir, UnrealTargetPlatform.Linux); string LinuxArchitectureString; if (Ini.GetString("/Script/LinuxTargetPlatform.LinuxTargetSettings", "TargetArchitecture", out LinuxArchitectureString)) { LinuxArchitecture Architecture; if (Enum.TryParse(LinuxArchitectureString, out Architecture)) { switch (Architecture) { default: System.Console.WriteLine("Architecture enum value {0} does not map to a valid triplet.", Architecture); break; case LinuxArchitecture.X86_64UnknownLinuxGnu: ActiveArchitecture = "x86_64-unknown-linux-gnu"; break; case LinuxArchitecture.ArmUnknownLinuxGnueabihf: ActiveArchitecture = "arm-unknown-linux-gnueabihf"; break; case LinuxArchitecture.AArch64UnknownLinuxGnueabi: ActiveArchitecture = "aarch64-unknown-linux-gnueabi"; break; case LinuxArchitecture.I686UnknownLinuxGnu: ActiveArchitecture = "i686-unknown-linux-gnu"; break; } } } return(ActiveArchitecture); }
// Look for any build options in the engine config file. public override void ParseProjectSettings() { base.ParseProjectSettings(); string EngineIniPath = ProjectFile != null ? ProjectFile.Directory.FullName : null; if (String.IsNullOrEmpty(EngineIniPath)) { EngineIniPath = UnrealBuildTool.GetRemoteIniPath(); } ConfigCacheIni Ini = new ConfigCacheIni(UnrealTargetPlatform.IOS, "Engine", EngineIniPath); string ServerName = RemoteServerName; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "RemoteServerName", out ServerName) && !String.IsNullOrEmpty(ServerName)) { RemoteServerName = ServerName; } bool bUseRSync = false; if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bUseRSync", out bUseRSync)) { bUseRPCUtil = !bUseRSync; string UserName = RSyncUsername; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "RSyncUsername", out UserName) && !String.IsNullOrEmpty(UserName)) { RSyncUsername = UserName; } if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "DeltaCopyInstallPath", out OverrideDeltaCopyInstallPath)) { if (!string.IsNullOrEmpty(OverrideDeltaCopyInstallPath)) { SSHExe = Path.Combine(OverrideDeltaCopyInstallPath, Path.GetFileName(SSHExe)); RSyncExe = Path.Combine(OverrideDeltaCopyInstallPath, Path.GetFileName(RSyncExe)); } } string ConfigKeyPath; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "SSHPrivateKeyOverridePath", out ConfigKeyPath)) { if (File.Exists(ConfigKeyPath)) { SSHPrivateKeyOverridePath = ConfigKeyPath; } } } }
static bool bEnableTracing = false; // Debug option public HTML5ToolChain(FileReference InProjectFile) : base(CppPlatform.HTML5, WindowsCompiler.VisualStudio2015) { if (!HTML5SDKInfo.IsSDKInstalled()) { throw new BuildException("HTML5 SDK is not installed; cannot use toolchain."); } // ini configs // - normal ConfigCache w/ UnrealBuildTool.ProjectFile takes all game config ini files // (including project config ini files) // - but, during packaging, if -remoteini is used -- need to use UnrealBuildTool.GetRemoteIniPath() // (note: ConfigCache can take null ProjectFile) string EngineIniPath = UnrealBuildTool.GetRemoteIniPath(); DirectoryReference ProjectDir = !String.IsNullOrEmpty(EngineIniPath) ? new DirectoryReference(EngineIniPath) : DirectoryReference.FromFile(InProjectFile); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectDir, UnrealTargetPlatform.HTML5); // these will be going away... bool targetingAsmjs = false; // inverted check bool targetWebGL1 = false; // inverted check if (Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "TargetAsmjs", out targetingAsmjs)) { targetingWasm = !targetingAsmjs; } if (Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "TargetWebGL1", out targetWebGL1)) { targetWebGL2 = !targetWebGL1; } Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableSIMD", out enableSIMD); Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableMultithreading", out enableMultithreading); Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableTracing", out bEnableTracing); Log.TraceInformation("HTML5ToolChain: TargetWasm = " + targetingWasm); Log.TraceInformation("HTML5ToolChain: TargetWebGL2 = " + targetWebGL2); Log.TraceInformation("HTML5ToolChain: EnableSIMD = " + enableSIMD); Log.TraceInformation("HTML5ToolChain: EnableMultithreading " + enableMultithreading); Log.TraceInformation("HTML5ToolChain: EnableTracing = " + bEnableTracing); // TODO: remove this "fix" when emscripten supports (SIMD & pthreads) + WASM if (targetingWasm) { enableSIMD = false; // TODO: double check Engine/Source/Runtime/Core/Private/HTML5/HTML5PlatformProcess.cpp::SupportsMultithreading() enableMultithreading = false; } }
public static bool GeneratePList(string ProjectDirectory, bool bIsUE4Game, string GameName, string ProjectName, string InEngineDir, string ExeName) { string IntermediateDirectory = (bIsUE4Game ? InEngineDir : ProjectDirectory) + "/Intermediate/Mac"; string DestPListFile = IntermediateDirectory + "/" + ExeName + "-Info.plist"; string SrcPListFile = (bIsUE4Game ? (InEngineDir + "Source/Programs/") : (ProjectDirectory + "/Source/")) + GameName + "/Resources/Mac/Info.plist"; if (!File.Exists(SrcPListFile)) { SrcPListFile = InEngineDir + "/Source/Runtime/Launch/Resources/Mac/Info.plist"; } string PListData = null; if (File.Exists(SrcPListFile)) { PListData = File.ReadAllText(SrcPListFile); } else { return(false); } // bundle identifier // plist replacements DirectoryReference DirRef = bIsUE4Game ? (!string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath()) ? new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()) : null) : new DirectoryReference(ProjectDirectory); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirRef, UnrealTargetPlatform.IOS); string BundleIdentifier; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier); string BundleVersion = MacToolChain.LoadEngineDisplayVersion(); PListData = PListData.Replace("${EXECUTABLE_NAME}", ExeName).Replace("${APP_NAME}", BundleIdentifier.Replace("[PROJECT_NAME]", ProjectName).Replace("_", "")).Replace("${ICON_NAME}", GameName).Replace("${MACOSX_DEPLOYMENT_TARGET}", MacToolChain.Settings.MinMacOSVersion).Replace("${BUNDLE_VERSION}", BundleVersion); if (!Directory.Exists(IntermediateDirectory)) { Directory.CreateDirectory(IntermediateDirectory); } File.WriteAllText(DestPListFile, PListData); return(true); }
/// <summary> /// Constructor /// </summary> /// <param name="ProjectFile">Project to read settings from</param> public RemoteMac(FileReference ProjectFile) { this.RsyncExe = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Extras", "ThirdPartyNotUE", "DeltaCopy", "Binaries", "Rsync.exe"); this.SshExe = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Extras", "ThirdPartyNotUE", "DeltaCopy", "Binaries", "Ssh.exe"); this.ProjectFile = ProjectFile; this.ProjectDirectory = DirectoryReference.FromFile(ProjectFile); // Apply settings from the XML file XmlConfig.ApplyTo(this); // Get the project config file path DirectoryReference EngineIniPath = ProjectFile != null ? ProjectFile.Directory : null; if (EngineIniPath == null && UnrealBuildTool.GetRemoteIniPath() != null) { EngineIniPath = new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()); } ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, EngineIniPath, UnrealTargetPlatform.IOS); // Read the project settings if we don't have anything in the build configuration settings if (String.IsNullOrEmpty(ServerName)) { // Read the server name string IniServerName; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "RemoteServerName", out IniServerName) && !String.IsNullOrEmpty(IniServerName)) { this.ServerName = IniServerName; } else { throw new BuildException("Remote compiling requires a server name. Use the editor (Project Settings > IOS) to set up your remote compilation settings."); } // Parse the username string IniUserName; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "RSyncUsername", out IniUserName) && !String.IsNullOrEmpty(IniUserName)) { this.UserName = IniUserName; } } // Split port out from the server name int PortIdx = ServerName.LastIndexOf(':'); if (PortIdx != -1) { string Port = ServerName.Substring(PortIdx + 1); if (!int.TryParse(Port, out ServerPort)) { throw new BuildException("Unable to parse port number from '{0}'", ServerName); } ServerName = ServerName.Substring(0, PortIdx); } // If a user name is not set, use the current user if (String.IsNullOrEmpty(UserName)) { UserName = Environment.UserName; } // Print out the server info Log.TraceInformation("[Remote] Using remote server '{0}' on port {1} (user '{2}')", ServerName, ServerPort, UserName); // Get the path to the SSH private key string OverrideSshPrivateKeyPath; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "SSHPrivateKeyOverridePath", out OverrideSshPrivateKeyPath) && !String.IsNullOrEmpty(OverrideSshPrivateKeyPath)) { SshPrivateKey = new FileReference(OverrideSshPrivateKeyPath); if (!FileReference.Exists(SshPrivateKey)) { throw new BuildException("SSH private key specified in config file ({0}) does not exist.", SshPrivateKey); } } // 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)) { Log.TraceWarning("No SSH private key found for {0}@{1}. Launching SSH to generate one.", UserName, ServerName); StringBuilder CommandLine = new StringBuilder(); CommandLine.AppendFormat("/C \"\"{0}\"", FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "BatchFiles", "MakeAndInstallSSHKey.bat")); CommandLine.AppendFormat(" \"{0}\"", SshExe); CommandLine.AppendFormat(" \"{0}\"", ServerPort); CommandLine.AppendFormat(" \"{0}\"", RsyncExe); CommandLine.AppendFormat(" \"{0}\"", UserName); CommandLine.AppendFormat(" \"{0}\"", ServerName); CommandLine.AppendFormat(" \"{0}\"", DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.MyDocuments)); CommandLine.AppendFormat(" \"{0}\"", GetLocalCygwinPath(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.MyDocuments))); CommandLine.AppendFormat(" \"{0}\"", UnrealBuildTool.EngineDirectory); CommandLine.Append("\""); using (Process ChildProcess = Process.Start("C:\\Windows\\System32\\Cmd.exe", CommandLine.ToString())) { ChildProcess.WaitForExit(); } if (!TryGetSshPrivateKey(out SshPrivateKey)) { throw new BuildException("Failed to generate SSH private key for {0}@{1}.", UserName, ServerName); } } // resolve the rest of the strings RsyncAuthentication = ExpandVariables(RsyncAuthentication); SshAuthentication = ExpandVariables(SshAuthentication); // Get the remote base directory RemoteBaseDir = String.Format("/Users/{0}/UE4/Builds/{1}", UserName, Environment.MachineName); // Build the list of directory mappings between the local and remote machines Mappings = new List <RemoteMapping>(); Mappings.Add(new RemoteMapping(UnrealBuildTool.EngineDirectory, GetRemotePath(UnrealBuildTool.EngineDirectory))); if (ProjectFile != null && !ProjectFile.IsUnderDirectory(UnrealBuildTool.EngineDirectory)) { Mappings.Add(new RemoteMapping(ProjectFile.Directory, GetRemotePath(ProjectFile.Directory))); } // Build a list of arguments for SSH CommonSshArguments = new List <string>(); CommonSshArguments.Add("-o BatchMode=yes"); CommonSshArguments.Add(SshAuthentication); CommonSshArguments.Add(String.Format("-p {0}", ServerPort)); CommonSshArguments.Add(String.Format("\"{0}@{1}\"", UserName, ServerName)); // Build a list of arguments for Rsync CommonRsyncArguments = new List <string>(); CommonRsyncArguments.Add("--compress"); CommonRsyncArguments.Add("--recursive"); CommonRsyncArguments.Add("--delete"); // Delete anything not in the source directory CommonRsyncArguments.Add("--delete-excluded"); // Delete anything not in the source directory CommonRsyncArguments.Add("--times"); // Preserve modification times CommonRsyncArguments.Add("--verbose"); CommonRsyncArguments.Add("-m"); CommonRsyncArguments.Add("--chmod=ug=rwX,o=rxX"); CommonRsyncArguments.Add(String.Format("--rsh=\"{0} -p {1}\"", RsyncAuthentication, ServerPort)); }
public static bool GenerateIOSPList(string ProjectDirectory, bool bIsUE4Game, string GameName, string ProjectName, string InEngineDir, string AppDirectory, UEDeployIOS InThis = null) { // generate the Info.plist for future use string BuildDirectory = ProjectDirectory + "/Build/IOS"; bool bSkipDefaultPNGs = false; string IntermediateDirectory = (bIsUE4Game ? InEngineDir : ProjectDirectory) + "/Intermediate/IOS"; string PListFile = IntermediateDirectory + "/" + GameName + "-Info.plist"; ProjectName = !String.IsNullOrEmpty(ProjectName) ? ProjectName : GameName; VersionUtilities.BuildDirectory = BuildDirectory; VersionUtilities.GameName = GameName; // read the old file string OldPListData = File.Exists(PListFile) ? File.ReadAllText(PListFile) : ""; // determine if there is a launch.xib string LaunchXib = InEngineDir + "/Build/IOS/Resources/Interface/LaunchScreen.xib"; if (File.Exists(BuildDirectory + "/Resources/Interface/LaunchScreen.xib")) { LaunchXib = BuildDirectory + "/Resources/Interface/LaunchScreen.xib"; } // get the settings from the ini file // plist replacements DirectoryReference DirRef = bIsUE4Game ? (!string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath()) ? new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()) : null) : new DirectoryReference(ProjectDirectory); ConfigCacheIni Ini = ConfigCacheIni.CreateConfigCacheIni(UnrealTargetPlatform.IOS, "Engine", DirRef); // orientations string SupportedOrientations = ""; bool bSupported = true; Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsPortraitOrientation", out bSupported); SupportedOrientations += bSupported ? "\t\t<string>UIInterfaceOrientationPortrait</string>\n" : ""; Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsUpsideDownOrientation", out bSupported); SupportedOrientations += bSupported ? "\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n" : ""; Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsLandscapeLeftOrientation", out bSupported); SupportedOrientations += bSupported ? "\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n" : ""; Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsLandscapeRightOrientation", out bSupported); SupportedOrientations += bSupported ? "\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n" : ""; // bundle display name string BundleDisplayName; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleDisplayName", out BundleDisplayName); // bundle identifier string BundleIdentifier; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier); // bundle name string BundleName; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleName", out BundleName); // disable https requirement bool bDisableHTTPS; Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bDisableHTTPS", out bDisableHTTPS); // short version string string BundleShortVersion; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "VersionInfo", out BundleShortVersion); // required capabilities string RequiredCaps = ""; if (InThis != null) { // required capabilities RequiredCaps += InThis.IOSPlatformContext.GetRequiredCapabilities(); } Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsOpenGLES2", out bSupported); RequiredCaps += bSupported ? "\t\t<string>opengles-2</string>\n" : ""; if (!bSupported) { Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsMetal", out bSupported); RequiredCaps += bSupported ? "\t\t<string>metal</string>\n" : ""; } // minimum iOS version string MinVersion; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "MinimumiOSVersion", out MinVersion)) { switch (MinVersion) { case "IOS_61": Log.TraceWarning("IOS 6 is no longer supported in UE4 as 4.11"); MinVersion = "7.0"; break; case "IOS_7": MinVersion = "7.0"; break; case "IOS_8": MinVersion = "8.0"; break; case "IOS_9": MinVersion = "9.0"; break; } } else { MinVersion = "7.0"; } // Get Facebook Support details bool bEnableFacebookSupport = true; Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableFacebookSupport", out bEnableFacebookSupport); // Write the Facebook App ID if we need it. string FacebookAppID = ""; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "FacebookAppID", out FacebookAppID); bEnableFacebookSupport = bEnableFacebookSupport && !string.IsNullOrWhiteSpace(FacebookAppID); // Add remote-notifications as background mode bool bRemoteNotificationsSupported = false; Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableRemoteNotificationsSupport", out bRemoteNotificationsSupported); // extra plist data string ExtraData = ""; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "AdditionalPlistData", out ExtraData); // generate the plist file StringBuilder Text = new StringBuilder(); Text.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); Text.AppendLine("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); Text.AppendLine("<plist version=\"1.0\">"); Text.AppendLine("<dict>"); Text.AppendLine("\t<key>CFBundleURLTypes</key>"); Text.AppendLine("\t<array>"); Text.AppendLine("\t\t<dict>"); Text.AppendLine("\t\t\t<key>CFBundleURLName</key>"); Text.AppendLine("\t\t\t<string>com.Epic.Unreal</string>"); Text.AppendLine("\t\t\t<key>CFBundleURLSchemes</key>"); Text.AppendLine("\t\t\t<array>"); Text.AppendLine(string.Format("\t\t\t\t<string>{0}</string>", bIsUE4Game ? "UE4Game" : GameName)); if (bEnableFacebookSupport) { // This is needed for facebook login to redirect back to the app after completion. Text.AppendLine(string.Format("\t\t\t\t<string>fb{0}</string>", FacebookAppID)); } Text.AppendLine("\t\t\t</array>"); Text.AppendLine("\t\t</dict>"); Text.AppendLine("\t</array>"); Text.AppendLine("\t<key>CFBundleDevelopmentRegion</key>"); Text.AppendLine("\t<string>English</string>"); Text.AppendLine("\t<key>CFBundleDisplayName</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", EncodeBundleName(BundleDisplayName, ProjectName))); Text.AppendLine("\t<key>CFBundleExecutable</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", bIsUE4Game ? "UE4Game" : GameName)); Text.AppendLine("\t<key>CFBundleIdentifier</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", BundleIdentifier.Replace("[PROJECT_NAME]", ProjectName).Replace("_", ""))); Text.AppendLine("\t<key>CFBundleInfoDictionaryVersion</key>"); Text.AppendLine("\t<string>6.0</string>"); Text.AppendLine("\t<key>CFBundleName</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", EncodeBundleName(BundleName, ProjectName))); Text.AppendLine("\t<key>CFBundlePackageType</key>"); Text.AppendLine("\t<string>APPL</string>"); Text.AppendLine("\t<key>CFBundleSignature</key>"); Text.AppendLine("\t<string>????</string>"); Text.AppendLine("\t<key>CFBundleVersion</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", VersionUtilities.UpdateBundleVersion(OldPListData))); Text.AppendLine("\t<key>CFBundleShortVersionString</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", BundleShortVersion)); Text.AppendLine("\t<key>LSRequiresIPhoneOS</key>"); Text.AppendLine("\t<true/>"); Text.AppendLine("\t<key>UIStatusBarHidden</key>"); Text.AppendLine("\t<true/>"); Text.AppendLine("\t<key>UIRequiresFullScreen</key>"); Text.AppendLine("\t<true/>"); Text.AppendLine("\t<key>UIViewControllerBasedStatusBarAppearance</key>"); Text.AppendLine("\t<false/>"); Text.AppendLine("\t<key>UISupportedInterfaceOrientations</key>"); Text.AppendLine("\t<array>"); foreach (string Line in SupportedOrientations.Split("\r\n".ToCharArray())) { if (!string.IsNullOrWhiteSpace(Line)) { Text.AppendLine(Line); } } Text.AppendLine("\t</array>"); Text.AppendLine("\t<key>UIRequiredDeviceCapabilities</key>"); Text.AppendLine("\t<array>"); foreach (string Line in RequiredCaps.Split("\r\n".ToCharArray())) { if (!string.IsNullOrWhiteSpace(Line)) { Text.AppendLine(Line); } } Text.AppendLine("\t</array>"); Text.AppendLine("\t<key>CFBundleIcons</key>"); Text.AppendLine("\t<dict>"); Text.AppendLine("\t\t<key>CFBundlePrimaryIcon</key>"); Text.AppendLine("\t\t<dict>"); Text.AppendLine("\t\t\t<key>CFBundleIconFiles</key>"); Text.AppendLine("\t\t\t<array>"); Text.AppendLine("\t\t\t\t<string>Icon29.png</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>Icon40.png</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>Icon57.png</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t</array>"); Text.AppendLine("\t\t\t<key>UIPrerenderedIcon</key>"); Text.AppendLine("\t\t\t<true/>"); Text.AppendLine("\t\t</dict>"); Text.AppendLine("\t</dict>"); Text.AppendLine("\t<key>CFBundleIcons~ipad</key>"); Text.AppendLine("\t<dict>"); Text.AppendLine("\t\t<key>CFBundlePrimaryIcon</key>"); Text.AppendLine("\t\t<dict>"); Text.AppendLine("\t\t\t<key>CFBundleIconFiles</key>"); Text.AppendLine("\t\t\t<array>"); Text.AppendLine("\t\t\t\t<string>Icon29.png</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>Icon40.png</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>Icon50.png</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>Icon72.png</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>Icon76.png</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); Text.AppendLine("\t\t\t</array>"); Text.AppendLine("\t\t\t<key>UIPrerenderedIcon</key>"); Text.AppendLine("\t\t\t<true/>"); Text.AppendLine("\t\t</dict>"); Text.AppendLine("\t</dict>"); if (File.Exists(LaunchXib)) { // TODO: compile the xib via remote tool Text.AppendLine("\t<key>UILaunchStoryboardName</key>"); Text.AppendLine("\t<string>LaunchScreen</string>"); bSkipDefaultPNGs = true; } else { // this is a temp way to inject the iphone 6 images without needing to upgrade everyone's plist // eventually we want to generate this based on what the user has set in the project settings string[] IPhoneConfigs = { "Default-IPhone6-Landscape", "Landscape", "{375, 667}", "8.0", "Default-IPhone6", "Portrait", "{375, 667}", "8.0", "Default-IPhone6Plus-Landscape", "Landscape", "{414, 736}", "8.0", "Default-IPhone6Plus-Portrait", "Portrait", "{414, 736}", "8.0", "Default", "Landscape", "{320, 480}", "7.0", "Default", "Portrait", "{320, 480}", "7.0", "Default-568h", "Landscape", "{320, 568}", "7.0", "Default-568h", "Portrait", "{320, 568}", "7.0", }; Text.AppendLine("\t<key>UILaunchImages~iphone</key>"); Text.AppendLine("\t<array>"); for (int ConfigIndex = 0; ConfigIndex < IPhoneConfigs.Length; ConfigIndex += 4) { Text.AppendLine("\t\t<dict>"); Text.AppendLine("\t\t\t<key>UILaunchImageMinimumOSVersion</key>"); Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPhoneConfigs[ConfigIndex + 3])); Text.AppendLine("\t\t\t<key>UILaunchImageName</key>"); Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPhoneConfigs[ConfigIndex + 0])); Text.AppendLine("\t\t\t<key>UILaunchImageOrientation</key>"); Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPhoneConfigs[ConfigIndex + 1])); Text.AppendLine("\t\t\t<key>UILaunchImageSize</key>"); Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPhoneConfigs[ConfigIndex + 2])); Text.AppendLine("\t\t</dict>"); } // close it out Text.AppendLine("\t</array>"); // this is a temp way to inject the iPad Pro without needing to upgrade everyone's plist // eventually we want to generate this based on what the user has set in the project settings string[] IPadConfigs = { "Default-Landscape", "Landscape", "{768, 1024}", "7.0", "Default-Portrait", "Portrait", "{768, 1024}", "7.0", "Default-Landscape-1336", "Landscape", "{1024, 1366}", "9.0", "Default-Portrait-1336", "Portrait", "{1024, 1366}", "9.0", }; Text.AppendLine("\t<key>UILaunchImages~ipad</key>"); Text.AppendLine("\t<array>"); for (int ConfigIndex = 0; ConfigIndex < IPadConfigs.Length; ConfigIndex += 4) { Text.AppendLine("\t\t<dict>"); Text.AppendLine("\t\t\t<key>UILaunchImageMinimumOSVersion</key>"); Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPadConfigs[ConfigIndex + 3])); Text.AppendLine("\t\t\t<key>UILaunchImageName</key>"); Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPadConfigs[ConfigIndex + 0])); Text.AppendLine("\t\t\t<key>UILaunchImageOrientation</key>"); Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPadConfigs[ConfigIndex + 1])); Text.AppendLine("\t\t\t<key>UILaunchImageSize</key>"); Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPadConfigs[ConfigIndex + 2])); Text.AppendLine("\t\t</dict>"); } Text.AppendLine("\t</array>"); } Text.AppendLine("\t<key>CFBundleSupportedPlatforms</key>"); Text.AppendLine("\t<array>"); Text.AppendLine("\t\t<string>iPhoneOS</string>"); Text.AppendLine("\t</array>"); Text.AppendLine("\t<key>MinimumOSVersion</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", MinVersion)); // disable exempt encryption Text.AppendLine("\t<key>ITSAppUsesNonExemptEncryption</key>"); Text.AppendLine("\t<false/>"); // disable HTTPS requirement if (bDisableHTTPS) { Text.AppendLine("\t<key>NSAppTransportSecurity</key>"); Text.AppendLine("\t\t<dict>"); Text.AppendLine("\t\t\t<key>NSAllowsArbitraryLoads</key><true/>"); Text.AppendLine("\t\t</dict>"); } if (bEnableFacebookSupport) { Text.AppendLine("\t<key>FacebookAppID</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", FacebookAppID)); } if (!string.IsNullOrEmpty(ExtraData)) { ExtraData = ExtraData.Replace("\\n", "\n"); foreach (string Line in ExtraData.Split("\r\n".ToCharArray())) { if (!string.IsNullOrWhiteSpace(Line)) { Text.AppendLine("\t" + Line); } } } // Add remote-notifications as background mode if (bRemoteNotificationsSupported) { Text.AppendLine("\t<key>UIBackgroundModes</key>"); Text.AppendLine("\t<array>"); Text.AppendLine("\t\t<string>remote-notification</string>"); Text.AppendLine("\t</array>"); } Text.AppendLine("</dict>"); Text.AppendLine("</plist>"); // Create the intermediate directory if needed if (!Directory.Exists(IntermediateDirectory)) { Directory.CreateDirectory(IntermediateDirectory); } if (InThis != null && InThis.UPL != null) { // Allow UPL to modify the plist here XDocument XDoc; try { XDoc = XDocument.Parse(Text.ToString()); } catch (Exception e) { throw new BuildException("plist is invalid {0}\n{1}", e, Text.ToString()); } XDoc.DocumentType.InternalSubset = ""; InThis.UPL.ProcessPluginNode("None", "iosPListUpdates", "", ref XDoc); string result = XDoc.Declaration.ToString() + "\n" + XDoc.ToString().Replace("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"[]>", "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); File.WriteAllText(PListFile, result); } else { File.WriteAllText(PListFile, Text.ToString()); } if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac) { if (!Directory.Exists(AppDirectory)) { Directory.CreateDirectory(AppDirectory); } File.WriteAllText(AppDirectory + "/Info.plist", Text.ToString()); } return(bSkipDefaultPNGs); }
public static bool GenerateTVOSPList(string ProjectDirectory, bool bIsUE4Game, string GameName, bool bIsClient, string ProjectName, string InEngineDir, string AppDirectory, UnrealPluginLanguage UPL, string BundleID) { // @todo tvos: THIS! // generate the Info.plist for future use string BuildDirectory = ProjectDirectory + "/Build/TVOS"; bool bSkipDefaultPNGs = false; string IntermediateDirectory = (bIsUE4Game ? InEngineDir : ProjectDirectory) + "/Intermediate/TVOS"; string PListFile = IntermediateDirectory + "/" + GameName + "-Info.plist"; // @todo tvos: This is really nasty - both IOS and TVOS are setting static vars VersionUtilities.BuildDirectory = BuildDirectory; VersionUtilities.GameName = GameName; // read the old file string OldPListData = File.Exists(PListFile) ? File.ReadAllText(PListFile) : ""; // determine if there is a launch.xib //string LaunchXib = InEngineDir + "/Build/IOS/Resources/Interface/LaunchScreen.xib"; //if (File.Exists(BuildDirectory + "/Resources/Interface/LaunchScreen.xib")) //{ // LaunchXib = BuildDirectory + "/Resources/Interface/LaunchScreen.xib"; //} // get the settings from the ini file // plist replacements // @todo tvos: Are we going to make TVOS specific .ini files? DirectoryReference DirRef = bIsUE4Game ? (!string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath()) ? new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()) : null) : new DirectoryReference(ProjectDirectory); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirRef, UnrealTargetPlatform.IOS); // bundle display name string BundleDisplayName; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleDisplayName", out BundleDisplayName); // bundle identifier string BundleIdentifier; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier); if (!string.IsNullOrEmpty(BundleID)) { BundleIdentifier = BundleID; } // bundle name string BundleName; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleName", out BundleName); // short version string string BundleShortVersion; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "VersionInfo", out BundleShortVersion); // required capabilities string RequiredCaps = "\t\t<string>arm64</string>\n"; // minimum iOS version string MinVersion; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "MinimumTVOSVersion", out MinVersion)) { switch (MinVersion) { case "TVOS_9": MinVersion = "9.0"; break; } } else { MinVersion = "9.0"; } // extra plist data string ExtraData = ""; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "AdditionalPlistData", out ExtraData); // create the final display name, including converting all entities for XML use string FinalDisplayName = BundleDisplayName.Replace("[PROJECT_NAME]", ProjectName).Replace("_", ""); FinalDisplayName = FinalDisplayName.Replace("&", "&"); FinalDisplayName = FinalDisplayName.Replace("\"", """); FinalDisplayName = FinalDisplayName.Replace("\'", "'"); FinalDisplayName = FinalDisplayName.Replace("<", "<"); FinalDisplayName = FinalDisplayName.Replace(">", ">"); // generate the plist file StringBuilder Text = new StringBuilder(); Text.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); Text.AppendLine("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); Text.AppendLine("<plist version=\"1.0\">"); Text.AppendLine("<dict>"); Text.AppendLine("\t<key>CFBundleDevelopmentRegion</key>"); Text.AppendLine("\t<string>en</string>"); Text.AppendLine("\t<key>CFBundleDisplayName</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", EncodeBundleName(BundleDisplayName, ProjectName))); Text.AppendLine("\t<key>CFBundleExecutable</key>"); string BundleExecutable = bIsUE4Game ? (bIsClient ? "UE4Client" : "UE4Game") : (bIsClient ? GameName + "Client" : GameName); Text.AppendLine(string.Format("\t<string>{0}</string>", BundleExecutable)); Text.AppendLine("\t<key>CFBundleIdentifier</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", BundleIdentifier.Replace("[PROJECT_NAME]", ProjectName).Replace("_", ""))); Text.AppendLine("\t<key>CFBundleInfoDictionaryVersion</key>"); Text.AppendLine("\t<string>6.0</string>"); Text.AppendLine("\t<key>CFBundleName</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", EncodeBundleName(BundleName, ProjectName))); Text.AppendLine("\t<key>CFBundlePackageType</key>"); Text.AppendLine("\t<string>APPL</string>"); Text.AppendLine("\t<key>CFBundleSignature</key>"); Text.AppendLine("\t<string>????</string>"); Text.AppendLine("\t<key>CFBundleVersion</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", VersionUtilities.UpdateBundleVersion(OldPListData, InEngineDir))); Text.AppendLine("\t<key>CFBundleShortVersionString</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", BundleShortVersion)); Text.AppendLine("\t<key>LSRequiresIPhoneOS</key>"); Text.AppendLine("\t<true/>"); Text.AppendLine("\t<key>UIRequiredDeviceCapabilities</key>"); Text.AppendLine("\t<array>"); foreach (string Line in RequiredCaps.Split("\r\n".ToCharArray())) { if (!string.IsNullOrWhiteSpace(Line)) { Text.AppendLine(Line); } } Text.AppendLine("\t</array>"); Text.AppendLine("\t<key>TVTopShelfImage</key>"); Text.AppendLine("\t<dict>"); Text.AppendLine("\t\t<key>TVTopShelfPrimaryImage</key>"); Text.AppendLine("\t\t<string>Top Shelf Image</string>"); Text.AppendLine("\t\t<key>TVTopShelfPrimaryImageWide</key>"); Text.AppendLine("\t\t<string>Top Shelf Image Wide</string>"); Text.AppendLine("\t</dict>"); Text.AppendLine("\t<key>UILaunchImages</key>"); Text.AppendLine("\t<array>"); Text.AppendLine("\t\t<dict>"); Text.AppendLine("\t\t\t<key>UILaunchImageSize</key>"); Text.AppendLine("\t\t\t<string>{1920, 1080}</string>"); Text.AppendLine("\t\t\t<key>UILaunchImageName</key>"); Text.AppendLine("\t\t\t<string>Launch Image</string>"); Text.AppendLine("\t\t\t<key>UILaunchImageMinimumOSVersion</key>"); Text.AppendLine("\t\t\t<string>9.0</string>"); Text.AppendLine("\t\t\t<key>UILaunchImageOrientation</key>"); Text.AppendLine("\t\t\t<string>Landscape</string>"); Text.AppendLine("\t\t</dict>"); Text.AppendLine("\t</array>"); Text.AppendLine("\t<key>CFBundleIcons</key>"); Text.AppendLine("\t<dict>"); Text.AppendLine("\t\t<key>CFBundlePrimaryIcon</key>"); Text.AppendLine("\t\t<string>App Icon</string>"); Text.AppendLine("\t</dict>"); /* Text.AppendLine("\t<key>CFBundleIcons</key>"); * Text.AppendLine("\t<dict>"); * Text.AppendLine("\t\t<key>CFBundlePrimaryIcon</key>"); * Text.AppendLine("\t\t<dict>"); * Text.AppendLine("\t\t\t<key>CFBundleIconFiles</key>"); * Text.AppendLine("\t\t\t<array>"); * Text.AppendLine("\t\t\t\t<string>Icon29.png</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t\t<string>Icon40.png</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t\t<string>Icon57.png</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t</array>"); * Text.AppendLine("\t\t\t<key>UIPrerenderedIcon</key>"); * Text.AppendLine("\t\t\t<true/>"); * Text.AppendLine("\t\t</dict>"); * Text.AppendLine("\t</dict>"); * Text.AppendLine("\t<key>CFBundleIcons~ipad</key>"); * Text.AppendLine("\t<dict>"); * Text.AppendLine("\t\t<key>CFBundlePrimaryIcon</key>"); * Text.AppendLine("\t\t<dict>"); * Text.AppendLine("\t\t\t<key>CFBundleIconFiles</key>"); * Text.AppendLine("\t\t\t<array>"); * Text.AppendLine("\t\t\t\t<string>Icon29.png</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t\t<string>Icon40.png</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t\t<string>Icon50.png</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t\t<string>Icon72.png</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t\t<string>Icon76.png</string>"); * Text.AppendLine("\t\t\t\t<string>[email protected]</string>"); * Text.AppendLine("\t\t\t</array>"); * Text.AppendLine("\t\t\t<key>UIPrerenderedIcon</key>"); * Text.AppendLine("\t\t\t<true/>"); * Text.AppendLine("\t\t</dict>"); * Text.AppendLine("\t</dict>"); * if (File.Exists(LaunchXib)) * { * // TODO: compile the xib via remote tool * Text.AppendLine("\t<key>UILaunchStoryboardName</key>"); * Text.AppendLine("\t<string>LaunchScreen</string>"); * bSkipDefaultPNGs = true; * } * else * { * // this is a temp way to inject the iphone 6 images without needing to upgrade everyone's plist * // eventually we want to generate this based on what the user has set in the project settings * string[] IPhoneConfigs = * { * "Default-IPhone6", "Landscape", "{375, 667}", * "Default-IPhone6", "Portrait", "{375, 667}", * "Default-IPhone6Plus-Landscape", "Landscape", "{414, 736}", * "Default-IPhone6Plus-Portrait", "Portrait", "{414, 736}", * "Default", "Landscape", "{320, 480}", * "Default", "Portrait", "{320, 480}", * "Default-568h", "Landscape", "{320, 568}", * "Default-568h", "Portrait", "{320, 568}", * }; * * Text.AppendLine("\t<key>UILaunchImages~iphone</key>"); * Text.AppendLine("\t<array>"); * for (int ConfigIndex = 0; ConfigIndex < IPhoneConfigs.Length; ConfigIndex += 3) * { * Text.AppendLine("\t\t<dict>"); * Text.AppendLine("\t\t\t<key>UILaunchImageMinimumOSVersion</key>"); * Text.AppendLine("\t\t\t<string>8.0</string>"); * Text.AppendLine("\t\t\t<key>UILaunchImageName</key>"); * Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPhoneConfigs[ConfigIndex + 0])); * Text.AppendLine("\t\t\t<key>UILaunchImageOrientation</key>"); * Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPhoneConfigs[ConfigIndex + 1])); * Text.AppendLine("\t\t\t<key>UILaunchImageSize</key>"); * Text.AppendLine(string.Format("\t\t\t<string>{0}</string>", IPhoneConfigs[ConfigIndex + 2])); * Text.AppendLine("\t\t</dict>"); * } * * // close it out * Text.AppendLine("\t</array>"); * } * Text.AppendLine("\t<key>UILaunchImages~ipad</key>"); * Text.AppendLine("\t<array>"); * Text.AppendLine("\t\t<dict>"); * Text.AppendLine("\t\t\t<key>UILaunchImageMinimumOSVersion</key>"); * Text.AppendLine("\t\t\t<string>7.0</string>"); * Text.AppendLine("\t\t\t<key>UILaunchImageName</key>"); * Text.AppendLine("\t\t\t<string>Default-Landscape</string>"); * Text.AppendLine("\t\t\t<key>UILaunchImageOrientation</key>"); * Text.AppendLine("\t\t\t<string>Landscape</string>"); * Text.AppendLine("\t\t\t<key>UILaunchImageSize</key>"); * Text.AppendLine("\t\t\t<string>{768, 1024}</string>"); * Text.AppendLine("\t\t</dict>"); * Text.AppendLine("\t\t<dict>"); * Text.AppendLine("\t\t\t<key>UILaunchImageMinimumOSVersion</key>"); * Text.AppendLine("\t\t\t<string>7.0</string>"); * Text.AppendLine("\t\t\t<key>UILaunchImageName</key>"); * Text.AppendLine("\t\t\t<string>Default-Portrait</string>"); * Text.AppendLine("\t\t\t<key>UILaunchImageOrientation</key>"); * Text.AppendLine("\t\t\t<string>Portrait</string>"); * Text.AppendLine("\t\t\t<key>UILaunchImageSize</key>"); * Text.AppendLine("\t\t\t<string>{768, 1024}</string>"); * Text.AppendLine("\t\t</dict>"); * Text.AppendLine("\t</array>"); * Text.AppendLine("\t<key>CFBundleSupportedPlatforms</key>"); * Text.AppendLine("\t<array>"); * Text.AppendLine("\t\t<string>iPhoneOS</string>"); * Text.AppendLine("\t</array>"); * Text.AppendLine("\t<key>MinimumOSVersion</key>"); * Text.AppendLine(string.Format("\t<string>{0}</string>", MinVersion)); * if (!string.IsNullOrEmpty(ExtraData)) * { * ExtraData = ExtraData.Replace("\\n", "\n"); * foreach (string Line in ExtraData.Split("\r\n".ToCharArray())) * { * if (!string.IsNullOrWhiteSpace(Line)) * { * Text.AppendLine("\t" + Line); * } * } * }*/ // write the iCloud container identifier, if present in the old file if (!string.IsNullOrEmpty(OldPListData)) { int index = OldPListData.IndexOf("ICloudContainerIdentifier"); if (index > 0) { index = OldPListData.IndexOf("<string>", index) + 8; int length = OldPListData.IndexOf("</string>", index) - index; string ICloudContainerIdentifier = OldPListData.Substring(index, length); Text.AppendLine("\t<key>ICloudContainerIdentifier</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", ICloudContainerIdentifier)); } } Text.AppendLine("</dict>"); Text.AppendLine("</plist>"); // Create the intermediate directory if needed if (!Directory.Exists(IntermediateDirectory)) { Directory.CreateDirectory(IntermediateDirectory); } if (UPL != null) { // Allow UPL to modify the plist here XDocument XDoc; try { XDoc = XDocument.Parse(Text.ToString()); } catch (Exception e) { throw new BuildException("plist is invalid {0}\n{1}", e, Text.ToString()); } XDoc.DocumentType.InternalSubset = ""; UPL.ProcessPluginNode("None", "iosPListUpdates", "", ref XDoc); string result = XDoc.Declaration.ToString() + "\n" + XDoc.ToString().Replace("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"[]>", "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); File.WriteAllText(PListFile, result); } else { File.WriteAllText(PListFile, Text.ToString()); } if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac) { if (!Directory.Exists(AppDirectory)) { Directory.CreateDirectory(AppDirectory); } File.WriteAllText(AppDirectory + "/Info.plist", Text.ToString()); } return(bSkipDefaultPNGs); }
public override void ValidateTarget(TargetRules Target) { // WindowsTargetRules are reused for HoloLens, so that build modules can keep the model that reuses "windows" configs for most cases // That means overriding those settings here that need to be adjusted for HoloLens // Compiler version and pix flags must be reloaded from the HoloLens hive // Currently BP-only projects don't load build-related settings from their remote ini when building UE4Game.exe // (see TargetRules.cs, where the possibly-null project directory is passed to ConfigCache.ReadSettings). // It's important for HoloLens that we *do* use the project-specific settings when building (VS 2017 vs 2015 and // retail Windows Store are both examples). Possibly this should be done on all platforms? But in the interest // of not changing behavior on other platforms I'm limiting the scope. DirectoryReference IniDirRef = DirectoryReference.FromFile(Target.ProjectFile); if (IniDirRef == null && !string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath())) { IniDirRef = new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()); } // Stash the current compiler choice (accounts for command line) in case ReadSettings reverts it to default WindowsCompiler CompilerBeforeReadSettings = Target.HoloLensPlatform.Compiler; ConfigCache.ReadSettings(IniDirRef, Platform, Target.HoloLensPlatform); if (Target.HoloLensPlatform.Compiler == WindowsCompiler.Default) { if (CompilerBeforeReadSettings != WindowsCompiler.Default) { // Previous setting was more specific, use that Target.HoloLensPlatform.Compiler = CompilerBeforeReadSettings; } else { Target.HoloLensPlatform.Compiler = WindowsPlatform.GetDefaultCompiler(Target.ProjectFile); } } if (!Target.bGenerateProjectFiles) { Log.TraceInformationOnce("Using {0} architecture for deploying to HoloLens device", Target.HoloLensPlatform.Architecture); } Target.WindowsPlatform.Compiler = Target.HoloLensPlatform.Compiler; Target.WindowsPlatform.Architecture = Target.HoloLensPlatform.Architecture; Target.WindowsPlatform.bPixProfilingEnabled = Target.HoloLensPlatform.bPixProfilingEnabled; Target.WindowsPlatform.bUseWindowsSDK10 = true; Target.bDeployAfterCompile = true; Target.bCompileNvCloth = false; // requires CUDA // Disable Simplygon support if compiling against the NULL RHI. if (Target.GlobalDefinitions.Contains("USE_NULL_RHI=1")) { Target.bCompileSpeedTree = false; } // Use shipping binaries to avoid dependency on nvToolsExt which fails WACK. if (Target.Configuration == UnrealTargetConfiguration.Shipping) { Target.bUseShippingPhysXLibraries = true; } // Be resilient to SDKs being uninstalled but still referenced in the INI file VersionNumber SelectedWindowsSdkVersion; DirectoryReference SelectedWindowsSdkDir; if (!WindowsPlatform.TryGetWindowsSdkDir(Target.HoloLensPlatform.Win10SDKVersionString, out SelectedWindowsSdkVersion, out SelectedWindowsSdkDir)) { Target.HoloLensPlatform.Win10SDKVersionString = "Latest"; } // Initialize the VC environment for the target, and set all the version numbers to the concrete values we chose. VCEnvironment Environment = VCEnvironment.Create(Target.WindowsPlatform.Compiler, Platform, Target.WindowsPlatform.Architecture, Target.WindowsPlatform.CompilerVersion, Target.HoloLensPlatform.Win10SDKVersionString, null); Target.WindowsPlatform.Environment = Environment; Target.WindowsPlatform.Compiler = Environment.Compiler; Target.WindowsPlatform.CompilerVersion = Environment.CompilerVersion.ToString(); Target.WindowsPlatform.WindowsSdkVersion = Environment.WindowsSdkVersion.ToString(); // Windows 10 SDK version // Auto-detect latest compatible by default (recommended), allow for explicit override if necessary // Validate that the SDK isn't too old, and that the combination of VS and SDK is supported. Target.HoloLensPlatform.Win10SDKVersion = new Version(Environment.WindowsSdkVersion.ToString()); if (!Target.bGenerateProjectFiles) { Log.TraceInformationOnce("Building using Windows SDK version {0} for HoloLens", Target.HoloLensPlatform.Win10SDKVersion); if (Target.HoloLensPlatform.Win10SDKVersion < MinimumSDKVersionRecommended) { Log.TraceWarning("Your Windows SDK version {0} is older than the minimum recommended version ({1}) for HoloLens. Consider upgrading.", Target.HoloLensPlatform.Win10SDKVersion, MinimumSDKVersionRecommended); } else if (Target.HoloLensPlatform.Win10SDKVersion > MaximumSDKVersionTested) { Log.TraceInformationOnce("Your Windows SDK version ({0}) for HoloLens is newer than the highest tested with this version of UBT ({1}). This is probably fine, but if you encounter issues consider using an earlier SDK.", Target.HoloLensPlatform.Win10SDKVersion, MaximumSDKVersionTested); } } HoloLensExports.InitWindowsSdkToolPath(Target.HoloLensPlatform.Win10SDKVersion.ToString()); }
public static bool GenerateTVOSPList(string ProjectDirectory, bool bIsUE4Game, string GameName, bool bIsClient, string ProjectName, string InEngineDir, string AppDirectory, UnrealPluginLanguage UPL, string BundleID) { // @todo tvos: THIS! // generate the Info.plist for future use string BuildDirectory = ProjectDirectory + "/Build/TVOS"; bool bSkipDefaultPNGs = false; string IntermediateDirectory = (bIsUE4Game ? InEngineDir : ProjectDirectory) + "/Intermediate/TVOS"; string PListFile = IntermediateDirectory + "/" + GameName + "-Info.plist"; // @todo tvos: This is really nasty - both IOS and TVOS are setting static vars VersionUtilities.BuildDirectory = BuildDirectory; VersionUtilities.GameName = GameName; // read the old file string OldPListData = File.Exists(PListFile) ? File.ReadAllText(PListFile) : ""; // get the settings from the ini file // plist replacements // @todo tvos: Are we going to make TVOS specific .ini files? DirectoryReference DirRef = bIsUE4Game ? (!string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath()) ? new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()) : null) : new DirectoryReference(ProjectDirectory); ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirRef, UnrealTargetPlatform.IOS); // bundle display name string BundleDisplayName; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleDisplayName", out BundleDisplayName); // bundle identifier string BundleIdentifier; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier); if (!string.IsNullOrEmpty(BundleID)) { BundleIdentifier = BundleID; } // bundle name string BundleName; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleName", out BundleName); // short version string string BundleShortVersion; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "VersionInfo", out BundleShortVersion); // required capabilities string RequiredCaps = "\t\t<string>arm64</string>\n"; // minimum iOS version string MinVersion; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "MinimumTVOSVersion", out MinVersion)) { switch (MinVersion) { case "TVOS_9": MinVersion = "9.0"; break; } } else { MinVersion = "9.0"; } // extra plist data string ExtraData = ""; Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "AdditionalPlistData", out ExtraData); // create the final display name, including converting all entities for XML use string FinalDisplayName = BundleDisplayName.Replace("[PROJECT_NAME]", ProjectName).Replace("_", ""); FinalDisplayName = FinalDisplayName.Replace("&", "&"); FinalDisplayName = FinalDisplayName.Replace("\"", """); FinalDisplayName = FinalDisplayName.Replace("\'", "'"); FinalDisplayName = FinalDisplayName.Replace("<", "<"); FinalDisplayName = FinalDisplayName.Replace(">", ">"); // generate the plist file StringBuilder Text = new StringBuilder(); Text.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); Text.AppendLine("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); Text.AppendLine("<plist version=\"1.0\">"); Text.AppendLine("<dict>"); Text.AppendLine("\t<key>CFBundleDevelopmentRegion</key>"); Text.AppendLine("\t<string>en</string>"); Text.AppendLine("\t<key>CFBundleDisplayName</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", EncodeBundleName(BundleDisplayName, ProjectName))); Text.AppendLine("\t<key>CFBundleExecutable</key>"); string BundleExecutable = bIsUE4Game ? (bIsClient ? "UE4Client" : "UE4Game") : (bIsClient ? GameName + "Client" : GameName); Text.AppendLine(string.Format("\t<string>{0}</string>", BundleExecutable)); Text.AppendLine("\t<key>CFBundleIdentifier</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", BundleIdentifier.Replace("[PROJECT_NAME]", ProjectName).Replace("_", ""))); Text.AppendLine("\t<key>CFBundleInfoDictionaryVersion</key>"); Text.AppendLine("\t<string>6.0</string>"); Text.AppendLine("\t<key>CFBundleName</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", EncodeBundleName(BundleName, ProjectName))); Text.AppendLine("\t<key>CFBundlePackageType</key>"); Text.AppendLine("\t<string>APPL</string>"); Text.AppendLine("\t<key>CFBundleSignature</key>"); Text.AppendLine("\t<string>????</string>"); Text.AppendLine("\t<key>CFBundleVersion</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", VersionUtilities.UpdateBundleVersion(OldPListData, InEngineDir))); Text.AppendLine("\t<key>CFBundleShortVersionString</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", BundleShortVersion)); Text.AppendLine("\t<key>LSRequiresIPhoneOS</key>"); Text.AppendLine("\t<true/>"); Text.AppendLine("\t<key>UIRequiredDeviceCapabilities</key>"); Text.AppendLine("\t<array>"); foreach (string Line in RequiredCaps.Split("\r\n".ToCharArray())) { if (!string.IsNullOrWhiteSpace(Line)) { Text.AppendLine(Line); } } Text.AppendLine("\t</array>"); Text.AppendLine("\t<key>TVTopShelfImage</key>"); Text.AppendLine("\t<dict>"); Text.AppendLine("\t\t<key>TVTopShelfPrimaryImage</key>"); Text.AppendLine("\t\t<string>Top Shelf Image</string>"); Text.AppendLine("\t\t<key>TVTopShelfPrimaryImageWide</key>"); Text.AppendLine("\t\t<string>Top Shelf Image Wide</string>"); Text.AppendLine("\t</dict>"); Text.AppendLine("\t<key>CFBundleIcons</key>"); Text.AppendLine("\t<dict>"); Text.AppendLine("\t\t<key>CFBundlePrimaryIcon</key>"); Text.AppendLine("\t\t<string>App Icon</string>"); Text.AppendLine("\t</dict>"); Text.AppendLine("\t<key>UILaunchStoryboardName</key>"); Text.AppendLine("\t<string>LaunchScreen</string>"); // write the iCloud container identifier, if present in the old file if (!string.IsNullOrEmpty(OldPListData)) { int index = OldPListData.IndexOf("ICloudContainerIdentifier"); if (index > 0) { index = OldPListData.IndexOf("<string>", index) + 8; int length = OldPListData.IndexOf("</string>", index) - index; string ICloudContainerIdentifier = OldPListData.Substring(index, length); Text.AppendLine("\t<key>ICloudContainerIdentifier</key>"); Text.AppendLine(string.Format("\t<string>{0}</string>", ICloudContainerIdentifier)); } } Text.AppendLine("</dict>"); Text.AppendLine("</plist>"); // Create the intermediate directory if needed if (!Directory.Exists(IntermediateDirectory)) { Directory.CreateDirectory(IntermediateDirectory); } if (UPL != null) { // Allow UPL to modify the plist here XDocument XDoc; try { XDoc = XDocument.Parse(Text.ToString()); } catch (Exception e) { throw new BuildException("plist is invalid {0}\n{1}", e, Text.ToString()); } XDoc.DocumentType.InternalSubset = ""; UPL.ProcessPluginNode("None", "iosPListUpdates", "", ref XDoc); string result = XDoc.Declaration.ToString() + "\n" + XDoc.ToString().Replace("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"[]>", "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); File.WriteAllText(PListFile, result); } else { File.WriteAllText(PListFile, Text.ToString()); } if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac) { if (!Directory.Exists(AppDirectory)) { Directory.CreateDirectory(AppDirectory); } File.WriteAllText(AppDirectory + "/Info.plist", Text.ToString()); } return(bSkipDefaultPNGs); }
public bool HasIcons(DirectoryReference ProjectDirectoryName) { string IconDir = (((ProjectDirectoryName != null) ? ProjectDirectoryName.ToString() : (string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath()) ? UnrealBuildTool.EngineDirectory.ToString() : UnrealBuildTool.GetRemoteIniPath()))) + "/Build/" + (this.Platform == UnrealTargetPlatform.IOS ? "IOS" : "TVOS") + "/Resources/Graphics"; if (Directory.Exists(IconDir)) { FileInfo[] Files = (new DirectoryInfo(IconDir).GetFiles("Icon*.*", SearchOption.AllDirectories)); if (Files.Length > 0) { return(true); } } return(false); }