// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using System.Threading; using System.Reflection; using System.Linq; using System.Net.NetworkInformation; using System.Collections; using AutomationTool; using UnrealBuildTool; /// /// Helper command to run a game. /// /// /// Uses the following command line params: /// -cooked /// -cookonthefly /// -dedicatedserver /// -win32 /// -noclient /// -logwindow /// public partial class Project : CommandUtils { #region Fields /// /// Thread used to read client log file. /// private static Thread ClientLogReaderThread; #endregion #region Run Command // debug commands for the engine to crash public static string[] CrashCommands = { "crash", "CHECK", "GPF", "ASSERT", "ENSURE", "RENDERCRASH", "RENDERCHECK", "RENDERGPF", "THREADCRASH", "THREADCHECK", "THREADGPF", }; /// /// For not-installed runs, returns a temp log folder to make sure it doesn't fall into sandbox paths /// /// private static string GetLogFolderOutsideOfSandbox() { return GlobalCommandLine.Installed ? CmdEnv.LogFolder : CombinePaths(Path.GetTempPath(), CommandUtils.EscapePath(CmdEnv.LocalRoot), "Logs"); } /// /// Fot not-installed runs, copies all logs from the temp log folder back to the UAT log folder. /// private static void CopyLogsBackToLogFolder() { if (!GlobalCommandLine.Installed) { var LogFolderOutsideOfSandbox = GetLogFolderOutsideOfSandbox(); var TempLogFiles = FindFiles_NoExceptions("*", false, LogFolderOutsideOfSandbox); foreach (var LogFilename in TempLogFiles) { var DestFilename = CombinePaths(CmdEnv.LogFolder, Path.GetFileName(LogFilename)); CopyFile_NoExceptions(LogFilename, DestFilename); } } } public static void Run(ProjectParams Params) { Params.ValidateAndLog(); if (!Params.Run) { return; } var LogFolderOutsideOfSandbox = GetLogFolderOutsideOfSandbox(); if (!GlobalCommandLine.Installed) { // In the installed runs, this is the same folder as CmdEnv.LogFolder so delete only in not-installed DeleteDirectory(LogFolderOutsideOfSandbox); CreateDirectory(LogFolderOutsideOfSandbox); } var ServerLogFile = CombinePaths(LogFolderOutsideOfSandbox, "Server.log"); var ClientLogFile = CombinePaths(LogFolderOutsideOfSandbox, Params.EditorTest ? "Editor.log" : "Client.log"); try { RunInternal(Params, ServerLogFile, ClientLogFile); } catch { throw; } finally { CopyLogsBackToLogFolder(); } } private static void RunInternal(ProjectParams Params, string ServerLogFile, string ClientLogFile) { // Setup server process if required. ProcessResult ServerProcess = null; if (Params.CookOnTheFly && !Params.SkipServer) { if (Params.ClientTargetPlatforms.Count > 0) { Platform ClientPlatformInst = Params.ClientTargetPlatformInstances[0]; string TargetCook = ClientPlatformInst.GetCookPlatform(false, Params.HasDedicatedServerAndClient, Params.CookFlavor); ServerProcess = RunCookOnTheFlyServer(Params.RawProjectPath, Params.NoClient ? "" : ServerLogFile, TargetCook, Params.RunCommandline); } else { throw new AutomationException("Failed to run, client target platform not specified"); } } else if (Params.DedicatedServer && !Params.SkipServer) { if (Params.ServerTargetPlatforms.Count > 0) { UnrealTargetPlatform ServerPlatform = Params.ServerTargetPlatforms[0]; ServerProcess = RunDedicatedServer(Params, ServerLogFile, Params.RunCommandline); // With dedicated server, the client connects to local host to load a map. if (ServerPlatform == UnrealTargetPlatform.Linux) { Params.MapToRun = Params.ServerDeviceAddress; } else { Params.MapToRun = "127.0.0.1"; } } else { throw new AutomationException("Failed to run, server target platform not specified"); } } else if (Params.FileServer && !Params.SkipServer) { ServerProcess = RunFileServer(Params, ServerLogFile, Params.RunCommandline); } if (ServerProcess != null) { Log("Waiting a few seconds for the server to start..."); Thread.Sleep(5000); } if (!Params.NoClient) { Log("Starting Client...."); var SC = CreateDeploymentContext(Params, false); ERunOptions ClientRunFlags; string ClientApp; string ClientCmdLine; SetupClientParams(SC, Params, ClientLogFile, out ClientRunFlags, out ClientApp, out ClientCmdLine); // Run the client. if (ServerProcess != null) { RunClientWithServer(ServerLogFile, ServerProcess, ClientApp, ClientCmdLine, ClientRunFlags, ClientLogFile, Params); } else { RunStandaloneClient(SC, ClientLogFile, ClientRunFlags, ClientApp, ClientCmdLine, Params); } } } #endregion #region Client private static void RunStandaloneClient(List DeployContextList, string ClientLogFile, ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params) { if (Params.Unattended) { string LookFor = "Bringing up level for play took"; if (Params.RunAutomationTest != "") { LookFor = "Automation Test Succeeded"; } else if (Params.RunAutomationTests) { LookFor = "Automation Test Queue Empty"; } else if (Params.EditorTest) { LookFor = "Asset discovery search completed in"; } { string AllClientOutput = ""; int LastAutoFailIndex = -1; ProcessResult ClientProcess = null; FileStream ClientProcessLog = null; StreamReader ClientLogReader = null; Log("Starting Client for unattended test...."); ClientProcess = Run(ClientApp, ClientCmdLine + " -FORCELOGFLUSH -testexit=\"" + LookFor + "\"", null, ClientRunFlags | ERunOptions.NoWaitForExit); while (!FileExists(ClientLogFile) && !ClientProcess.HasExited) { Log("Waiting for client logging process to start...{0}", ClientLogFile); Thread.Sleep(2000); } if (!ClientProcess.HasExited) { Thread.Sleep(2000); Log("Client logging process started...{0}", ClientLogFile); ClientProcessLog = File.Open(ClientLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); ClientLogReader = new StreamReader(ClientProcessLog); } if (ClientProcess.HasExited || ClientLogReader == null) { throw new AutomationException("Client exited before we asked it to."); } bool bKeepReading = true; bool WelcomedCorrectly = false; while (!ClientProcess.HasExited && bKeepReading) { while (!ClientLogReader.EndOfStream && bKeepReading && !ClientProcess.HasExited) { string ClientOutput = ClientLogReader.ReadToEnd(); if (!String.IsNullOrEmpty(ClientOutput)) { AllClientOutput += ClientOutput; Console.Write(ClientOutput); if (AllClientOutput.LastIndexOf(LookFor) > AllClientOutput.IndexOf(LookFor)) { Log("Client loaded, lets wait 30 seconds..."); Thread.Sleep(30000); WelcomedCorrectly = true; Log("Test complete..."); bKeepReading = false; } else if (Params.RunAutomationTests) { int FailIndex = AllClientOutput.LastIndexOf("Automation Test Failed"); int ParenIndex = AllClientOutput.LastIndexOf(")"); if (FailIndex >= 0 && ParenIndex > FailIndex && FailIndex > LastAutoFailIndex) { string Tail = AllClientOutput.Substring(FailIndex); int CloseParenIndex = Tail.IndexOf(")"); int OpenParenIndex = Tail.IndexOf("("); string Test = ""; if (OpenParenIndex >= 0 && CloseParenIndex > OpenParenIndex) { Test = Tail.Substring(OpenParenIndex + 1, CloseParenIndex - OpenParenIndex - 1); Log(System.Diagnostics.TraceEventType.Error, "Automated test failed ({0}).", Test); LastAutoFailIndex = FailIndex; } } } } } } if (ClientProcess != null && !ClientProcess.HasExited) { Log("Stopping client..."); ClientProcess.StopProcess(); } if (!WelcomedCorrectly) { throw new AutomationException("Client exited before we asked it to."); } } } else { var SC = DeployContextList[0]; ProcessResult ClientProcess = SC.StageTargetPlatform.RunClient(ClientRunFlags, ClientApp, ClientCmdLine, Params); if (ClientProcess != null) { // If the client runs without StdOut redirect we're going to read the log output directly from log file on // a separate thread. if ((ClientRunFlags & ERunOptions.NoStdOutRedirect) == ERunOptions.NoStdOutRedirect) { ClientLogReaderThread = new System.Threading.Thread(ClientLogReaderProc); ClientLogReaderThread.Start(new object[] { ClientLogFile, ClientProcess }); } do { Thread.Sleep(100); } while (ClientProcess.HasExited == false); if (ClientProcess.ExitCode != 0) { throw new AutomationException("Client exited with error code: " + ClientProcess.ExitCode); } } } } private static void RunClientWithServer(string ServerLogFile, ProcessResult ServerProcess, string ClientApp, string ClientCmdLine, ERunOptions ClientRunFlags, string ClientLogFile, ProjectParams Params) { ProcessResult ClientProcess = null; var OtherClients = new List(); bool WelcomedCorrectly = false; int NumClients = Params.NumClients; string AllClientOutput = ""; int LastAutoFailIndex = -1; if (Params.Unattended) { string LookFor = "Bringing up level for play took"; if (Params.DedicatedServer) { LookFor = "Welcomed by server"; } else if (Params.RunAutomationTest != "") { LookFor = "Automation Test Succeeded"; } else if (Params.RunAutomationTests) { LookFor = "Automation Test Queue Empty"; } { while (!FileExists(ServerLogFile) && !ServerProcess.HasExited) { Log("Waiting for logging process to start..."); Thread.Sleep(2000); } Thread.Sleep(1000); string AllServerOutput = ""; using (FileStream ProcessLog = File.Open(ServerLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { StreamReader LogReader = new StreamReader(ProcessLog); bool bKeepReading = true; FileStream ClientProcessLog = null; StreamReader ClientLogReader = null; // Read until the process has exited. while (!ServerProcess.HasExited && bKeepReading) { while (!LogReader.EndOfStream && bKeepReading && ClientProcess == null) { string Output = LogReader.ReadToEnd(); if (!String.IsNullOrEmpty(Output)) { AllServerOutput += Output; if (ClientProcess == null && (AllServerOutput.Contains("Game Engine Initialized") || AllServerOutput.Contains("Unreal Network File Server is ready"))) { Log("Starting Client for unattended test...."); ClientProcess = Run(ClientApp, ClientCmdLine + " -FORCELOGFLUSH -testexit=\"" + LookFor + "\"", null, ClientRunFlags | ERunOptions.NoWaitForExit); //@todo no testing is done on these if (NumClients > 1 && NumClients < 9) { for (int i = 1; i < NumClients; i++) { Log("Starting Extra Client...."); OtherClients.Add(Run(ClientApp, ClientCmdLine, null, ClientRunFlags | ERunOptions.NoWaitForExit)); } } while (!FileExists(ClientLogFile) && !ClientProcess.HasExited) { Log("Waiting for client logging process to start...{0}", ClientLogFile); Thread.Sleep(2000); } if (!ClientProcess.HasExited) { Thread.Sleep(2000); Log("Client logging process started...{0}", ClientLogFile); ClientProcessLog = File.Open(ClientLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); ClientLogReader = new StreamReader(ClientProcessLog); } } else if (ClientProcess == null && !ServerProcess.HasExited) { Log("Waiting for server to start...."); Thread.Sleep(2000); } if (ClientProcess != null && ClientProcess.HasExited) { ServerProcess.StopProcess(); throw new AutomationException("Client exited before we asked it to."); } } } if (ClientLogReader != null) { if (ClientProcess.HasExited) { ServerProcess.StopProcess(); throw new AutomationException("Client exited or closed the log before we asked it to."); } while (!ClientProcess.HasExited && !ServerProcess.HasExited && bKeepReading) { while (!ClientLogReader.EndOfStream && bKeepReading && !ServerProcess.HasExited && !ClientProcess.HasExited) { string ClientOutput = ClientLogReader.ReadToEnd(); if (!String.IsNullOrEmpty(ClientOutput)) { AllClientOutput += ClientOutput; Console.Write(ClientOutput); if (AllClientOutput.LastIndexOf(LookFor) > AllClientOutput.IndexOf(LookFor)) { if (Params.FakeClient) { Log("Welcomed by server or client loaded, lets wait ten minutes..."); Thread.Sleep(60000 * 10); } else { Log("Welcomed by server or client loaded, lets wait 30 seconds..."); Thread.Sleep(30000); } WelcomedCorrectly = true; bKeepReading = false; } else if (Params.RunAutomationTests) { int FailIndex = AllClientOutput.LastIndexOf("Automation Test Failed"); int ParenIndex = AllClientOutput.LastIndexOf(")"); if (FailIndex >= 0 && ParenIndex > FailIndex && FailIndex > LastAutoFailIndex) { string Tail = AllClientOutput.Substring(FailIndex); int CloseParenIndex = Tail.IndexOf(")"); int OpenParenIndex = Tail.IndexOf("("); string Test = ""; if (OpenParenIndex >= 0 && CloseParenIndex > OpenParenIndex) { Test = Tail.Substring(OpenParenIndex + 1, CloseParenIndex - OpenParenIndex - 1); Log(System.Diagnostics.TraceEventType.Error, "Automated test failed ({0}).", Test); LastAutoFailIndex = FailIndex; } } } } } } } } } } } else { LogFileReaderProcess(ServerLogFile, ServerProcess, (string Output) => { bool bKeepReading = true; if (ClientProcess == null && !String.IsNullOrEmpty(Output)) { AllClientOutput += Output; if (ClientProcess == null && (AllClientOutput.Contains("Game Engine Initialized") || AllClientOutput.Contains("Unreal Network File Server is ready"))) { Log("Starting Client...."); ClientProcess = Run(ClientApp, ClientCmdLine, null, ClientRunFlags | ERunOptions.NoWaitForExit); if (NumClients > 1 && NumClients < 9) { for (int i = 1; i < NumClients; i++) { Log("Starting Extra Client...."); OtherClients.Add(Run(ClientApp, ClientCmdLine, null, ClientRunFlags | ERunOptions.NoWaitForExit)); } } } } else if (ClientProcess == null && !ServerProcess.HasExited) { Log("Waiting for server to start...."); Thread.Sleep(2000); } if (String.IsNullOrEmpty(Output) == false) { Console.Write(Output); } if (ClientProcess != null && ClientProcess.HasExited) { Log("Client exited, stopping server...."); ServerProcess.StopProcess(); bKeepReading = false; } return bKeepReading; // Keep reading }); } Log("Server exited...."); if (ClientProcess != null && !ClientProcess.HasExited) { ClientProcess.StopProcess(); } foreach (var OtherClient in OtherClients) { if (OtherClient != null && !OtherClient.HasExited) { OtherClient.StopProcess(); } } if (Params.Unattended) { if (!WelcomedCorrectly) { throw new AutomationException("Server or client exited before we asked it to."); } } } private static void SetupClientParams(List DeployContextList, ProjectParams Params, string ClientLogFile, out ERunOptions ClientRunFlags, out string ClientApp, out string ClientCmdLine) { if (Params.ClientTargetPlatforms.Count == 0) { throw new AutomationException("No ClientTargetPlatform set for SetupClientParams."); } // var DeployContextList = CreateDeploymentContext(Params, false); if (DeployContextList.Count == 0) { throw new AutomationException("No DeployContextList for SetupClientParams."); } var SC = DeployContextList[0]; // Get client app name and command line. ClientRunFlags = ERunOptions.AllowSpew | ERunOptions.AppMustExist; ClientApp = ""; ClientCmdLine = ""; string TempCmdLine = ""; var PlatformName = Params.ClientTargetPlatforms[0].ToString(); if (Params.Cook || Params.CookOnTheFly) { List Exes = SC.StageTargetPlatform.GetExecutableNames(SC, true); ClientApp = Exes[0]; if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS) { TempCmdLine += SC.ProjectArgForCommandLines + " "; } TempCmdLine += Params.MapToRun + " "; if (Params.CookOnTheFly || Params.FileServer) { TempCmdLine += "-filehostip="; if (UnrealBuildTool.ExternalExecution.GetRuntimePlatform () == UnrealTargetPlatform.Mac) { NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces (); foreach (NetworkInterface adapter in Interfaces) { if (adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback) { IPInterfaceProperties IP = adapter.GetIPProperties (); for (int Index = 0; Index < IP.UnicastAddresses.Count; ++Index) { if (IP.UnicastAddresses [Index].IsDnsEligible && IP.UnicastAddresses [Index].Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { TempCmdLine += IP.UnicastAddresses[Index].Address.ToString(); if (String.IsNullOrEmpty (Params.Port) == false) { TempCmdLine += ":"; TempCmdLine += Params.Port; } TempCmdLine += "+"; } } } } } else { NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces (); foreach (NetworkInterface adapter in Interfaces) { if (adapter.OperationalStatus == OperationalStatus.Up) { IPInterfaceProperties IP = adapter.GetIPProperties(); for (int Index = 0; Index < IP.UnicastAddresses.Count; ++Index) { if (IP.UnicastAddresses[Index].IsDnsEligible) { TempCmdLine += IP.UnicastAddresses[Index].Address.ToString(); if (String.IsNullOrEmpty(Params.Port) == false) { TempCmdLine += ":"; TempCmdLine += Params.Port; } TempCmdLine += "+"; } } } } } TempCmdLine += "127.0.0.1"; if (String.IsNullOrEmpty(Params.Port) == false) { TempCmdLine += ":"; TempCmdLine += Params.Port; } TempCmdLine += " "; if (!Params.Stage) { TempCmdLine += "-streaming "; } else if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS) { // per josh, allowcaching is deprecated/doesn't make sense for iOS. TempCmdLine += "-allowcaching "; } } else if (Params.Pak || Params.SignedPak) { if (Params.SignedPak) { TempCmdLine += "-signedpak "; } else { TempCmdLine += "-pak "; } } else if (!Params.Stage) { var SandboxPath = CombinePaths(SC.RuntimeProjectRootDir, "Saved", "Cooked", SC.CookPlatform); if (!SC.StageTargetPlatform.LaunchViaUFE) { TempCmdLine += "-sandbox=" + CommandUtils.MakePathSafeToUseWithCommandLine(SandboxPath) + " "; } else { TempCmdLine += "-sandbox=\'" + SandboxPath + "\' "; } } } else { ClientApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries", PlatformName, "UE4Editor.exe"); TempCmdLine += SC.ProjectArgForCommandLines + " "; if (!Params.EditorTest) { TempCmdLine += "-game " + Params.MapToRun + " "; } } if (Params.LogWindow) { // Without NoStdOutRedirect '-log' doesn't log anything to the window ClientRunFlags |= ERunOptions.NoStdOutRedirect; TempCmdLine += "-log "; } else { TempCmdLine += "-stdout "; } if (Params.Unattended) { TempCmdLine += "-unattended "; } if (IsBuildMachine || Params.Unattended) { TempCmdLine += "-buildmachine "; } if (Params.CrashIndex > 0) { int RealIndex = Params.CrashIndex - 1; if (RealIndex < 0 || RealIndex >= CrashCommands.Count()) { throw new AutomationException("CrashIndex {0} is out of range...max={1}", Params.CrashIndex, CrashCommands.Count()); } TempCmdLine += String.Format("-execcmds=\"debug {0}\" ", CrashCommands[RealIndex]); } else if (Params.RunAutomationTest != "") { TempCmdLine += "-execcmds=\"automation list, automation run " + Params.RunAutomationTest + "\" "; } else if (Params.RunAutomationTests) { TempCmdLine += "-execcmds=\"automation list, automation runall\" "; } if (!SC.StageTargetPlatform.LaunchViaUFE) { TempCmdLine += "-abslog=" + CommandUtils.MakePathSafeToUseWithCommandLine(ClientLogFile) + " "; } if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS) { TempCmdLine += "-Messaging -nomcp -Windowed "; } else { // skip arguments which don't make sense for iOS TempCmdLine += "-Messaging -nomcp "; } if (Params.NullRHI && SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.Mac) // all macs have GPUs, and currently the mac dies with nullrhi { TempCmdLine += "-nullrhi "; } TempCmdLine += "-CrashForUAT "; TempCmdLine += Params.RunCommandline; // todo: move this into the platform if (SC.StageTargetPlatform.LaunchViaUFE) { ClientCmdLine = "-run=Launch "; ClientCmdLine += "-Device=" + Params.Device + " "; ClientCmdLine += "-Exe=\"" + ClientApp + "\" "; ClientCmdLine += "-Targetplatform=" + Params.ClientTargetPlatforms[0].ToString() + " "; ClientCmdLine += "-Params=\"" + TempCmdLine + "\""; ClientApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/Win64/UnrealFrontend.exe"); Log("Launching via UFE:"); Log("\tClientCmdLine: " + ClientCmdLine + ""); } else { ClientCmdLine = TempCmdLine; } } #endregion #region Client Thread private static void ClientLogReaderProc(object ArgsContainer) { var Args = ArgsContainer as object[]; var ClientLogFile = (string)Args[0]; var ClientProcess = (ProcessResult)Args[1]; LogFileReaderProcess(ClientLogFile, ClientProcess, (string Output) => { if (String.IsNullOrEmpty(Output) == false) { Log(Output); } return true; }); } #endregion #region Servers private static ProcessResult RunDedicatedServer(ProjectParams Params, string ServerLogFile, string AdditionalCommandLine) { ProjectParams ServerParams = new ProjectParams(Params); ServerParams.Device = Params.ServerDevice; if (ServerParams.ServerTargetPlatforms.Count == 0) { throw new AutomationException("No ServerTargetPlatform set for RunDedicatedServer."); } var DeployContextList = CreateDeploymentContext(ServerParams, true); if (DeployContextList.Count == 0) { throw new AutomationException("No DeployContextList for RunDedicatedServer."); } var SC = DeployContextList[0]; var ServerApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/Win64/UE4Editor.exe"); if (ServerParams.Cook) { List Exes = SC.StageTargetPlatform.GetExecutableNames(SC); ServerApp = Exes[0]; } var Args = ServerParams.Cook ? "" : (SC.ProjectArgForCommandLines + " "); Console.WriteLine(Params.ServerDeviceAddress); UnrealTargetPlatform ServerPlatform = ServerParams.ServerTargetPlatforms[0]; if (ServerParams.Cook && ServerPlatform == UnrealTargetPlatform.Linux && !String.IsNullOrEmpty(ServerParams.ServerDeviceAddress)) { ServerApp = @"C:\Windows\system32\cmd.exe"; string plinkPath = CombinePaths(Environment.GetEnvironmentVariable("LINUX_ROOT"), "bin/PLINK.exe "); string exePath = CombinePaths(SC.ShortProjectName, "Binaries", ServerPlatform.ToString(), SC.ShortProjectName + "Server"); if (ServerParams.ServerConfigsToBuild[0] != UnrealTargetConfiguration.Development) { exePath += "-" + ServerPlatform.ToString() + "-" + ServerParams.ServerConfigsToBuild[0].ToString(); } exePath = CombinePaths("LinuxServer", exePath.ToLower()).Replace("\\", "/"); Args = String.Format("/k {0} -batch -ssh -t -i {1} {2}@{3} {4} {5} {6} -server -Messaging", plinkPath, ServerParams.DevicePassword, ServerParams.DeviceUsername, ServerParams.ServerDeviceAddress, exePath, Args, ServerParams.MapToRun); } else { var Map = ServerParams.MapToRun; if (!String.IsNullOrEmpty(ServerParams.AdditionalServerMapParams)) { Map += ServerParams.AdditionalServerMapParams; } if (Params.FakeClient) { Map += "?fake"; } Args += String.Format("{0} -server -abslog={1} -unattended -FORCELOGFLUSH -log -Messaging -nomcp", Map, CommandUtils.MakePathSafeToUseWithCommandLine(ServerLogFile)); } if (ServerParams.Pak || ServerParams.SignedPak) { if (ServerParams.SignedPak) { Args += " -signedpak"; } else { Args += " -pak"; } } if (IsBuildMachine || Params.Unattended) { Args += " -buildmachine"; } Args += " -CrashForUAT"; Args += " " + AdditionalCommandLine; if (ServerParams.Cook && ServerPlatform == UnrealTargetPlatform.Linux && !String.IsNullOrEmpty(ServerParams.ServerDeviceAddress)) { Args += String.Format(" 2>&1 > {0}", ServerLogFile); } PushDir(Path.GetDirectoryName(ServerApp)); var Result = Run(ServerApp, Args, null, ERunOptions.AllowSpew | ERunOptions.NoWaitForExit | ERunOptions.AppMustExist | ERunOptions.NoStdOutRedirect); PopDir(); return Result; } private static ProcessResult RunCookOnTheFlyServer(string ProjectName, string ServerLogFile, string TargetPlatform, string AdditionalCommandLine) { var ServerApp = HostPlatform.Current.GetUE4ExePath("UE4Editor.exe"); var Args = String.Format("{0} -run=cook -targetplatform={1} -cookonthefly -unattended -CrashForUAT -FORCELOGFLUSH -log", CommandUtils.MakePathSafeToUseWithCommandLine(ProjectName), TargetPlatform); if (!String.IsNullOrEmpty(ServerLogFile)) { Args += " -abslog=" + CommandUtils.MakePathSafeToUseWithCommandLine(ServerLogFile); } if (IsBuildMachine) { Args += " -buildmachine"; } Args += " " + AdditionalCommandLine; // Run the server (Without NoStdOutRedirect -log doesn't log anything to the window) PushDir(Path.GetDirectoryName(ServerApp)); var Result = Run(ServerApp, Args, null, ERunOptions.AllowSpew | ERunOptions.NoWaitForExit | ERunOptions.AppMustExist | ERunOptions.NoStdOutRedirect); PopDir(); return Result; } private static ProcessResult RunFileServer(ProjectParams Params, string ServerLogFile, string AdditionalCommandLine) { #if false // this section of code would provide UFS with a more accurate file mapping var SC = new StagingContext(Params, false); CreateStagingManifest(SC); MaybeConvertToLowerCase(Params, SC); var UnrealFileServerResponseFile = new List(); foreach (var Pair in SC.UFSStagingFiles) { string Src = Pair.Key; string Dest = Pair.Value; Dest = CombinePaths(PathSeparator.Slash, SC.UnrealFileServerInternalRoot, Dest); UnrealFileServerResponseFile.Add("\"" + Src + "\" \"" + Dest + "\""); } string UnrealFileServerResponseFileName = CombinePaths(CmdEnv.LogFolder, "UnrealFileServerList.txt"); File.WriteAllLines(UnrealFileServerResponseFileName, UnrealFileServerResponseFile); #endif var UnrealFileServerExe = HostPlatform.Current.GetUE4ExePath("UnrealFileServer.exe"); Log("Running UnrealFileServer *******"); var Args = String.Format("{0} -abslog={1} -unattended -CrashForUAT -FORCELOGFLUSH -log {2}", CommandUtils.MakePathSafeToUseWithCommandLine(Params.RawProjectPath), CommandUtils.MakePathSafeToUseWithCommandLine(ServerLogFile), AdditionalCommandLine); if (IsBuildMachine) { Args += " -buildmachine"; } PushDir(Path.GetDirectoryName(UnrealFileServerExe)); var Result = Run(UnrealFileServerExe, Args, null, ERunOptions.AllowSpew | ERunOptions.NoWaitForExit | ERunOptions.AppMustExist | ERunOptions.NoStdOutRedirect); PopDir(); return Result; } #endregion }