예제 #1
0
        /// <summary>
        /// Attempts to get the SSH private key from the standard locations
        /// </summary>
        /// <param name="OutPrivateKey">If successful, receives the location of the private key that was found</param>
        /// <returns>True if a private key was found, false otherwise</returns>
        private bool TryGetSshPrivateKey(out FileReference OutPrivateKey)
        {
            // Build a list of all the places to look for a private key
            List <DirectoryReference> Locations = new List <DirectoryReference>();

            Locations.Add(DirectoryReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.ApplicationData), "Unreal Engine", "UnrealBuildTool"));
            Locations.Add(DirectoryReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.Personal), "Unreal Engine", "UnrealBuildTool"));
            if (ProjectFile != null)
            {
                Locations.Add(DirectoryReference.Combine(ProjectFile.Directory, "Build", "NotForLicensees"));
                Locations.Add(DirectoryReference.Combine(ProjectFile.Directory, "Build", "NoRedist"));
                Locations.Add(DirectoryReference.Combine(ProjectFile.Directory, "Build"));
            }
            Locations.Add(DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "NotForLicensees"));
            Locations.Add(DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "NoRedist"));
            Locations.Add(DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Build"));

            // Find the first that exists
            foreach (DirectoryReference Location in Locations)
            {
                FileReference KeyFile = FileReference.Combine(Location, "SSHKeys", ServerName, UserName, "RemoteToolChainPrivate.key");
                if (FileReference.Exists(KeyFile))
                {
                    OutPrivateKey = KeyFile;
                    return(true);
                }
            }

            // Nothing found
            OutPrivateKey = null;
            return(false);
        }
예제 #2
0
        /// <summary>
        /// Gets the path to the linker.
        /// </summary>
        static FileReference GetLinkerToolPath(UnrealTargetPlatform Platform, WindowsCompiler Compiler, DirectoryReference DefaultLinkerDir)
        {
            // If we were asked to use Clang, then we'll redirect the path to the compiler to the LLVM installation directory
            if (Compiler == WindowsCompiler.Clang && WindowsPlatform.bAllowClangLinker)
            {
                FileReference LinkerPath = FileReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.ProgramFiles), "LLVM", "bin", "lld.exe");
                if (FileReference.Exists(LinkerPath))
                {
                    return(LinkerPath);
                }

                FileReference LinkerPathX86 = FileReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.ProgramFilesX86), "LLVM", "bin", "lld.exe");
                if (FileReference.Exists(LinkerPathX86))
                {
                    return(LinkerPathX86);
                }

                throw new BuildException("Clang was selected as the Windows compiler, but {0} and {1} were not found.", LinkerPath, LinkerPathX86);
            }
            else if (Compiler == WindowsCompiler.Intel && WindowsPlatform.bAllowICLLinker)
            {
                FileReference LinkerPath = FileReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.ProgramFilesX86), "IntelSWTools", "compilers_and_libraries", "windows", "bin", (Platform == UnrealTargetPlatform.Win32)? "ia32" : "intel64", "xilink.exe");
                if (FileReference.Exists(LinkerPath))
                {
                    return(LinkerPath);
                }

                throw new BuildException("ICL was selected as the Windows compiler, but {0} was not found.", LinkerPath);
            }
            else
            {
                return(FileReference.Combine(DefaultLinkerDir, "link.exe"));
            }
        }
예제 #3
0
        /// <summary>
        /// Gets the path to the library linker.
        /// </summary>
        static FileReference GetLibraryLinkerToolPath(UnrealTargetPlatform Platform, WindowsCompiler Compiler, DirectoryReference DefaultLinkerDir)
        {
            // Regardless of the target, if we're linking on a 64 bit machine, we want to use the 64 bit linker (it's faster than the 32 bit linker)
            if (Compiler == WindowsCompiler.Intel && WindowsPlatform.bAllowICLLinker)
            {
                FileReference LibPath = FileReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.ProgramFilesX86), "IntelSWTools", "compilers_and_libraries", "windows", "bin", Platform == UnrealTargetPlatform.Win32 ? "ia32" : "intel64", "xilib.exe");
                if (FileReference.Exists(LibPath))
                {
                    return(LibPath);
                }

                throw new BuildException("ICL was selected as the Windows compiler, but does not appear to be installed.  Could not find: " + LibPath);
            }
            else
            {
                return(FileReference.Combine(DefaultLinkerDir, "lib.exe"));
            }
        }
예제 #4
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="ProjectFile">Project to read settings from</param>
        public RemoteMac(FileReference ProjectFile)
        {
            this.RsyncExe         = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Extras", "ThirdPartyNotUE", "DeltaCopy", "Binaries", "Rsync.exe");
            this.SshExe           = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Extras", "ThirdPartyNotUE", "DeltaCopy", "Binaries", "Ssh.exe");
            this.ProjectFile      = ProjectFile;
            this.ProjectDirectory = DirectoryReference.FromFile(ProjectFile);

            // Apply settings from the XML file
            XmlConfig.ApplyTo(this);

            // Get the project config file path
            DirectoryReference EngineIniPath = ProjectFile != null ? ProjectFile.Directory : null;

            if (EngineIniPath == null && UnrealBuildTool.GetRemoteIniPath() != null)
            {
                EngineIniPath = new DirectoryReference(UnrealBuildTool.GetRemoteIniPath());
            }
            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, EngineIniPath, UnrealTargetPlatform.IOS);

            // Read the project settings if we don't have anything in the build configuration settings
            if (String.IsNullOrEmpty(ServerName))
            {
                // Read the server name
                string IniServerName;
                if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "RemoteServerName", out IniServerName) && !String.IsNullOrEmpty(IniServerName))
                {
                    this.ServerName = IniServerName;
                }
                else
                {
                    throw new BuildException("Remote compiling requires a server name. Use the editor (Project Settings > IOS) to set up your remote compilation settings.");
                }

                // Parse the username
                string IniUserName;
                if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "RSyncUsername", out IniUserName) && !String.IsNullOrEmpty(IniUserName))
                {
                    this.UserName = IniUserName;
                }
            }

            // Split port out from the server name
            int PortIdx = ServerName.LastIndexOf(':');

            if (PortIdx != -1)
            {
                string Port = ServerName.Substring(PortIdx + 1);
                if (!int.TryParse(Port, out ServerPort))
                {
                    throw new BuildException("Unable to parse port number from '{0}'", ServerName);
                }
                ServerName = ServerName.Substring(0, PortIdx);
            }

            // If a user name is not set, use the current user
            if (String.IsNullOrEmpty(UserName))
            {
                UserName = Environment.UserName;
            }

            // Print out the server info
            Log.TraceInformation("[Remote] Using remote server '{0}' on port {1} (user '{2}')", ServerName, ServerPort, UserName);

            // Get the path to the SSH private key
            string OverrideSshPrivateKeyPath;

            if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "SSHPrivateKeyOverridePath", out OverrideSshPrivateKeyPath) && !String.IsNullOrEmpty(OverrideSshPrivateKeyPath))
            {
                SshPrivateKey = new FileReference(OverrideSshPrivateKeyPath);
                if (!FileReference.Exists(SshPrivateKey))
                {
                    throw new BuildException("SSH private key specified in config file ({0}) does not exist.", SshPrivateKey);
                }
            }

            // If it's not set, look in the standard locations. If that fails, spawn the batch file to generate one.
            if (SshPrivateKey == null && !TryGetSshPrivateKey(out SshPrivateKey))
            {
                Log.TraceWarning("No SSH private key found for {0}@{1}. Launching SSH to generate one.", UserName, ServerName);

                StringBuilder CommandLine = new StringBuilder();
                CommandLine.AppendFormat("/C \"\"{0}\"", FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "BatchFiles", "MakeAndInstallSSHKey.bat"));
                CommandLine.AppendFormat(" \"{0}\"", SshExe);
                CommandLine.AppendFormat(" \"{0}\"", ServerPort);
                CommandLine.AppendFormat(" \"{0}\"", RsyncExe);
                CommandLine.AppendFormat(" \"{0}\"", UserName);
                CommandLine.AppendFormat(" \"{0}\"", ServerName);
                CommandLine.AppendFormat(" \"{0}\"", DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.MyDocuments));
                CommandLine.AppendFormat(" \"{0}\"", GetLocalCygwinPath(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.MyDocuments)));
                CommandLine.AppendFormat(" \"{0}\"", UnrealBuildTool.EngineDirectory);
                CommandLine.Append("\"");

                using (Process ChildProcess = Process.Start("C:\\Windows\\System32\\Cmd.exe", CommandLine.ToString()))
                {
                    ChildProcess.WaitForExit();
                }

                if (!TryGetSshPrivateKey(out SshPrivateKey))
                {
                    throw new BuildException("Failed to generate SSH private key for {0}@{1}.", UserName, ServerName);
                }
            }

            // resolve the rest of the strings
            RsyncAuthentication = ExpandVariables(RsyncAuthentication);
            SshAuthentication   = ExpandVariables(SshAuthentication);

            // Get the remote base directory
            RemoteBaseDir = String.Format("/Users/{0}/UE4/Builds/{1}", UserName, Environment.MachineName);

            // Build the list of directory mappings between the local and remote machines
            Mappings = new List <RemoteMapping>();
            Mappings.Add(new RemoteMapping(UnrealBuildTool.EngineDirectory, GetRemotePath(UnrealBuildTool.EngineDirectory)));
            if (ProjectFile != null && !ProjectFile.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
            {
                Mappings.Add(new RemoteMapping(ProjectFile.Directory, GetRemotePath(ProjectFile.Directory)));
            }

            // Build a list of arguments for SSH
            CommonSshArguments = new List <string>();
            CommonSshArguments.Add("-o BatchMode=yes");
            CommonSshArguments.Add(SshAuthentication);
            CommonSshArguments.Add(String.Format("-p {0}", ServerPort));
            CommonSshArguments.Add(String.Format("\"{0}@{1}\"", UserName, ServerName));

            // Build a list of arguments for Rsync
            CommonRsyncArguments = new List <string>();
            CommonRsyncArguments.Add("--compress");
            CommonRsyncArguments.Add("--recursive");
            CommonRsyncArguments.Add("--delete");            // Delete anything not in the source directory
            CommonRsyncArguments.Add("--delete-excluded");   // Delete anything not in the source directory
            CommonRsyncArguments.Add("--times");             // Preserve modification times
            CommonRsyncArguments.Add("--verbose");
            CommonRsyncArguments.Add("-m");
            CommonRsyncArguments.Add("--chmod=ug=rwX,o=rxX");
            CommonRsyncArguments.Add(String.Format("--rsh=\"{0} -p {1}\"", RsyncAuthentication, ServerPort));
        }
예제 #5
0
        protected IOSProvisioningData(IOSProjectSettings ProjectSettings, bool bIsTVOS, bool bForDistribtion)
        {
            SigningCertificate = ProjectSettings.SigningCertificate;
            string MobileProvision = ProjectSettings.MobileProvision;

            FileReference ProjectFile = ProjectSettings.ProjectFile;

            if (!string.IsNullOrEmpty(SigningCertificate))
            {
                // verify the certificate
                Process IPPProcess = new Process();
                if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                {
                    string IPPCmd = "\"" + UnrealBuildTool.EngineDirectory + "/Binaries/DotNET/IOS/IPhonePackager.exe\" certificates " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + ProjectSettings.BundleIdentifier + (bForDistribtion ? " -distribution" : "");
                    IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                    IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "/Build/BatchFiles/Mac/RunMono.sh";
                    IPPProcess.StartInfo.Arguments        = IPPCmd;
                    IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                }
                else
                {
                    string IPPCmd = "certificates " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + ProjectSettings.BundleIdentifier + (bForDistribtion ? " -distribution" : "");
                    IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                    IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "\\Binaries\\DotNET\\IOS\\IPhonePackager.exe";
                    IPPProcess.StartInfo.Arguments        = IPPCmd;
                    IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                }
                Utils.RunLocalProcess(IPPProcess);
            }
            else
            {
                SigningCertificate = bForDistribtion ? "iPhone Distribution" : "iPhone Developer";
                bHaveCertificate   = true;
            }

            if (!string.IsNullOrEmpty(MobileProvision))
            {
                DirectoryReference MobileProvisionDir;
                if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                {
                    MobileProvisionDir = DirectoryReference.Combine(new DirectoryReference(Environment.GetEnvironmentVariable("HOME")), "Library", "MobileDevice", "Provisioning Profiles");
                }
                else
                {
                    MobileProvisionDir = DirectoryReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.LocalApplicationData), "Apple Computer", "MobileDevice", "Provisioning Profiles");
                }

                FileReference PossibleMobileProvisionFile = FileReference.Combine(MobileProvisionDir, MobileProvision);
                if (FileReference.Exists(PossibleMobileProvisionFile))
                {
                    MobileProvisionFile = PossibleMobileProvisionFile;
                }
            }

            if (MobileProvisionFile == null || !bHaveCertificate)
            {
                SigningCertificate  = "";
                MobileProvision     = "";
                MobileProvisionFile = null;
                Log.TraceLog("Provision not specified or not found for " + ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game") + ", searching for compatible match...");
                Process IPPProcess = new Process();
                if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                {
                    string IPPCmd = "\"" + UnrealBuildTool.EngineDirectory + "/Binaries/DotNET/IOS/IPhonePackager.exe\" signing_match " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + ProjectSettings.BundleIdentifier + (bIsTVOS ? " -tvos" : "") + (bForDistribtion ? " -distribution" : "");
                    IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                    IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "/Build/BatchFiles/Mac/RunMono.sh";
                    IPPProcess.StartInfo.Arguments        = IPPCmd;
                    IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                }
                else
                {
                    string IPPCmd = "signing_match " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + ProjectSettings.BundleIdentifier + (bIsTVOS ? " -tvos" : "") + (bForDistribtion ? " -distribution" : "");
                    IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                    IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "\\Binaries\\DotNET\\IOS\\IPhonePackager.exe";
                    IPPProcess.StartInfo.Arguments        = IPPCmd;
                    IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                }
                Utils.RunLocalProcess(IPPProcess);
                if (MobileProvisionFile != null)
                {
                    Log.TraceLog("Provision found for " + ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game") + ", Provision: " + MobileProvisionFile + " Certificate: " + SigningCertificate);
                }
            }

            // add to the dictionary
            SigningCertificate = SigningCertificate.Replace("\"", "");

            // read the provision to get the UUID
            if (MobileProvisionFile == null)
            {
                Log.TraceLog("No matching provision file was discovered for {0}. Please ensure you have a compatible provision installed.", ProjectFile);
            }
            else if (!FileReference.Exists(MobileProvisionFile))
            {
                Log.TraceLog("Selected mobile provision for {0} ({1}) was not found. Please ensure you have a compatible provision installed.", ProjectFile, MobileProvisionFile);
            }
            else
            {
                byte[] AllBytes = FileReference.ReadAllBytes(MobileProvisionFile);

                uint StartIndex = (uint)AllBytes.Length;
                uint EndIndex   = (uint)AllBytes.Length;

                for (uint i = 0; i + 4 < AllBytes.Length; i++)
                {
                    if (AllBytes[i] == '<' && AllBytes[i + 1] == '?' && AllBytes[i + 2] == 'x' && AllBytes[i + 3] == 'm' && AllBytes[i + 4] == 'l')
                    {
                        StartIndex = i;
                        break;
                    }
                }

                if (StartIndex < AllBytes.Length)
                {
                    for (uint i = StartIndex; i + 7 < AllBytes.Length; i++)
                    {
                        if (AllBytes[i] == '<' && AllBytes[i + 1] == '/' && AllBytes[i + 2] == 'p' && AllBytes[i + 3] == 'l' && AllBytes[i + 4] == 'i' && AllBytes[i + 5] == 's' && AllBytes[i + 6] == 't' && AllBytes[i + 7] == '>')
                        {
                            EndIndex = i + 7;
                            break;
                        }
                    }
                }

                if (StartIndex < AllBytes.Length && EndIndex < AllBytes.Length)
                {
                    byte[] TextBytes = new byte[EndIndex - StartIndex];
                    Buffer.BlockCopy(AllBytes, (int)StartIndex, TextBytes, 0, (int)(EndIndex - StartIndex));

                    string AllText = Encoding.UTF8.GetString(TextBytes);
                    int    idx     = AllText.IndexOf("<key>UUID</key>");
                    if (idx > 0)
                    {
                        idx = AllText.IndexOf("<string>", idx);
                        if (idx > 0)
                        {
                            idx += "<string>".Length;
                            MobileProvisionUUID = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx);
                        }
                    }
                    idx = AllText.IndexOf("<key>com.apple.developer.team-identifier</key>");
                    if (idx > 0)
                    {
                        idx = AllText.IndexOf("<string>", idx);
                        if (idx > 0)
                        {
                            idx     += "<string>".Length;
                            TeamUUID = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx);
                        }
                    }
                    idx = AllText.IndexOf("<key>Name</key>");
                    if (idx > 0)
                    {
                        idx = AllText.IndexOf("<string>", idx);
                        if (idx > 0)
                        {
                            idx += "<string>".Length;
                            MobileProvisionName = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx);
                        }
                    }
                }

                if (string.IsNullOrEmpty(MobileProvisionUUID) || string.IsNullOrEmpty(TeamUUID))
                {
                    MobileProvision    = null;
                    SigningCertificate = null;
                    Log.TraceLog("Failed to parse the mobile provisioning profile.");
                }
            }
        }