public static bool CanCreateMapPaks(ProjectParams Param) { bool UseAsyncLevelLoading = false; var ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Param.RawProjectPath), UnrealTargetPlatform.HTML5); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UseAsyncLevelLoading", out UseAsyncLevelLoading); if (Param.Run) { return(false); } return(UseAsyncLevelLoading); }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { // Engine non-ufs (binaries) if (SC.bStageCrashReporter) { FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(CommandUtils.EngineDirectory, "CrashReportClient", SC.StageTargetPlatform.PlatformType, UnrealTargetConfiguration.Shipping, null); if (FileReference.Exists(ReceiptFileName)) { DirectoryReference EngineDir = CommandUtils.EngineDirectory; DirectoryReference ProjectDir = DirectoryReference.FromFile(Params.RawProjectPath); TargetReceipt Receipt = TargetReceipt.Read(ReceiptFileName, EngineDir, ProjectDir); SC.StageBuildProductsFromReceipt(Receipt, true, false); } } // Stage all the build products foreach (StageTarget Target in SC.StageTargets) { SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles); } // Copy the splash screen, windows specific FileReference SplashImage = FileReference.Combine(SC.ProjectRoot, "Content", "Splash", "Splash.bmp"); if (FileReference.Exists(SplashImage)) { SC.StageFile(StagedFileType.NonUFS, SplashImage); } // Stage the bootstrap executable if (!Params.NoBootstrapExe) { foreach (StageTarget Target in SC.StageTargets) { BuildProduct Executable = Target.Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable); if (Executable != null) { // only create bootstraps for executables List <StagedFileReference> StagedFiles = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList(); if (StagedFiles.Count > 0 && Executable.Path.HasExtension(".exe")) { string BootstrapArguments = ""; if (!ShouldStageCommandLine(Params, SC)) { if (!SC.IsCodeBasedProject) { BootstrapArguments = String.Format("..\\..\\..\\{0}\\{0}.uproject", SC.ShortProjectName); } else { BootstrapArguments = SC.ShortProjectName; } } string BootstrapExeName; if (SC.StageTargetConfigurations.Count > 1) { BootstrapExeName = Executable.Path.GetFileName(); } else if (Params.IsCodeBasedProject) { BootstrapExeName = Target.Receipt.TargetName + ".exe"; } else { BootstrapExeName = SC.ShortProjectName + ".exe"; } foreach (StagedFileReference StagePath in StagedFiles) { StageBootstrapExecutable(SC, BootstrapExeName, Executable.Path, StagePath, BootstrapArguments); } } } } } }
// -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- #region AMAZON S3 public void UploadToS3(DeploymentContext SC, string OutputFilename) { ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(SC.RawProjectPath), SC.StageTargetPlatform.PlatformType); bool Upload = false; string Region = ""; string KeyId = ""; string AccessKey = ""; string BucketName = ""; string FolderName = ""; if (!Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UploadToS3", out Upload) || !Upload) { return; } bool AmazonIdentity = Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3Region", out Region) && Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3KeyID", out KeyId) && Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3SecretAccessKey", out AccessKey) && Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3BucketName", out BucketName); if (!AmazonIdentity) { LogInformation("Amazon S3 Incorrectly configured"); return; } Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3FolderName", out FolderName); if (FolderName == "") { FolderName = SC.ShortProjectName; } else { // strip any before and after folder "/" FolderName = Regex.Replace(Regex.Replace(FolderName, "^/+", ""), "/+$", ""); } List <Task> UploadTasks = new List <Task>(); long msTimeOut = 0; foreach (KeyValuePair <string, string> Entry in SC.ArchivedFiles) { FileInfo Info = new FileInfo(Entry.Key); UploadTasks.Add(UploadToS3Worker(Info, Region, KeyId, AccessKey, BucketName, FolderName)); if (msTimeOut < Info.Length) { msTimeOut = Info.Length; } } msTimeOut /= 100; // [miliseconds] give 10 secs for each ~MB ( (10s * 1000ms) / ( 1024KB * 1024MB * 1000ms ) ) if (msTimeOut < (100 * 1000)) // HttpClient: default timeout is 100 sec { msTimeOut = 100 * 1000; } LogInformation("Upload Timeout set to: " + (msTimeOut / 1000) + "secs"); Task.WaitAll(UploadTasks.ToArray(), (int)msTimeOut); // set timeout [miliseconds] string URL = "https://" + BucketName + ".s3.amazonaws.com/" + FolderName + "/" + OutputFilename; LogInformation("Your project's shareable link is: " + URL); LogInformation("Upload Tasks finished."); }
public Noesis(ReadOnlyTargetRules Target) : base(Target) { Type = ModuleType.External; string NoesisBasePath = ModuleDirectory + "/NoesisSDK/"; string NoesisIncludePath = NoesisBasePath + "Include/"; string NoesisInteractivityIncludePath = NoesisBasePath + "Src/Packages/App/Interactivity/Include/"; PublicIncludePaths.Add(ModuleDirectory); PublicIncludePaths.Add(NoesisIncludePath); PublicIncludePaths.Add(NoesisInteractivityIncludePath); // Let's try to make sure the right version of the SDK is in the right place. const string RequiredVersionName = "2.2.5"; PublicDefinitions.Add("NOESIS_VERSION_NAME=\"" + RequiredVersionName + "\""); if (!Directory.Exists(NoesisBasePath)) { throw new BuildException("Could not find NoesisGUI SDK in " + NoesisBasePath + ". Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Bin")) { throw new BuildException("Could not find NoesisGUI SDK Bin directory in " + NoesisBasePath + "Bin. Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Include")) { throw new BuildException("Could not find NoesisGUI SDK Include directory in " + NoesisBasePath + "Include. Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Lib")) { throw new BuildException("Could not find NoesisGUI SDK Lib directory in " + NoesisBasePath + "Lib. Minimum required version is " + RequiredVersionName); } string NoesisSdkVersionInfo; try { NoesisSdkVersionInfo = File.ReadAllText(NoesisBasePath + "version.txt"); } catch (Exception) { throw new BuildException("Could not find NoesisGUI SDK version.txt in " + NoesisBasePath + "version.txt. Minimum required version is " + RequiredVersionName); } string[] LineSplit = NoesisSdkVersionInfo.Split('\n'); string[] SplitVersion = LineSplit[1].Split(' '); Version InstalledVersion = new Version(SplitVersion[0]); Version RequiredVersion = new Version(RequiredVersionName); if (InstalledVersion != RequiredVersion) { throw new BuildException("Wrong version of the NoesisGUI SDK installed in " + NoesisBasePath + ". Required version is " + RequiredVersionName); } PublicSystemIncludePaths.Add(NoesisIncludePath); if (Target.Platform == UnrealTargetPlatform.Win64) { string NoesisLibPath = NoesisBasePath + "Lib/windows_x86_64/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); string NoesisDllPath = "/NoesisSDK/Bin/windows_x86_64/Noesis.dll"; string NoesisDllTargetPath = "/Binaries/Win64/Noesis.dll"; if (Target.ProjectFile != null) { CopyNoesisDll(ModuleDirectory + NoesisDllPath, DirectoryReference.FromFile(Target.ProjectFile).ToString() + NoesisDllTargetPath); } CopyNoesisDll(ModuleDirectory + NoesisDllPath, ModuleDirectory + "/../.." + NoesisDllTargetPath); if (System.IO.File.Exists(Target.RelativeEnginePath + NoesisDllTargetPath)) { System.IO.File.Delete(Target.RelativeEnginePath + NoesisDllTargetPath); } if (Target.LinkType == TargetLinkType.Monolithic) { RuntimeDependencies.Add("$(ProjectDir)" + NoesisDllTargetPath); } else { RuntimeDependencies.Add("$(EngineDir)" + NoesisDllTargetPath); } } else if (Target.Platform == UnrealTargetPlatform.Mac) { string NoesisLibPath = NoesisBasePath + "Bin/osx/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.dylib"); string NoesisDylibPath = "/NoesisSDK/Bin/osx/Noesis.dylib"; RuntimeDependencies.Add(ModuleDirectory + NoesisDylibPath); } else if (Target.Platform == UnrealTargetPlatform.IOS) { string NoesisLibPath = NoesisBasePath + "Lib/ios/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis"); PublicFrameworks.Add("CoreText"); } else if (Target.Platform == UnrealTargetPlatform.Android) { string NoesisLibPath = NoesisBasePath + "Bin/android_arm/"; PublicLibraryPaths.Add(NoesisLibPath); string NoesisLib64Path = NoesisBasePath + "Bin/android_arm64/"; PublicLibraryPaths.Add(NoesisLib64Path); PublicAdditionalLibraries.Add("Noesis"); string NoesisAplPath = "/Noesis_APL.xml"; AdditionalPropertiesForReceipt.Add("AndroidPlugin", ModuleDirectory + NoesisAplPath); } else if (Target.Platform == UnrealTargetPlatform.PS4) { string NoesisLibPath = NoesisBasePath + "Lib/ps4/"; PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.a"); } else if (Target.Platform == UnrealTargetPlatform.XboxOne) { string NoesisLibPath = NoesisBasePath + "Bin/xbox_one/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); } else if (Target.Platform == UnrealTargetPlatform.HTML5) { string NoesisLibPath = NoesisBasePath + "Bin/wasm/"; PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.bc"); } }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { if (SC.bStageCrashReporter) { FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(CommandUtils.EngineDirectory, "CrashReportClient", SC.StageTargetPlatform.PlatformType, UnrealTargetConfiguration.Shipping, null); if (FileReference.Exists(ReceiptFileName)) { DirectoryReference EngineDir = CommandUtils.EngineDirectory; DirectoryReference ProjectDir = DirectoryReference.FromFile(Params.RawProjectPath); TargetReceipt Receipt = TargetReceipt.Read(ReceiptFileName, EngineDir, ProjectDir); SC.StageBuildProductsFromReceipt(Receipt, true, false); } } // Stage all the build products Console.WriteLine("Staging all {0} build products", SC.StageTargets.Count); int BuildProductIdx = 0; foreach (StageTarget Target in SC.StageTargets) { Console.WriteLine(" Product {0}: {1}", BuildProductIdx, Target.Receipt.TargetName); SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles); ++BuildProductIdx; } FileReference SplashImage = FileReference.Combine(SC.ProjectRoot, "Content", "Splash", "Splash.bmp"); if (FileReference.Exists(SplashImage)) { SC.StageFile(StagedFileType.NonUFS, SplashImage); } // Stage the bootstrap executable if (!Params.NoBootstrapExe) { foreach (StageTarget Target in SC.StageTargets) { BuildProduct Executable = Target.Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable); if (Executable != null) { // only create bootstraps for executables string FullExecutablePath = Path.GetFullPath(Executable.Path.FullName); if (Executable.Path.FullName.Replace("\\", "/").Contains("/" + TargetPlatformType.ToString() + "/")) { string BootstrapArguments = ""; if (!ShouldStageCommandLine(Params, SC)) { if (!SC.IsCodeBasedProject) { BootstrapArguments = String.Format("\\\"../../../{0}/{0}.uproject\\\"", SC.ShortProjectName); } else { BootstrapArguments = SC.ShortProjectName; } } string BootstrapExeName; if (SC.StageTargetConfigurations.Count > 1) { BootstrapExeName = Path.GetFileName(Executable.Path.FullName); } else if (Params.IsCodeBasedProject) { BootstrapExeName = Target.Receipt.TargetName; } else { BootstrapExeName = SC.ShortProjectName; } List <StagedFileReference> StagePaths = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList(); foreach (StagedFileReference StagePath in StagePaths) { StageBootstrapExecutable(SC, BootstrapExeName + ".sh", FullExecutablePath, StagePath.Name, BootstrapArguments); } } } } } }
public void UploadToS3(DeploymentContext SC) { ConfigCacheIni Ini = ConfigCacheIni.CreateConfigCacheIni(SC.StageTargetPlatform.PlatformType, "Engine", DirectoryReference.FromFile(SC.RawProjectPath)); bool Upload = false; string KeyId = ""; string AccessKey = ""; string BucketName = ""; string FolderName = ""; if (Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UploadToS3", out Upload)) { if (!Upload) { return; } } else { return; } bool AmazonIdentity = Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3KeyID", out KeyId) && Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3SecretAccessKey", out AccessKey) && Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3BucketName", out BucketName) && Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3FolderName", out FolderName); if (!AmazonIdentity) { Log("Amazon S3 Incorrectly configured"); return; } if (FolderName == "") { FolderName = SC.ShortProjectName; } List <Task> UploadTasks = new List <Task>(); foreach (KeyValuePair <string, string> Entry in SC.ArchivedFiles) { FileInfo Info = new FileInfo(Entry.Key); UploadTasks.Add(Task.Factory.StartNew(() => UploadToS3Worker(Info, KeyId, AccessKey, BucketName, FolderName))); } Task.WaitAll(UploadTasks.ToArray()); string URL = "http://" + BucketName + ".s3.amazonaws.com/" + FolderName + "/" + SC.ShortProjectName + ".html"; Log("Your project's shareable link is: " + URL); Log("Upload Tasks finished."); }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { Log("Package {0}", Params.RawProjectPath); Log("Setting Emscripten SDK for packaging.."); HTML5SDKInfo.SetupEmscriptenTemp(); HTML5SDKInfo.SetUpEmscriptenConfigFile(); string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Binaries", "HTML5"); if (!Directory.Exists(PackagePath)) { Directory.CreateDirectory(PackagePath); } // ini configurations var ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5); bool targetWebGL1 = false; // inverted checked - this will be going away soon... if (ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "TargetWebGL1", out targetWebGL1)) { targetWebGL2 = !targetWebGL1; } // Debug and Development builds are not uncompressed to: // - speed up iteration times // - ensure (IndexedDB) data are not cached/used // Shipping builds "can be": // - compressed // - (IndexedDB) cached if (Params.ClientConfigsToBuild[0].ToString() == "Shipping") { ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "Compressed", out Compressed); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableIndexedDB", out enableIndexedDB); } Log("HTML5Platform.Automation: TargetWebGL2 = " + targetWebGL2); Log("HTML5Platform.Automation: Compressed = " + Compressed); Log("HTML5Platform.Automation: EnableIndexedDB = " + enableIndexedDB); string FinalDataLocation = Path.Combine(PackagePath, Params.ShortProjectName) + ".data"; if (HTMLPakAutomation.CanCreateMapPaks(Params)) { HTMLPakAutomation PakAutomation = new HTMLPakAutomation(Params, SC); // Create Necessary Paks. PakAutomation.CreateEnginePak(); PakAutomation.CreateGamePak(); PakAutomation.CreateContentDirectoryPak(); // Create Emscripten Package from Necessary Paks. - This will be the VFS. PakAutomation.CreateEmscriptenDataPackage(PackagePath, FinalDataLocation); // Create All Map Paks which will be downloaded on the fly. PakAutomation.CreateMapPak(); // Create Delta Paks if setup. List <string> Paks = new List <string>(); ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LevelTransitions", out Paks); if (Paks != null) { foreach (var Pak in Paks) { var Matched = Regex.Matches(Pak, "\"[^\"]+\"", RegexOptions.IgnoreCase); string MapFrom = Path.GetFileNameWithoutExtension(Matched[0].ToString().Replace("\"", "")); string MapTo = Path.GetFileNameWithoutExtension(Matched[1].ToString().Replace("\"", "")); PakAutomation.CreateDeltaMapPaks(MapFrom, MapTo); } } } else { // we need to operate in the root string PythonPath = HTML5SDKInfo.Python(); string PackagerPath = HTML5SDKInfo.EmscriptenPackager(); using (new ScopedEnvVar("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN)) { using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5"))) { string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\" --no-heap-copy", PackagerPath, FinalDataLocation); RunAndLog(CmdEnv, PythonPath, CmdLine); } } } // copy the "Executable" to the package directory string ProjectGameExeFilename = Params.GetProjectExeForPlatform(UnrealTargetPlatform.HTML5).ToString(); string GameBasename = Path.GetFileNameWithoutExtension(ProjectGameExeFilename); if (Params.ClientConfigsToBuild[0].ToString() != "Development") { GameBasename += "-HTML5-" + Params.ClientConfigsToBuild[0].ToString(); } // no extension string GameBasepath = Path.GetDirectoryName(ProjectGameExeFilename); string FullGameBasePath = Path.Combine(GameBasepath, GameBasename); string FullPackageGameBasePath = Path.Combine(PackagePath, GameBasename); // with extension string GameExe = GameBasename + ".js"; string FullGameExePath = Path.Combine(GameBasepath, GameExe); string FullPackageGameExePath = Path.Combine(PackagePath, GameExe); // ensure the ue4game binary exists, if applicable if (!FileExists_NoExceptions(FullGameExePath)) { Log("Failed to find game application " + FullGameExePath); throw new AutomationException(ExitCode.Error_MissingExecutable, "Stage Failed. Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", FullGameExePath); } if (FullGameExePath != FullPackageGameExePath) // TODO: remove this check { File.Copy(FullGameExePath + ".symbols", FullPackageGameExePath + ".symbols", true); File.Copy(FullGameBasePath + ".wasm", FullPackageGameBasePath + ".wasm", true); File.Copy(FullGameExePath, FullPackageGameExePath, true); } File.SetAttributes(FullPackageGameExePath + ".symbols", FileAttributes.Normal); File.SetAttributes(FullPackageGameBasePath + ".wasm", FileAttributes.Normal); File.SetAttributes(FullPackageGameExePath, FileAttributes.Normal); // put the HTML file to the package directory string TemplateFile = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/GameX.html.template"); string OutputFile = Path.Combine(PackagePath, (Params.ClientConfigsToBuild[0].ToString() != "Development" ? (Params.ShortProjectName + "-HTML5-" + Params.ClientConfigsToBuild[0].ToString()) : Params.ShortProjectName)) + ".html"; GenerateFileFromTemplate(TemplateFile, OutputFile, Params.ShortProjectName, Params.ClientConfigsToBuild[0].ToString(), Params.StageCommandline, !Params.IsCodeBasedProject, HTML5SDKInfo.HeapSize(ConfigCache, Params.ClientConfigsToBuild[0].ToString())); string MacBashTemplateFile = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/RunMacHTML5LaunchHelper.command.template"); string MacBashOutputFile = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command"); string MonoPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/BatchFiles/Mac/SetupMono.sh"); GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath); string htaccessTemplate = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/htaccess.template"); string htaccesspath = Path.Combine(PackagePath, ".htaccess"); if (File.Exists(htaccesspath)) { FileAttributes attributes = File.GetAttributes(htaccesspath); if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { attributes &= ~FileAttributes.ReadOnly; File.SetAttributes(htaccesspath, attributes); } } File.Copy(htaccessTemplate, htaccesspath, true); string JSDir = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5"); string OutDir = PackagePath; // Gather utlity .js files and combine into one file string[] UtilityJavaScriptFiles = Directory.GetFiles(JSDir, "*.js"); string DestinationFile = OutDir + "/Utility.js"; File.Delete(DestinationFile); foreach (var UtilityFile in UtilityJavaScriptFiles) { string Data = File.ReadAllText(UtilityFile); File.AppendAllText(DestinationFile, Data); } if (Compressed) { Log("Build configuration is " + Params.ClientConfigsToBuild[0].ToString() + ", so (gzip) compressing files for web servers."); // Compress all files. These are independent tasks which can be threaded. List <Task> CompressionTasks = new List <Task>(); // data file CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FinalDataLocation, FinalDataLocation + "gz"))); // data file .js driver. CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FinalDataLocation + ".js", FinalDataLocation + ".jsgz"))); // main game code CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameBasePath + ".wasm", FullPackageGameBasePath + ".wasmgz"))); // main js. CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameExePath, FullPackageGameExePath + "gz"))); // symbols file. CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameExePath + ".symbols", FullPackageGameExePath + ".symbolsgz"))); // Utility CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(OutDir + "/Utility.js", OutDir + "/Utility.jsgz"))); Task.WaitAll(CompressionTasks.ToArray()); } else { Log("Build configuration is " + Params.ClientConfigsToBuild[0].ToString() + ", so not compressing. Build Shipping configuration to compress files to save space."); // nuke old compressed files to prevent using stale files File.Delete(FinalDataLocation + "gz"); File.Delete(FinalDataLocation + ".jsgz"); File.Delete(FullPackageGameExePath + "gz"); File.Delete(FullPackageGameBasePath + ".wasmgz"); File.Delete(FullPackageGameExePath + ".symbolsgz"); File.Delete(OutDir + "/Utility.jsgz"); } File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"), CombinePaths(OutDir, "HTML5LaunchHelper.exe"), true); // Task.WaitAll(CompressionTasks); PrintRunTime(); }
/// <summary> /// Runs a commandlet using Engine/Binaries/Win64/UE4Editor-Cmd.exe. /// </summary> /// <param name="ProjectFile">Project name.</param> /// <param name="UE4Exe">The name of the UE4 Editor executable to use.</param> /// <param name="Commandlet">Commandlet name.</param> /// <param name="Parameters">Command line parameters (without -run=)</param> /// <param name="DestLogFile">Log file after completion</param> public static void RunCommandlet(FileReference ProjectName, string UE4Exe, string Commandlet, string Parameters, out string DestLogFile) { LogInformation("Running UE4Editor {0} for project {1}", Commandlet, ProjectName); var CWD = Path.GetDirectoryName(UE4Exe); string EditorExe = UE4Exe; if (String.IsNullOrEmpty(CWD)) { EditorExe = HostPlatform.Current.GetUE4ExePath(UE4Exe); CWD = CombinePaths(CmdEnv.LocalRoot, HostPlatform.Current.RelativeBinariesFolder); } PushDir(CWD); DateTime StartTime = DateTime.UtcNow; string LocalLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.EngineSavedFolder, Commandlet)); LogInformation("Commandlet log file is {0}", LocalLogFile); string Args = String.Format( "{0} -run={1} {2} -abslog={3} -stdout -CrashForUAT -unattended -NoLogTimes {5}{4}", (ProjectName == null) ? "" : CommandUtils.MakePathSafeToUseWithCommandLine(ProjectName.FullName), Commandlet, String.IsNullOrEmpty(Parameters) ? "" : Parameters, CommandUtils.MakePathSafeToUseWithCommandLine(LocalLogFile), IsBuildMachine ? "-buildmachine" : "", (GlobalCommandLine.Verbose || GlobalCommandLine.AllowStdOutLogVerbosity) ? "-AllowStdOutLogVerbosity " : "" ); ERunOptions Opts = ERunOptions.Default; if (GlobalCommandLine.UTF8Output) { Args += " -UTF8Output"; Opts |= ERunOptions.UTF8Output; } IProcessResult RunResult = Run(EditorExe, Args, Options: Opts, Identifier: Commandlet); PopDir(); // If we're running on a Windows build machine, copy any crash dumps into the log folder if (HostPlatform.Current.HostEditorPlatform == UnrealTargetPlatform.Win64 && IsBuildMachine) { DirectoryInfo CrashesDir = new DirectoryInfo(DirectoryReference.Combine(DirectoryReference.FromFile(ProjectName) ?? CommandUtils.EngineDirectory, "Saved", "Crashes").FullName); if (CrashesDir.Exists) { foreach (DirectoryInfo CrashDir in CrashesDir.EnumerateDirectories()) { if (CrashDir.LastWriteTimeUtc > StartTime) { DirectoryInfo OutputCrashesDir = new DirectoryInfo(Path.Combine(CmdEnv.LogFolder, "Crashes", CrashDir.Name)); try { CommandUtils.LogInformation("Copying crash data to {0}...", OutputCrashesDir.FullName); OutputCrashesDir.Create(); foreach (FileInfo CrashFile in CrashDir.EnumerateFiles()) { CrashFile.CopyTo(Path.Combine(OutputCrashesDir.FullName, CrashFile.Name)); } } catch (Exception Ex) { CommandUtils.LogWarning("Unable to copy crash data; skipping. See log for exception details."); CommandUtils.LogVerbose(Tools.DotNETCommon.ExceptionUtils.FormatExceptionDetails(Ex)); } } } } } // If we're running on a Mac, dump all the *.crash files that were generated while the editor was running. if (HostPlatform.Current.HostEditorPlatform == UnrealTargetPlatform.Mac) { // If the exit code indicates the main process crashed, introduce a small delay because the crash report is written asynchronously. // If we exited normally, still check without waiting in case SCW or some other child process crashed. if (RunResult.ExitCode > 128) { CommandUtils.LogInformation("Pausing before checking for crash logs..."); Thread.Sleep(10 * 1000); } // Create a list of directories containing crash logs, and add the system log folder List <string> CrashDirs = new List <string>(); CrashDirs.Add("/Library/Logs/DiagnosticReports"); // Add the user's log directory too string HomeDir = Environment.GetEnvironmentVariable("HOME"); if (!String.IsNullOrEmpty(HomeDir)) { CrashDirs.Add(Path.Combine(HomeDir, "Library/Logs/DiagnosticReports")); } // Check each directory for crash logs List <FileInfo> CrashFileInfos = new List <FileInfo>(); foreach (string CrashDir in CrashDirs) { try { DirectoryInfo CrashDirInfo = new DirectoryInfo(CrashDir); if (CrashDirInfo.Exists) { CrashFileInfos.AddRange(CrashDirInfo.EnumerateFiles("*.crash", SearchOption.TopDirectoryOnly).Where(x => x.LastWriteTimeUtc >= StartTime)); } } catch (UnauthorizedAccessException) { // Not all account types can access /Library/Logs/DiagnosticReports } } // Dump them all to the log foreach (FileInfo CrashFileInfo in CrashFileInfos) { // snmpd seems to often crash (suspect due to it being starved of CPU cycles during cooks) // also ignore spotlight crash with the excel plugin if (!CrashFileInfo.Name.StartsWith("snmpd_") && !CrashFileInfo.Name.StartsWith("mdworker32_") && !CrashFileInfo.Name.StartsWith("Dock_")) { CommandUtils.LogInformation("Found crash log - {0}", CrashFileInfo.FullName); try { string[] Lines = File.ReadAllLines(CrashFileInfo.FullName); foreach (string Line in Lines) { CommandUtils.LogInformation("Crash: {0}", Line); } } catch (Exception Ex) { CommandUtils.LogWarning("Failed to read file ({0})", Ex.Message); } } } } // Copy the local commandlet log to the destination folder. DestLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.LogFolder, Commandlet)); if (!CommandUtils.CopyFile_NoExceptions(LocalLogFile, DestLogFile)) { CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, LocalLogFile, DestLogFile); } string ProjectStatsDirectory = CombinePaths((ProjectName == null)? CombinePaths(CmdEnv.LocalRoot, "Engine") : Path.GetDirectoryName(ProjectName.FullName), "Saved", "Stats"); if (Directory.Exists(ProjectStatsDirectory)) { string DestCookerStats = CmdEnv.LogFolder; foreach (var StatsFile in Directory.EnumerateFiles(ProjectStatsDirectory, "*.csv")) { if (!CommandUtils.CopyFile_NoExceptions(StatsFile, CombinePaths(DestCookerStats, Path.GetFileName(StatsFile)))) { CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, StatsFile, CombinePaths(DestCookerStats, Path.GetFileName(StatsFile))); } } } // else // { // CommandUtils.LogWarning("Failed to find directory {0} will not save stats", ProjectStatsDirectory); // } // Whether it was copied correctly or not, delete the local log as it was only a temporary file. CommandUtils.DeleteFile_NoExceptions(LocalLogFile); // Throw an exception if the execution failed. Draw attention to signal exit codes on Posix systems, rather than just printing the exit code if (RunResult.ExitCode != 0) { string ExitCodeDesc = ""; if (RunResult.ExitCode > 128 && RunResult.ExitCode < 128 + 32) { if (RunResult.ExitCode == 139) { ExitCodeDesc = " (segmentation fault)"; } else { ExitCodeDesc = String.Format(" (signal {0})", RunResult.ExitCode - 128); } } throw new CommandletException(DestLogFile, RunResult.ExitCode, "Editor terminated with exit code {0}{1} while running {2}{3}; see log {4}", RunResult.ExitCode, ExitCodeDesc, Commandlet, (ProjectName == null)? "" : String.Format(" for {0}", ProjectName), DestLogFile) { OutputFormat = AutomationExceptionOutputFormat.Minimal }; } }
public static void CopySharedCookedBuildForTarget(string ProjectFullPath, UnrealTargetPlatform TargetPlatform, string CookPlatform, bool bOnlyCopyAssetRegistry = false) { var LocalPath = CommandUtils.CombinePaths(Path.GetDirectoryName(ProjectFullPath), "Saved", "SharedIterativeBuild", CookPlatform); FileReference ProjectFileRef = new FileReference(ProjectFullPath); // get network location ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFileRef), TargetPlatform); List <string> CookedBuildPaths; if (Hierarchy.GetArray("SharedCookedBuildSettings", "SharedCookedBuildPath", out CookedBuildPaths) == false) { CommandUtils.Log("Unable to copy shared cooked build: SharedCookedBuildPath not set in Engine.ini SharedCookedBuildSettings"); return; } foreach (var CookedBuildPath in CookedBuildPaths) { if (CopySharedCookedBuildForTargetInternal(CookedBuildPath, CookPlatform, LocalPath, bOnlyCopyAssetRegistry) == true) { return; } } return; }
public Noesis(ReadOnlyTargetRules Target) : base(Target) { Type = ModuleType.External; string NoesisBasePath = ModuleDirectory + "/NoesisSDK/"; string NoesisIncludePath = NoesisBasePath + "Include/"; PublicIncludePaths.Add(ModuleDirectory); PublicIncludePaths.Add(NoesisIncludePath); // Let's try to make sure the right version of the SDK is in the right place. const string RequiredRevision = "(r6972)"; const string RequiredVersionName = "2.1.0f1"; if (!Directory.Exists(NoesisBasePath)) { throw new BuildException("Could not find NoesisGUI SDK in " + NoesisBasePath + ". Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Bin")) { throw new BuildException("Could not find NoesisGUI SDK Bin directory in " + NoesisBasePath + "Bin. Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Include")) { throw new BuildException("Could not find NoesisGUI SDK Include directory in " + NoesisBasePath + "Include. Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Lib")) { throw new BuildException("Could not find NoesisGUI SDK Lib directory in " + NoesisBasePath + "Lib. Minimum required version is " + RequiredVersionName); } string NoesisSdkVersionInfo; try { NoesisSdkVersionInfo = File.ReadAllText(NoesisBasePath + "version.txt"); } catch (Exception) { throw new BuildException("Could not find NoesisGUI SDK version.txt in " + NoesisBasePath + "version.txt. Minimum required version is " + RequiredVersionName); } string[] SplitVersion = NoesisSdkVersionInfo.Split(' '); if (String.Compare(SplitVersion[SplitVersion.Length - 1], RequiredRevision) < 0) { throw new BuildException("Wrong version of the NoesisGUI SDK installed in " + NoesisBasePath + ". Minimum required version is " + RequiredVersionName); } PublicSystemIncludePaths.Add(NoesisIncludePath); if (Target.Platform == UnrealTargetPlatform.Win64) { string NoesisLibPath = NoesisBasePath + "Lib/windows_x86_64/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); string BaseTargetPath = ""; if (Target.LinkType == TargetLinkType.Monolithic) { if (Target.ProjectFile != null) { BaseTargetPath = DirectoryReference.FromFile(Target.ProjectFile).ToString(); } } else { BaseTargetPath = Target.RelativeEnginePath; } string NoesisDllPath = "/NoesisSDK/Bin/windows_x86_64/Noesis.dll"; string NoesisDllTargetPath = "/Binaries/Win64/Noesis.dll"; if (Target.LinkType == TargetLinkType.Monolithic) { RuntimeDependencies.Add("$(ProjectDir)" + NoesisDllTargetPath); } else { RuntimeDependencies.Add("$(EngineDir)" + NoesisDllTargetPath); } if (BaseTargetPath != "") { try { if (!System.IO.Directory.Exists(BaseTargetPath + "/Binaries/Win64")) { System.IO.Directory.CreateDirectory(BaseTargetPath + "/Binaries/Win64"); } System.IO.File.Copy(ModuleDirectory + NoesisDllPath, BaseTargetPath + NoesisDllTargetPath, true); } catch (IOException Exception) { if (Exception.HResult != -2147024864) // 0x80070020: The process cannot access the file ... because it is being used by another process. { throw; } } } } else if (Target.Platform == UnrealTargetPlatform.Mac) { string NoesisLibPath = NoesisBasePath + "Bin/osx/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.dylib"); string NoesisDylibPath = "/NoesisSDK/Bin/osx/Noesis.dylib"; RuntimeDependencies.Add(ModuleDirectory + NoesisDylibPath); } else if (Target.Platform == UnrealTargetPlatform.IOS) { string NoesisLibPath = NoesisBasePath + "Lib/ios/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis"); PublicAdditionalShadowFiles.Add(Path.Combine(NoesisLibPath, "libNoesis.a")); } else if (Target.Platform == UnrealTargetPlatform.Android) { string NoesisLibPath = NoesisBasePath + "Bin/android_arm/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis"); string NoesisAplPath = "/Noesis_APL.xml"; AdditionalPropertiesForReceipt.Add("AndroidPlugin", ModuleDirectory + NoesisAplPath); } else if (Target.Platform == UnrealTargetPlatform.PS4) { string NoesisLibPath = NoesisBasePath + "Lib/ps4/"; PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.a"); } else if (Target.Platform == UnrealTargetPlatform.XboxOne) { string NoesisLibPath = NoesisBasePath + "Bin/xbox_one/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); } }
static void CopySharedCookedBuildForTarget(ProjectParams Params, TargetPlatformDescriptor TargetPlatform, string CookPlatform) { string ProjectPath = Params.RawProjectPath.FullName; var LocalPath = CombinePaths(GetDirectoryName(ProjectPath), "Saved", "SharedIterativeBuild", CookPlatform); // get network location ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), TargetPlatform.Type); string CookedBuildPath; if (Hierarchy.GetString("SharedCookedBuildSettings", "SharedCookedBuildPath", out CookedBuildPath) == false) { Log("Unable to copy shared cooked build: SharedCookedBuildPath not set in Engine.ini SharedCookedBuildSettings"); return; } string BuildRoot = P4Enabled ? P4Env.BuildRootP4.Replace("/", "+") : ""; int RecentCL = P4Enabled ? P4Env.Changelist : 0; BuildVersion Version; if (BuildVersion.TryRead(out Version)) { RecentCL = Version.Changelist; BuildRoot = Version.BranchName; } // check to see if we have already synced this build ;) var SyncedBuildFile = CombinePaths(LocalPath, "SyncedBuild.txt"); string BuildCL = "Invalid"; if (File.Exists(SyncedBuildFile)) { BuildCL = File.ReadAllText(SyncedBuildFile); } if (RecentCL == 0 && CookedBuildPath.Contains("[CL]")) { Log("Unable to copy shared cooked build: Unable to determine CL number from P4 or UGS, and is required by SharedCookedBuildPath"); return; } if (RecentCL == 0 && CookedBuildPath.Contains("[BRANCHNAME]")) { Log("Unable to copy shared cooked build: Unable to determine BRANCHNAME number from P4 or UGS, and is required by SharedCookedBuildPath"); return; } CookedBuildPath = CookedBuildPath.Replace("[CL]", RecentCL.ToString()); CookedBuildPath = CookedBuildPath.Replace("[BRANCHNAME]", BuildRoot); CookedBuildPath = CookedBuildPath.Replace("[PLATFORM]", CookPlatform); if (Directory.Exists(CookedBuildPath) == false) { Log("Unable to copy shared cooked build: Unable to find shared build at location {0} check SharedCookedBuildPath in Engine.ini SharedCookedBuildSettings is correct", CookedBuildPath); return; } Log("Attempting download of latest shared build CL {0} from location {1}", RecentCL, CookedBuildPath); if (BuildCL == RecentCL.ToString()) { Log("Already downloaded latest shared build at CL {0}", RecentCL); return; } // delete all the stuff Log("Deleting previous shared build because it was out of date"); CommandUtils.DeleteDirectory(LocalPath); Directory.CreateDirectory(LocalPath); // find all the files in the staged directory string CookedBuildStagedDirectory = Path.GetFullPath(Path.Combine(CookedBuildPath, "Staged")); string LocalBuildStagedDirectory = Path.GetFullPath(Path.Combine(LocalPath, "Staged")); if (Directory.Exists(CookedBuildStagedDirectory)) { foreach (string FileName in Directory.EnumerateFiles(CookedBuildStagedDirectory, "*.*", SearchOption.AllDirectories)) { string SourceFileName = Path.GetFullPath(FileName); string DestFileName = SourceFileName.Replace(CookedBuildStagedDirectory, LocalBuildStagedDirectory); Directory.CreateDirectory(Path.GetDirectoryName(DestFileName)); File.Copy(SourceFileName, DestFileName); } } string CookedBuildCookedDirectory = Path.Combine(CookedBuildPath, "Cooked"); CookedBuildCookedDirectory = Path.GetFullPath(CookedBuildCookedDirectory); string LocalBuildCookedDirectory = Path.Combine(LocalPath, "Cooked"); LocalBuildCookedDirectory = Path.GetFullPath(LocalBuildCookedDirectory); if (Directory.Exists(CookedBuildCookedDirectory)) { foreach (string FileName in Directory.EnumerateFiles(CookedBuildCookedDirectory, "*.*", SearchOption.AllDirectories)) { string SourceFileName = Path.GetFullPath(FileName); string DestFileName = SourceFileName.Replace(CookedBuildCookedDirectory, LocalBuildCookedDirectory); Directory.CreateDirectory(Path.GetDirectoryName(DestFileName)); File.Copy(SourceFileName, DestFileName); } } File.WriteAllText(SyncedBuildFile, RecentCL.ToString()); return; }
public PrFirebase(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; ConfigHierarchy EngineConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Target.ProjectFile), Target.Platform); bool bFirebaseLoggingInShipping = false; EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseLoggingInShipping", out bFirebaseLoggingInShipping); bool bFirebaseEnable = false; bool bFirebaseCrashlyticsEnable = false; bool bFirebaseRemoteConfigEnable = false; bool bFirebaseAuthEnable = false; bool bFirebasePerformanceEnable = false; EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseEnable", out bFirebaseEnable); EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseCrashlyticsEnable", out bFirebaseCrashlyticsEnable); EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseRemoteConfigEnable", out bFirebaseRemoteConfigEnable); EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseAuthEnable", out bFirebaseAuthEnable); EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebasePerformanceEnable", out bFirebasePerformanceEnable); PrivateIncludePaths.AddRange( new string[] { "PrFirebase/Private" }); PublicDependencyModuleNames.AddRange( new string[] { "Core", "CoreUObject", "Engine" }); PrivateIncludePathModuleNames.AddRange( new string[] { "Settings", } ); bool bSymbolsWarning = false; if (bFirebaseEnable) { if (Target.Platform == UnrealTargetPlatform.IOS) { bool bGeneratedSYMBundle = false; bool bGeneratedSYMFile = false; EngineConfig.TryGetValue("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGeneratedSYMBundle", out bGeneratedSYMBundle); EngineConfig.TryGetValue("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGeneratedSYMFile", out bGeneratedSYMFile); if ((!bGeneratedSYMBundle || !bGeneratedSYMFile) && bFirebaseCrashlyticsEnable) { bSymbolsWarning = true; } /* Firebase / Firebase Analytics */ PublicAdditionalFrameworks.Add( new Framework( "FIRAnalyticsConnector", "../../ThirdParty/iOS/FIRAnalyticsConnector.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "FirebaseAnalytics", "../../ThirdParty/iOS/FirebaseAnalytics.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "FirebaseCore", "../../ThirdParty/iOS/FirebaseCore.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "FirebaseCoreDiagnostics", "../../ThirdParty/iOS/FirebaseCoreDiagnostics.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "FirebaseInstallations", "../../ThirdParty/iOS/FirebaseInstallations.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "GoogleAppMeasurement", "../../ThirdParty/iOS/GoogleAppMeasurement.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "GoogleDataTransport", "../../ThirdParty/iOS/GoogleDataTransport.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "GoogleUtilities", "../../ThirdParty/iOS/GoogleUtilities.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "nanopb", "../../ThirdParty/iOS/nanopb.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "PromisesObjC", "../../ThirdParty/iOS/PromisesObjC.embeddedframework.zip" ) ); /* Crashlytics */ if (bFirebaseCrashlyticsEnable) { PublicAdditionalFrameworks.Add( new Framework( "FirebaseCrashlytics", "../../ThirdParty/iOS/FirebaseCrashlytics.embeddedframework.zip" ) ); } /* Remote Config */ if (bFirebaseRemoteConfigEnable) { PublicAdditionalFrameworks.Add( new Framework( "FirebaseABTesting", "../../ThirdParty/iOS/FirebaseABTesting.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "FirebaseRemoteConfig", "../../ThirdParty/iOS/FirebaseRemoteConfig.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "Protobuf", "../../ThirdParty/iOS/Protobuf.embeddedframework.zip" ) ); } /* Performance */ if (bFirebasePerformanceEnable) { PublicAdditionalFrameworks.Add( new Framework( "FirebaseABTesting", "../../ThirdParty/iOS/FirebaseABTesting.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "FirebasePerformance", "../../ThirdParty/iOS/FirebasePerformance.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "FirebaseRemoteConfig", "../../ThirdParty/iOS/FirebaseRemoteConfig.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "GoogleToolboxForMac", "../../ThirdParty/iOS/GoogleToolboxForMac.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "GTMSessionFetcher", "../../ThirdParty/iOS/GTMSessionFetcher.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "Protobuf", "../../ThirdParty/iOS/Protobuf.embeddedframework.zip" ) ); } /* Auth */ if (bFirebaseAuthEnable) { PublicAdditionalFrameworks.Add( new Framework( "FirebaseAuth", "../../ThirdParty/iOS/FirebaseAuth.embeddedframework.zip" ) ); PublicAdditionalFrameworks.Add( new Framework( "GTMSessionFetcher", "../../ThirdParty/iOS/GTMSessionFetcher.embeddedframework.zip" ) ); } PublicSystemLibraries.Add("sqlite3"); PrivateIncludePaths.Add("PrFirebase/External/iOS"); string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath); AdditionalPropertiesForReceipt.Add("IOSPlugin", Path.Combine(PluginPath, "PrFirebase_UPL_IOS.xml")); } else if (Target.Platform == UnrealTargetPlatform.Android) { PublicDependencyModuleNames.AddRange( new string[] { "Launch" }); string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath); AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(PluginPath, "PrFirebase_UPL_Android.xml")); } else { bFirebaseEnable = false; } } PublicDefinitions.Add("WITH_FIREBASE=" + (bFirebaseEnable ? "1" : "0")); PublicDefinitions.Add("WITH_FIREBASE_CRASHLYTICS=" + (bFirebaseEnable && bFirebaseCrashlyticsEnable ? "1" : "0")); PublicDefinitions.Add("WITH_FIREBASE_REMOTECONFIG=" + (bFirebaseEnable && bFirebaseRemoteConfigEnable ? "1" : "0")); PublicDefinitions.Add("WITH_FIREBASE_AUTH=" + (bFirebaseEnable && bFirebaseAuthEnable ? "1" : "0")); PublicDefinitions.Add("WITH_FIREBASE_PERFORMANCE=" + (bFirebaseEnable && bFirebasePerformanceEnable ? "1" : "0")); PublicDefinitions.Add("WITH_FIREBASE_SYMBOLS_WARNING=" + (bFirebaseEnable && bSymbolsWarning ? "1" : "0")); PublicDefinitions.Add("FIREBASE_LOGGING=" + (bFirebaseLoggingInShipping ? "1" : "0")); }
private static bool FindBestSharedCookedBuild(ref string FinalCookedBuildPath, string ProjectFullPath, UnrealTargetPlatform TargetPlatform, string CookPlatform, string SharedCookedBuildCL) { string BuildRoot = CommandUtils.P4Enabled ? CommandUtils.P4Env.Branch.Replace("/", "+") : ""; int CurrentCLInt = CommandUtils.P4Enabled ? CommandUtils.P4Env.Changelist : 0; BuildVersion Version; if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version)) { CurrentCLInt = Version.Changelist; BuildRoot = Version.BranchName; } System.GC.Collect(); string CurrentCL = CurrentCLInt.ToString(); FileReference ProjectFileRef = new FileReference(ProjectFullPath); // get network location ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFileRef), TargetPlatform); List <string> CookedBuildPaths; if (Hierarchy.GetArray("SharedCookedBuildSettings", "SharedCookedBuildPath", out CookedBuildPaths) == false) { CommandUtils.LogInformation("Unable to copy shared cooked build: SharedCookedBuildPath not set in Engine.ini SharedCookedBuildSettings"); return(false); } const string MetaDataFilename = "\\Metadata\\DevelopmentAssetRegistry.bin"; if (SharedCookedBuildCL == "usesyncedbuild") { foreach (string CookedBuildPath in CookedBuildPaths) { if (CurrentCL == "" && FinalCookedBuildPath.Contains("[CL]")) { CommandUtils.LogInformation("Unable to copy shared cooked build: Unable to determine CL number from P4 or UGS, and is required by SharedCookedBuildPath"); return(false); } if (CurrentCL == "" && FinalCookedBuildPath.Contains("[BRANCHNAME]")) { CommandUtils.LogInformation("Unable to copy shared cooked build: Unable to determine BRANCHNAME number from P4 or UGS, and is required by SharedCookedBuildPath"); return(false); } FinalCookedBuildPath = FinalCookedBuildPath.Replace("[CL]", CurrentCL.ToString()); FinalCookedBuildPath = FinalCookedBuildPath.Replace("[BRANCHNAME]", BuildRoot); FinalCookedBuildPath = FinalCookedBuildPath.Replace("[PLATFORM]", CookPlatform); // make sure that the directory and metadata file exist. otherwise this build might not be finished yet and we should skip it if (Directory.Exists(FinalCookedBuildPath)) { if (File.Exists(FinalCookedBuildPath + MetaDataFilename)) { return(true); } } } } else if (SharedCookedBuildCL == "userecentbuild") { // build our CookedBUildPath into a regex which we can execute on the directories and extract info from string BestBuild = null; int BestCLNumber = 0; // find all the recent builds which are valid foreach (string CookedBuildPath in CookedBuildPaths) { int IndexOfFirstParam = CookedBuildPath.IndexOf("["); int CustomFolderStart = CookedBuildPath.LastIndexOf("\\", IndexOfFirstParam); string CookedBuildDirectory = CookedBuildPath.Substring(0, CustomFolderStart); string BuildNameWildcard = CookedBuildPath.Substring(CustomFolderStart); BuildNameWildcard += MetaDataFilename; FileFilter BuildSearch = new FileFilter(); // we know the platform and the branch name; string BuildRule = BuildNameWildcard; BuildRule = BuildRule.Replace("[BRANCHNAME]", BuildRoot); BuildRule = BuildRule.Replace("[PLATFORM]", CookPlatform); string IncludeRule = BuildRule.Replace("[CL]", "*"); string ForgetRule = BuildRule.Replace("[CL]", "*-PF-*"); // get rid of any preflights from the list... they don't count because who knows what they did... BuildSearch.AddRule(IncludeRule); BuildSearch.AddRule(ForgetRule, FileFilterType.Exclude); List <FileReference> ValidBuilds = BuildSearch.ApplyToDirectory(new DirectoryReference(CookedBuildDirectory), false); // figure out what the CL is string BuildNameRegex = String.Format(".*{0}", CookedBuildPath.Substring(CustomFolderStart)); BuildNameRegex = BuildNameRegex.Replace("\\", "\\\\"); BuildNameRegex = BuildNameRegex.Replace("[BRANCHNAME]", BuildRoot); BuildNameRegex = BuildNameRegex.Replace("+", "\\+"); BuildNameRegex = BuildNameRegex.Replace("[PLATFORM]", CookPlatform); BuildNameRegex = BuildNameRegex.Replace("[CL]", "(?<CL>.*)"); Regex ExtractCL = new Regex(BuildNameRegex); foreach (FileReference ValidBuild in ValidBuilds) { string BuildPath = ValidBuild.FullName.Replace(MetaDataFilename, ""); Match CLMatch = ExtractCL.Match(BuildPath); if (CLMatch != null) { string CLNumber = CLMatch.Result("${CL}"); int CLNumberInt = int.Parse(CLNumber); if (CLNumberInt <= CurrentCLInt) { if (CLNumberInt > BestCLNumber) { BestCLNumber = CLNumberInt; BestBuild = BuildPath; } } } } } if (string.IsNullOrEmpty(BestBuild)) { return(false); } FinalCookedBuildPath = BestBuild; return(true); } return(false); }
public Noesis(ReadOnlyTargetRules Target) : base(Target) { Type = ModuleType.External; string NoesisBasePath = ModuleDirectory + "/NoesisSDK/"; string NoesisIncludePath = NoesisBasePath + "Include/"; string NoesisInteractivityIncludePath = NoesisBasePath + "Src/Packages/App/Interactivity/Include/"; PublicIncludePaths.Add(ModuleDirectory); PublicIncludePaths.Add(NoesisIncludePath); PublicIncludePaths.Add(NoesisInteractivityIncludePath); if (!Directory.Exists(NoesisBasePath)) { throw new BuildException("Could not find NoesisGUI SDK in " + NoesisBasePath + "."); } if (!Directory.Exists(NoesisBasePath + "Include")) { throw new BuildException("Could not find NoesisGUI SDK Include directory in " + NoesisBasePath + "Include."); } PublicSystemIncludePaths.Add(NoesisIncludePath); UnrealTargetPlatform Platform; if (Target.Platform == UnrealTargetPlatform.Win64) { PublicAdditionalLibraries.Add(NoesisBasePath + "Lib/windows_x86_64/Noesis.lib"); string NoesisDllPath = "/NoesisSDK/Bin/windows_x86_64/Noesis.dll"; string NoesisDllTargetPath = "/Binaries/Win64/Noesis.dll"; if (Target.ProjectFile != null) { System.Console.WriteLine("Copying Noesis.dll to {0}", DirectoryReference.FromFile(Target.ProjectFile).ToString() + NoesisDllTargetPath); CopyNoesisDll(ModuleDirectory + NoesisDllPath, DirectoryReference.FromFile(Target.ProjectFile).ToString() + NoesisDllTargetPath); } System.Console.WriteLine("Copying Noesis.dll to {0}", System.IO.Path.GetFullPath(ModuleDirectory + "/../.." + NoesisDllTargetPath)); CopyNoesisDll(ModuleDirectory + NoesisDllPath, ModuleDirectory + "/../.." + NoesisDllTargetPath); if (System.IO.File.Exists(Target.RelativeEnginePath + NoesisDllTargetPath)) { System.IO.File.Delete(Target.RelativeEnginePath + NoesisDllTargetPath); } if (Target.LinkType == TargetLinkType.Monolithic) { RuntimeDependencies.Add("$(ProjectDir)" + NoesisDllTargetPath); } else { RuntimeDependencies.Add("$(EngineDir)" + NoesisDllTargetPath); } } else if (Target.Platform == UnrealTargetPlatform.Linux) { PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/linunx_x86_64/libNoesis.so"); } else if (Target.Platform == UnrealTargetPlatform.Mac) { PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/macos/Noesis.dylib"); string NoesisDylibPath = "/NoesisSDK/Bin/macos/Noesis.dylib"; RuntimeDependencies.Add(ModuleDirectory + NoesisDylibPath); } else if (Target.Platform == UnrealTargetPlatform.IOS) { PublicDefinitions.Add("NS_STATIC_LIBRARY"); PublicAdditionalLibraries.Add(NoesisBasePath + "Lib/ios/libNoesis.a"); PublicFrameworks.Add("CoreText"); } else if (Target.Platform == UnrealTargetPlatform.Android) { PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/android_arm/libNoesis.so"); PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/android_arm64/libNoesis.so"); PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/android_x86/libNoesis.so"); PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/android_x86_64/libNoesis.so"); string NoesisAplPath = "/Noesis_APL.xml"; AdditionalPropertiesForReceipt.Add("AndroidPlugin", ModuleDirectory + NoesisAplPath); } else if (Target.Platform == UnrealTargetPlatform.PS4) { PublicDefinitions.Add("NS_STATIC_LIBRARY"); PublicAdditionalLibraries.Add(NoesisBasePath + "Lib/ps4/Noesis.a"); } else if (Target.Platform == UnrealTargetPlatform.XboxOne) { PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/xbox_one/Noesis.lib"); } else if (UnrealTargetPlatform.TryParse("HTML5", out Platform) && Target.Platform == Platform) { PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/wasm/Noesis.bc"); } }
public override IProcessResult RunClient(ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params) { // look for browser string BrowserPath = Params.Devices[0].Replace("HTML5@", ""); // open the webpage Int32 ServerPort = 8000; // HTML5LaunchHelper default var ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5); ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "DeployServerPort", out ServerPort); // LaunchOn via Editor or FrontEnd string WorkingDirectory = Path.GetDirectoryName(ClientApp); string url = Path.GetFileName(ClientApp) + ".html"; // WARNING: splitting the following situation // if cookonthefly is used: tell the browser to use the PROXY at DEFAULT_HTTP_FILE_SERVING_PORT // leave the normal HTML5LaunchHelper port (ServerPort) alone -- otherwise it will collide with the PROXY port if (ClientCmdLine.Contains("filehostip")) { url += "?cookonthefly=true"; Int32 ProxyPort = 41898; // DEFAULT_HTTP_FILE_SERVING_PORT url = String.Format("http://localhost:{0}/{1}", ProxyPort, url); } else { url = String.Format("http://localhost:{0}/{1}", ServerPort, url); } // Check HTML5LaunchHelper source for command line args var LowerBrowserPath = BrowserPath.ToLower(); var ProfileDirectory = Path.Combine(Utils.GetUserSettingDirectory().FullName, "UE4_HTML5", "user"); string BrowserCommandline = url; if (LowerBrowserPath.Contains("chrome")) { ProfileDirectory = Path.Combine(ProfileDirectory, "chrome"); // removing [--enable-logging] otherwise, chrome breaks with a bunch of the following errors: // > ERROR:process_info.cc(631)] range at 0x7848406c00000000, size 0x1a4 fully unreadable // leaving this note here for future reference: UE-45078 BrowserCommandline += " " + String.Format("--user-data-dir=\\\"{0}\\\" --no-first-run", ProfileDirectory); } else if (LowerBrowserPath.Contains("firefox")) { ProfileDirectory = Path.Combine(ProfileDirectory, "firefox"); BrowserCommandline += " " + String.Format("-no-remote -profile \\\"{0}\\\"", ProfileDirectory); } if (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Linux) { // TODO: test on other platforms to remove this if() check if (!Directory.Exists(ProfileDirectory)) { Directory.CreateDirectory(ProfileDirectory); } } string LauncherArguments = string.Format(" -Browser=\"{0}\" + -BrowserCommandLine=\"{1}\" -ServerPort=\"{2}\" -ServerRoot=\"{3}\" ", new object[] { BrowserPath, BrowserCommandline, ServerPort, WorkingDirectory }); var LaunchHelperPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"); IProcessResult BrowserProcess = Run(LaunchHelperPath, LauncherArguments, null, ClientRunFlags | ERunOptions.NoWaitForExit); return(BrowserProcess); }
public static bool CanCreateMapPaks(ProjectParams Param) { bool UseAsyncLevelLoading = false; var ConfigCache = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", DirectoryReference.FromFile(Param.RawProjectPath), new DirectoryReference(CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine"))); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UseAsyncLevelLoading", out UseAsyncLevelLoading); if (Param.Run) { return(false); } return(UseAsyncLevelLoading); }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { LogInformation("Package {0}", Params.RawProjectPath); LogInformation("Setting Emscripten SDK for packaging.."); HTML5SDKInfo.SetupEmscriptenTemp(); HTML5SDKInfo.SetUpEmscriptenConfigFile(); // ---------------------------------------- // ini configurations ConfigHierarchy ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableMultithreading", out enableMultithreading); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "OffscreenCanvas", out bMultithreading_UseOffscreenCanvas); // Debug and Development builds are not compressed to: // - speed up iteration times // - ensure (IndexedDB) data are not cached/used // Shipping builds "can be": // - compressed // - (IndexedDB) cached string ProjectConfiguration = Params.ClientConfigsToBuild[0].ToString(); if (ProjectConfiguration == "Shipping") { ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "Compressed", out Compressed); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableIndexedDB", out enableIndexedDB); } LogInformation("HTML5Platform.Automation: Compressed = " + Compressed); LogInformation("HTML5Platform.Automation: EnableIndexedDB = " + enableIndexedDB); LogInformation("HTML5Platform.Automation: Multithreading = " + enableMultithreading); LogInformation("HTML5Platform.Automation: OffscreenCanvas = " + bMultithreading_UseOffscreenCanvas); // ---------------------------------------- // package directory string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Binaries", "HTML5"); if (!Directory.Exists(PackagePath)) { Directory.CreateDirectory(PackagePath); } string _ProjectNameExtra = ProjectConfiguration != "Development" ? "-HTML5-" + ProjectConfiguration : ""; string _ProjectFullpath = Params.GetProjectExeForPlatform(UnrealTargetPlatform.HTML5).ToString(); string _ProjectFilename = Path.GetFileNameWithoutExtension(_ProjectFullpath) + _ProjectNameExtra; string SrcUE4GameBasename = Path.Combine(Path.GetDirectoryName(_ProjectFullpath), _ProjectFilename); string UE4GameBasename = Path.Combine(PackagePath, _ProjectFilename); string ProjectBasename = Path.Combine(PackagePath, Params.ShortProjectName + _ProjectNameExtra); if (Params.IsCodeBasedProject && Params.HasClientCookedTargets) { UE4GameBasename = Params.ClientCookedTargets[0]; } // ---------------------------------------- // packaging if (HTMLPakAutomation.CanCreateMapPaks(Params)) { HTMLPakAutomation PakAutomation = new HTMLPakAutomation(Params, SC); // Create Necessary Paks. PakAutomation.CreateEnginePak(); PakAutomation.CreateGamePak(); PakAutomation.CreateContentDirectoryPak(); // Create Emscripten Package from Necessary Paks. - This will be the VFS. PakAutomation.CreateEmscriptenDataPackage(PackagePath, ProjectBasename + ".data"); // Create All Map Paks which will be downloaded on the fly. PakAutomation.CreateMapPak(); // Create Delta Paks if setup. List <string> Paks = new List <string>(); ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LevelTransitions", out Paks); if (Paks != null) { foreach (var Pak in Paks) { var Matched = Regex.Matches(Pak, "\"[^\"]+\"", RegexOptions.IgnoreCase); string MapFrom = Path.GetFileNameWithoutExtension(Matched[0].ToString().Replace("\"", "")); string MapTo = Path.GetFileNameWithoutExtension(Matched[1].ToString().Replace("\"", "")); PakAutomation.CreateDeltaMapPaks(MapFrom, MapTo); } } } else { // we need to operate in the root string PythonPath = HTML5SDKInfo.Python().FullName; string EmPackagerPath = HTML5SDKInfo.EmscriptenPackager(); using (new ScopedEnvVar("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN)) { using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5"))) { string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\" --no-heap-copy", EmPackagerPath, ProjectBasename + ".data"); RunAndLog(CmdEnv, PythonPath, CmdLine); } } } // ---------------------------------------- // copy to package directory // ensure the ue4game binary exists, if applicable if (!FileExists_NoExceptions(SrcUE4GameBasename + ".js")) { LogInformation("Failed to find game application " + SrcUE4GameBasename + ".js"); throw new AutomationException(ExitCode.Error_MissingExecutable, "Stage Failed. Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", SrcUE4GameBasename + ".js"); } if (!Params.IsCodeBasedProject) { // template project - need to copy over UE4Game.* File.Copy(SrcUE4GameBasename + ".wasm", UE4GameBasename + ".wasm", true); File.Copy(SrcUE4GameBasename + ".js", UE4GameBasename + ".js", true); File.SetAttributes(UE4GameBasename + ".wasm", FileAttributes.Normal); File.SetAttributes(UE4GameBasename + ".js", FileAttributes.Normal); if (File.Exists(SrcUE4GameBasename + ".js.symbols")) { File.Copy(SrcUE4GameBasename + ".js.symbols", UE4GameBasename + ".js.symbols", true); File.SetAttributes(UE4GameBasename + ".js.symbols", FileAttributes.Normal); } if (enableMultithreading) { File.Copy(SrcUE4GameBasename + ".js.mem", UE4GameBasename + ".js.mem", true); File.SetAttributes(UE4GameBasename + ".js.mem", FileAttributes.Normal); File.Copy(SrcUE4GameBasename + ".worker.js", UE4GameBasename + ".worker.js", true); File.SetAttributes(UE4GameBasename + ".worker.js", FileAttributes.Normal); } else { // nuke possibly old deployed .worker.js, which is not needed for singlethreaded build. File.Delete(UE4GameBasename + ".worker.js"); } } // else, c++ projects will compile "to" PackagePath // note: ( ProjectBasename + ".data" ) already created above (!HTMLPakAutomation.CanCreateMapPaks()) // ---------------------------------------- // generate HTML files to the package directory // custom HTML, JS (if any), and CSS (if any) template files string LocalBuildPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5"); string BuildPath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Build", "HTML5"); string TemplateFile = CombinePaths(BuildPath, "project_template.html"); if (!File.Exists(TemplateFile)) { // fall back to default UE4 template files BuildPath = LocalBuildPath; TemplateFile = CombinePaths(BuildPath, "project_template.html"); } GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".html", Params, SC, ConfigCache); TemplateFile = CombinePaths(BuildPath, "project_template.js"); if (File.Exists(TemplateFile)) { GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".UE4.js", Params, SC, ConfigCache); } TemplateFile = CombinePaths(BuildPath, "project_template.css"); if (File.Exists(TemplateFile)) { GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".css", Params, SC, ConfigCache); } // ---------------------------------------- // (development) support files string MacBashTemplateFile = CombinePaths(LocalBuildPath, "RunMacHTML5LaunchHelper_template.command"); string MacBashOutputFile = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command"); string MonoPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/BatchFiles/Mac/SetupMono.sh"); GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath); // ........................................ string htaccesspath = Path.Combine(PackagePath, ".htaccess"); if (File.Exists(htaccesspath)) { FileAttributes attributes = File.GetAttributes(htaccesspath); if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { attributes &= ~FileAttributes.ReadOnly; File.SetAttributes(htaccesspath, attributes); } } File.Copy(CombinePaths(LocalBuildPath, "htaccess_template.txt"), htaccesspath, true); // ---------------------------------------- // final copies // Gather utlity .js files and combine into one file string DestinationFile = PackagePath + "/Utility.js"; File.Delete(DestinationFile); // spelling this out - one file at a time (i.e. don't slurp in project_template.js) File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "json2.js"))); File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "jstorage.js"))); File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "moz_binarystring.js"))); if (Compressed) { LogInformation("Build configuration is " + ProjectConfiguration + ", so (gzip) compressing files for web servers."); // Compress all files. These are independent tasks which can be threaded. List <Task> CompressionTasks = new List <Task>(); CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".wasm", UE4GameBasename + ".wasmgz"))); // main game code CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js", UE4GameBasename + ".jsgz"))); // main js (emscripten) CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(PackagePath + "/Utility.js", PackagePath + "/Utility.jsgz"))); // Utility CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".data", ProjectBasename + ".datagz"))); // DATA file CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".data.js", ProjectBasename + ".data.jsgz"))); // DATA file .js driver (emscripten) if (File.Exists(UE4GameBasename + ".js.symbols")) { CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js.symbols", UE4GameBasename + ".js.symbolsgz"))); // symbols fil. } if (File.Exists(ProjectBasename + ".UE4.js")) { CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".UE4.js", ProjectBasename + ".UE4.jsgz"))); // UE4 js } if (File.Exists(ProjectBasename + ".css")) { CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".css", ProjectBasename + ".cssgz"))); // UE4 css } if (enableMultithreading) { CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js.mem", UE4GameBasename + ".js.memgz"))); // mem init file CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".worker.js", UE4GameBasename + ".worker.jsgz"))); // pthread file } Task.WaitAll(CompressionTasks.ToArray()); } else { LogInformation("Build configuration is " + ProjectConfiguration + ", so not compressing. Build Shipping configuration to compress files to save space."); // nuke old compressed files to prevent using stale files File.Delete(UE4GameBasename + ".wasmgz"); File.Delete(UE4GameBasename + ".jsgz"); File.Delete(UE4GameBasename + ".js.symbolsgz"); File.Delete(UE4GameBasename + ".js.memgz"); File.Delete(UE4GameBasename + ".worker.jsgz"); File.Delete(PackagePath + "/Utility.jsgz"); File.Delete(ProjectBasename + ".datagz"); File.Delete(ProjectBasename + ".data.jsgz"); File.Delete(ProjectBasename + ".UE4.jsgz"); File.Delete(ProjectBasename + ".cssgz"); } File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"), CombinePaths(PackagePath, "HTML5LaunchHelper.exe"), true); // Task.WaitAll(CompressionTasks); PrintRunTime(); }
/** * Notify stakeholders of the commandlet results */ void SendCompletionMessage(bool bWasSuccessful, String MessageBody) { if (StakeholdersEmailAddresses != null) { MailMessage Message = new System.Net.Mail.MailMessage(); Message.Priority = MailPriority.High; Message.From = new MailAddress("*****@*****.**"); string Branch = "Unknown"; if (P4Enabled) { Branch = P4Env.Branch; } foreach (String NextStakeHolder in StakeholdersEmailAddresses) { Message.To.Add(new MailAddress(NextStakeHolder)); } ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.EditorPerProjectUserSettings, DirectoryReference.FromFile(ProjectFullPath), UnrealTargetPlatform.Win64); List <string> Emails; Ini.GetArray("RebuildHLODSettings", "EmailNotification", out Emails); foreach (var Email in Emails) { Message.CC.Add(new MailAddress(Email)); } Message.Subject = String.Format("Nightly HLOD rebuild {0} for {1}", bWasSuccessful ? "[SUCCESS]" : "[FAILED]", Branch); Message.Body = MessageBody; /*Attachment Attach = new Attachment(); * Message.Attachments.Add()*/ try { #pragma warning disable CS0618 // Mono 4.6.x obsoletes this class SmtpClient MailClient = new SmtpClient("smtp.epicgames.net"); MailClient.Send(Message); #pragma warning restore CS0618 } catch (Exception Ex) { LogError("Failed to send notify email to {0} ({1})", String.Join(", ", StakeholdersEmailAddresses.ToArray()), Ex.Message); } } }
// -------------------------------------------------------------------------------- // RunProjectCommand.Automation.cs public override IProcessResult RunClient(ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params) { // look for browser string BrowserPath = Params.Devices[0].Replace("HTML5@", ""); // open the webpage Int32 ServerPort = 8000; // HTML5LaunchHelper default var ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5); ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "DeployServerPort", out ServerPort); // LaunchOn via Editor or FrontEnd string WorkingDirectory = Path.GetDirectoryName(ClientApp); string url = Path.GetFileName(ClientApp) + ".html"; // UE-64628: seems proxy port is no longer used anymore -- leaving details here for future reference... // // WARNING: splitting the following situation // // if cookonthefly is used: tell the browser to use the PROXY at DEFAULT_HTTP_FILE_SERVING_PORT // // leave the normal HTML5LaunchHelper port (ServerPort) alone -- otherwise it will collide with the PROXY port if (ClientCmdLine.Contains("filehostip")) { url += "?cookonthefly=true"; // Int32 ProxyPort = 41898; // DEFAULT_HTTP_FILE_SERVING_PORT // url = String.Format("http://localhost:{0}/{1}", ProxyPort, url); } // else // { url = String.Format("http://localhost:{0}/{1}", ServerPort, url); // } // Check HTML5LaunchHelper source for command line args var LowerBrowserPath = BrowserPath.ToLower(); var ProfileDirectory = Path.Combine(Utils.GetUserSettingDirectory().FullName, "UE4_HTML5", "user"); string BrowserCommandline = url; if (LowerBrowserPath.Contains("chrome")) { ProfileDirectory = Path.Combine(ProfileDirectory, "chrome"); // removing [--enable-logging] otherwise, chrome breaks with a bunch of the following errors: // > ERROR:process_info.cc(631)] range at 0x7848406c00000000, size 0x1a4 fully unreadable // leaving this note here for future reference: UE-45078 BrowserCommandline += " " + String.Format("--user-data-dir=\\\"{0}\\\" --no-first-run", ProfileDirectory); } else if (LowerBrowserPath.Contains("firefox")) { ProfileDirectory = Path.Combine(ProfileDirectory, "firefox"); BrowserCommandline += " " + String.Format("-no-remote -profile \\\"{0}\\\"", ProfileDirectory); } else if (LowerBrowserPath.Contains("safari")) { // NOT SUPPORTED: cannot have a separate UE4 profile for safari // -- this "can" be done with a different user (e.g. guest) account... // (which is not a turn key solution that can be done within UE4) // -- some have tried using symlinks to "mimic" this // https://discussions.apple.com/thread/3327990 // -- but, none of these are fool proof with an existing/running safari instance // -- also, "Safari Extensions JS" has been officially deprecated as of Safari 12 // (in favor of using "Safari App Extension") // https://developer.apple.com/documentation/safariextensions // this means, Safari "LaunchOn" (UE4 Editor -> Launch -> Safari) will run with your FULL // Safari profile -- so, all of your "previously opened" tabs will all also be opened... } // TODO: test on other platforms to remove this first if() check if (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Linux) { if (!Directory.Exists(ProfileDirectory)) { Directory.CreateDirectory(ProfileDirectory); } } string LauncherArguments = string.Format(" -Browser=\"{0}\" + -BrowserCommandLine=\"{1}\" -ServerPort=\"{2}\" -ServerRoot=\"{3}\" ", new object[] { BrowserPath, BrowserCommandline, ServerPort, WorkingDirectory }); var LaunchHelperPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"); IProcessResult BrowserProcess = Run(LaunchHelperPath, LauncherArguments, null, ClientRunFlags | ERunOptions.NoWaitForExit); return(BrowserProcess); }
public List <ISharedCookedBuild> FindBestBuilds() { // Attempt manifest searching first ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFile), UnrealTargetPlatform.Win64); IEnumerable <string> RawSharedCookedSources = null; Hierarchy.TryGetValues("SharedCookedBuildSettings", "SharedCookedSources", out RawSharedCookedSources); if (RawSharedCookedSources == null) { throw new AutomationException("Unable to locate shared cooked builds. SharedCookedSources not set in Engine.ini [SharedCookedBuildSettings]"); } List <Dictionary <string, string> > ParsedSharedCookSources = new List <Dictionary <string, string> >(); foreach (string RawConfig in RawSharedCookedSources) { Dictionary <string, string> ParsedSource = null; if (ConfigHierarchy.TryParse(RawConfig, out ParsedSource)) { ParsedSharedCookSources.Add(ParsedSource); } } List <ISharedCookedBuild> CandidateBuilds = new List <ISharedCookedBuild>(); // If existing sync is present, stick to it. Read version out of sync file foreach (string Platform in TargetPlatforms) { FileReference SyncedBuildFile = new FileReference(CommandUtils.CombinePaths(InstallPath.FullName, Platform, SyncedBuildFileName)); if (FileReference.Exists(SyncedBuildFile)) { string[] SyncedBuildInfo = FileReference.ReadAllLines(SyncedBuildFile); int SyncedCL = int.Parse(SyncedBuildInfo[0]); if (IsValidCL(SyncedCL, BuildType, LocalSync)) { CandidateBuilds.Add(new ExistingSharedCookedBuild() { CL = SyncedCL, Platform = Platform }); } } } foreach (Dictionary <string, string> Source in ParsedSharedCookSources) { SharedCookSource SourceType = (SharedCookSource)Enum.Parse(typeof(SharedCookSource), Source["Type"], true); foreach (string Platform in TargetPlatforms) { if (SourceType == SharedCookSource.Manifest) { CandidateBuilds.AddRange(FindValidManifestBuilds(Source["Path"], Platform)); } else if (SourceType == SharedCookSource.LooseFiles) { CandidateBuilds.AddRange(FindValidLooseBuilds(Source["Path"], Platform)); } } } // Strip all failed searches CandidateBuilds.RemoveAll(x => x == null); // Make sure we have a matching CL for all target platforms, regardless of source List <int> OrderedDistinctCLs = CandidateBuilds.Select(x => x.CL).Distinct().OrderByDescending(i => i).ToList(); int BestCL = -1; foreach (int CL in OrderedDistinctCLs) { // Ensure we have a platform for each HashSet <string> CLPlatforms = new HashSet <string>(CandidateBuilds.Where(x => x.CL == CL).Select(x => x.Platform).ToList()); if (CLPlatforms.SetEquals(TargetPlatforms)) { BestCL = CL; break; } } if (BestCL < 0) { CommandUtils.LogError("Could not locate valid shared cooked build for all target platforms"); CommandUtils.LogError("Current CL: {0}, Current Code CL: {1}", LocalSync.Changelist, LocalSync.CompatibleChangelist); } return(CandidateBuilds.Where(x => x.CL == BestCL).ToList()); }
public OnlineSubsystemApple(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; if (Target.Platform == UnrealTargetPlatform.IOS || Target.Platform == UnrealTargetPlatform.TVOS) { ConfigHierarchy PlatformGameConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Target.ProjectFile), UnrealTargetPlatform.IOS); PlatformGameConfig.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableSignInWithAppleSupport", out bSignInWithAppleSupported); } else if (Target.Platform == UnrealTargetPlatform.Mac) { // TODO: Mark.Fitt enable Mac support } PrivateIncludePaths.Add("Private"); PublicDefinitions.Add("ONLINESUBSYSTEMAPPLE_PACKAGE=1"); PublicDefinitions.Add("ONLINESUBSYSTEMAPPLE_IDENTITY_ENABLE_SIWA=" + (bSignInWithAppleSupported ? "1" : "0")); PrivateDependencyModuleNames.AddRange( new string[] { "Core", "CoreUObject", "Engine", "OnlineSubsystem", }); if (Target.Platform == UnrealTargetPlatform.Mac || Target.Platform == UnrealTargetPlatform.IOS || Target.Platform == UnrealTargetPlatform.TVOS) { if (bSignInWithAppleSupported) { PublicWeakFrameworks.Add("AuthenticationServices"); } } }