Example #1
0
        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;
        }