private RemoteToolChainErrorCode InitializeRemoteExecution() { if (bHasBeenInitialized) { return(InitializationErrorCode); } // don't need to set up the remote environment if we're simply listing build folders. if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac && !UEBuildConfiguration.bListBuildFolders) { // If we don't care which machine we're going to build on, query and // pick the one with the most free command slots available if (RemoteServerName == "best_available") { int AvailableSlots = 0; int Attempts = 0; if (!ProjectFileGenerator.bGenerateProjectFiles) { Log.TraceInformation("Picking a random Mac builder..."); } while (AvailableSlots < 2 && Attempts < 20) { RemoteServerName = PotentialServerNames.OrderBy(x => Guid.NewGuid()).FirstOrDefault(); // make sure it's ready to take commands AvailableSlots = GetAvailableCommandSlotCount(RemoteServerName); Attempts++; } // make sure it succeeded if (AvailableSlots <= 1) { throw new BuildException("Failed to find a Mac available to take commands!"); } else if (!ProjectFileGenerator.bGenerateProjectFiles) { Log.TraceInformation("Chose {0} after {1} attempts to find a Mac, with {2} slots", RemoteServerName, Attempts, AvailableSlots); } /* * this does not work right, because it pushes a lot of tasks to machines that have substantially more slots than others * Log.TraceInformation("Picking the best available Mac builder..."); * Int32 MostAvailableCount = Int32.MinValue; * foreach (string NextMacName in PotentialServerNames) * { * Int32 NextAvailableCount = GetAvailableCommandSlotCount(NextMacName); * if (NextAvailableCount > MostAvailableCount) * { * MostAvailableName = NextMacName; * MostAvailableCount = NextAvailableCount; * } * * Log.TraceVerbose("... " + NextMacName + " has " + NextAvailableCount + " slots available"); * } * Log.TraceVerbose("Picking the compile server with the most available command slots: " + MostAvailableName); * * // Finally, assign the name of the Mac we're going to use * RemoteServerName = MostAvailableName; */ } else if (!ProjectFileGenerator.bGenerateProjectFiles) { Log.TraceInformation("Picking the default remote server " + RemoteServerName); } // we need a server name! if (string.IsNullOrEmpty(RemoteServerName)) { Log.TraceError("Remote compiling requires a server name. Use the editor (Project Settings, IOS) to set up your remote compilation settings."); return(RemoteToolChainErrorCode.ServerNameNotSpecified); } // Split port out from RemoteServerName String[] RemoteServerNameSplit = RemoteServerName.Split(':'); if (RemoteServerNameSplit.Length > 1) { if (RemoteServerNameSplit.Length != 2) { Log.TraceError("Remote compiling server name contains too many colons."); return(RemoteToolChainErrorCode.ServerNameNotSpecified); } RemoteServerName = RemoteServerNameSplit[0]; RemoteServerPort = Convert.ToInt32(RemoteServerNameSplit[1]); } if (!bUseRPCUtil) { // Verify the Delta Copy install path ResolvedRSyncExe = ResolveString(RSyncExe, true); ResolvedSSHExe = ResolveString(SSHExe, true); if (!File.Exists(ResolvedRSyncExe) || !File.Exists(ResolvedSSHExe)) { Log.TraceError("Remote compiling requires Delta Copy to be installed. Use the editor (Project Settings, IOS) to set up your remote compilation settings."); return(RemoteToolChainErrorCode.MissingDeltaCopyInstall); } // we need the RemoteServerName and the Username to find the private key ResolvedRSyncUsername = ResolveString(RSyncUsername, false); if (string.IsNullOrEmpty(ResolvedRSyncUsername)) { Log.TraceError("Remote compiling requires a user name. Use the editor (Project Settings, IOS) to set up your remote compilation settings."); return(RemoteToolChainErrorCode.MissingRemoteUserName); } bool bFoundOverrideSSHPrivateKey = false; // if the override path is set, just use it directly if (!string.IsNullOrEmpty(SSHPrivateKeyOverridePath)) { ResolvedSSHPrivateKey = ResolveString(SSHPrivateKeyOverridePath, true); bFoundOverrideSSHPrivateKey = File.Exists(ResolvedSSHPrivateKey); // make sure it exists if (!bFoundOverrideSSHPrivateKey) { Log.TraceWarning("An SSHKey override was specified [" + SSHPrivateKeyOverridePath + "] but it doesn't exist. Looking elsewhere..."); } } if (!bFoundOverrideSSHPrivateKey) { // all the places to look for a key List <string> Locations = new List <string>(); Locations.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Unreal Engine", "UnrealBuildTool")); Locations.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Unreal Engine", "UnrealBuildTool")); if (ProjectFile != null) { Locations.Add(Path.Combine(ProjectFile.Directory.FullName, "Build", "NotForLicensees")); Locations.Add(Path.Combine(ProjectFile.Directory.FullName, "Build", "NoRedist")); Locations.Add(Path.Combine(ProjectFile.Directory.FullName, "Build")); } Locations.Add(Path.Combine(BuildConfiguration.RelativeEnginePath, "Build", "NotForLicensees")); Locations.Add(Path.Combine(BuildConfiguration.RelativeEnginePath, "Build", "NoRedist")); Locations.Add(Path.Combine(BuildConfiguration.RelativeEnginePath, "Build")); // look for a key file foreach (string Location in Locations) { string KeyPath = Path.Combine(Location, "SSHKeys", RemoteServerName, ResolvedRSyncUsername, "RemoteToolChainPrivate.key"); if (File.Exists(KeyPath)) { ResolvedSSHPrivateKey = KeyPath; bFoundOverrideSSHPrivateKey = true; break; } } } // resolve the rest of the strings ResolvedRsyncAuthentication = ResolveString(RsyncAuthentication, false) + " -p " + RemoteServerPort; ResolvedSSHAuthentication = ResolveString(SSHAuthentication, false) + " -p " + RemoteServerPort; } // start up remote communication and record if it succeeds InitializationErrorCode = (RemoteToolChainErrorCode)RPCUtilHelper.Initialize(RemoteServerName); if (InitializationErrorCode != RemoteToolChainErrorCode.NoError && InitializationErrorCode != RemoteToolChainErrorCode.MissingSSHKey) { Log.TraceError("Failed to initialize a connection to the Remote Server {0}", RemoteServerName); return(InitializationErrorCode); } else if (InitializationErrorCode == RemoteToolChainErrorCode.MissingSSHKey) { // Allow the user to set up a key from here. Process KeyProcess = new Process(); KeyProcess.StartInfo.WorkingDirectory = Path.GetFullPath(Path.Combine(BuildConfiguration.RelativeEnginePath, "Build", "BatchFiles")); KeyProcess.StartInfo.FileName = "MakeAndInstallSSHKey.bat"; KeyProcess.StartInfo.Arguments = string.Format( "\"{0}\" {1} \"{2}\" {3} {4} \"{5}\" \"{6}\" \"{7}\"", ResolvedSSHExe, RemoteServerPort, ResolvedRSyncExe, ResolvedRSyncUsername, RemoteServerName, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ConvertPathToCygwin(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)), Path.GetFullPath(BuildConfiguration.RelativeEnginePath)); KeyProcess.Start(); KeyProcess.WaitForExit(); // make sure it succeeded if we want to re-init if (KeyProcess.ExitCode == 0) { InitializationErrorCode = InitializeRemoteExecution(); } } } else { RemoteServerName = Environment.MachineName; // can't error in this case } bHasBeenInitialized = true; return(InitializationErrorCode); }
private static RemoteToolChainErrorCode InitializeRemoteExecution() { if (bHasBeenInitialized) { return InitializationErrorCode; } if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { // If we don't care which machine we're going to build on, query and // pick the one with the most free command slots available if (RemoteServerName == "best_available") { int AvailableSlots = 0; int Attempts = 0; if (!ProjectFileGenerator.bGenerateProjectFiles) { Log.TraceInformation("Picking a random Mac builder..."); } while (AvailableSlots < 2 && Attempts < 20) { RemoteServerName = PotentialServerNames.OrderBy(x => Guid.NewGuid()).FirstOrDefault(); // make sure it's ready to take commands AvailableSlots = GetAvailableCommandSlotCount(RemoteServerName); Attempts++; } // make sure it succeeded if (AvailableSlots <= 1) { throw new BuildException("Failed to find a Mac available to take commands!"); } else if (!ProjectFileGenerator.bGenerateProjectFiles) { Log.TraceInformation("Chose {0} after {1} attempts to find a Mac, with {2} slots", RemoteServerName, Attempts, AvailableSlots); } /* * this does not work right, because it pushes a lot of tasks to machines that have substantially more slots than others Log.TraceInformation("Picking the best available Mac builder..."); Int32 MostAvailableCount = Int32.MinValue; foreach (string NextMacName in PotentialServerNames) { Int32 NextAvailableCount = GetAvailableCommandSlotCount(NextMacName); if (NextAvailableCount > MostAvailableCount) { MostAvailableName = NextMacName; MostAvailableCount = NextAvailableCount; } Log.TraceVerbose("... " + NextMacName + " has " + NextAvailableCount + " slots available"); } Log.TraceVerbose("Picking the compile server with the most available command slots: " + MostAvailableName); // Finally, assign the name of the Mac we're going to use RemoteServerName = MostAvailableName; */ } else if (!ProjectFileGenerator.bGenerateProjectFiles) { Log.TraceInformation("Picking the default remote server " + RemoteServerName); } // we need a server name! if (string.IsNullOrEmpty(RemoteServerName)) { Log.TraceError("Remote compiling requires a server name. Use the editor to set up your remote compilation settings."); return RemoteToolChainErrorCode.ServerNameNotSpecified; } if (!bUseRPCUtil) { // Verify the Delta Copy install path ResolvedRSyncExe = ResolveString(RSyncExe, true); ResolvedSSHExe = ResolveString(SSHExe, true); if (!File.Exists(ResolvedRSyncExe) || !File.Exists(ResolvedSSHExe)) { Log.TraceError("Remote compiling requires Delta Copy to be installed."); return RemoteToolChainErrorCode.MissingDeltaCopyInstall; } // we need the RemoteServerName and the Username to find the private key ResolvedRSyncUsername = ResolveString(RSyncUsername, false); if (string.IsNullOrEmpty(ResolvedRSyncUsername)) { Log.TraceError("Remote compiling requires a user name. Use the editor to set up your remote compilation settings."); return RemoteToolChainErrorCode.MissingRemoteUserName; } bool bFoundOverrideSSHPrivateKey = false; // if the override path is set, just use it directly if (!string.IsNullOrEmpty(SSHPrivateKeyOverridePath)) { ResolvedSSHPrivateKey = ResolveString(SSHPrivateKeyOverridePath, true); bFoundOverrideSSHPrivateKey = File.Exists(ResolvedSSHPrivateKey); // make sure it exists if (!bFoundOverrideSSHPrivateKey) { Log.TraceWarning("An SSHKey override was specified [" + SSHPrivateKeyOverridePath + "] but it doesn't exist. Looking elsewhere..."); } } if (!bFoundOverrideSSHPrivateKey) { // all the places to look for a key string[] Locations = new string[] { Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Unreal Engine", "UnrealBuildTool"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Unreal Engine", "UnrealBuildTool"), Path.Combine(UnrealBuildTool.GetUProjectPath(), "Build", "NotForLicensees"), Path.Combine(UnrealBuildTool.GetUProjectPath(), "Build", "NoRedist"), Path.Combine(UnrealBuildTool.GetUProjectPath(), "Build"), Path.Combine(BuildConfiguration.RelativeEnginePath, "Build", "NotForLicensees"), Path.Combine(BuildConfiguration.RelativeEnginePath, "Build", "NoRedist"), Path.Combine(BuildConfiguration.RelativeEnginePath, "Build"), }; // look for a key file foreach (string Location in Locations) { string KeyPath = Path.Combine(Location, "SSHKeys", RemoteServerName, ResolvedRSyncUsername, "RemoteToolChainPrivate.key"); if (File.Exists(KeyPath)) { ResolvedSSHPrivateKey = KeyPath; bFoundOverrideSSHPrivateKey = true; break; } } } // resolve the rest of the strings ResolvedRsyncAuthentication = ResolveString(RsyncAuthentication, false); ResolvedSSHAuthentication = ResolveString(SSHAuthentication, false); } // start up remote communication and record if it succeeds InitializationErrorCode = (RemoteToolChainErrorCode)RPCUtilHelper.Initialize(RemoteServerName); if (InitializationErrorCode != RemoteToolChainErrorCode.NoError && InitializationErrorCode != RemoteToolChainErrorCode.MissingSSHKey) { Log.TraceError("Failed to initialize a connection to the Remote Server {0}", RemoteServerName); return InitializationErrorCode; } else if (InitializationErrorCode == RemoteToolChainErrorCode.MissingSSHKey) { // Allow the user to set up a key from here. Process KeyProcess = new Process(); KeyProcess.StartInfo.WorkingDirectory = Path.GetFullPath(Path.Combine(BuildConfiguration.RelativeEnginePath, "Build", "BatchFiles")); KeyProcess.StartInfo.FileName = "MakeAndInstallSSHKey.bat"; KeyProcess.StartInfo.Arguments = string.Format( "\"{0}\" \"{1}\" {2} {3} \"{4}\" \"{5}\" \"{6}\"", ResolvedSSHExe, ResolvedRSyncExe, ResolvedRSyncUsername, RemoteServerName, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ConvertPathToCygwin(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)), Path.GetFullPath(BuildConfiguration.RelativeEnginePath)); KeyProcess.Start(); KeyProcess.WaitForExit(); // make sure it succeeded if we want to re-init if (KeyProcess.ExitCode == 0) { InitializationErrorCode = InitializeRemoteExecution(); } } } else { RemoteServerName = Environment.MachineName; // can't error in this case } bHasBeenInitialized = true; return InitializationErrorCode; }