static public bool UploadFile(string LocalPath, string RemotePath) { string RemoteDir = Path.GetDirectoryName(RemotePath).Replace("\\", "/"); RemoteDir = RemoteDir.Replace(" ", "\\ "); string RemoteFilename = Path.GetFileName(RemotePath); // get the executable dir for SSH, so Rsync can call it easily string ExeDir = Path.GetDirectoryName(ResolvedSSHExe); Process RsyncProcess = new Process(); if (ExeDir != "") { RsyncProcess.StartInfo.WorkingDirectory = ExeDir; } // make simple rsync commandline to send a file RsyncProcess.StartInfo.FileName = ResolvedRSyncExe; RsyncProcess.StartInfo.Arguments = string.Format( "-zae \"{0}\" --rsync-path=\"mkdir -p {1} && rsync\" --chmod=ug=rwX,o=rxX '{2}' {3}@{4}:'{1}/{5}'", ResolvedRsyncAuthentication, RemoteDir, ConvertPathToCygwin(LocalPath), RSyncUsername, RemoteServerName, RemoteFilename ); RsyncProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedForRsync); RsyncProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedForRsync); // run rsync (0 means success) return(Utils.RunLocalProcess(RsyncProcess) == 0); }
static public bool DownloadFile(string RemotePath, string LocalPath) { // get the executable dir for SSH, so Rsync can call it easily string ExeDir = Path.GetDirectoryName(ResolvedSSHExe); string RemoteDir = RemotePath.Replace(" ", "\\ "); Process RsyncProcess = new Process(); if (ExeDir != "") { RsyncProcess.StartInfo.WorkingDirectory = ExeDir; } // make sure directory exists to download to Directory.CreateDirectory(Path.GetDirectoryName(LocalPath)); // make simple rsync commandline to send a file RsyncProcess.StartInfo.FileName = ResolvedRSyncExe; RsyncProcess.StartInfo.Arguments = string.Format( "-zae \"{0}\" {2}@{3}:'{4}' \"{1}\"", ResolvedRsyncAuthentication, ConvertPathToCygwin(LocalPath), RSyncUsername, RemoteServerName, RemoteDir ); RsyncProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedForRsync); RsyncProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedForRsync); //Console.WriteLine("COPY: {0} {1}", RsyncProcess.StartInfo.FileName, RsyncProcess.StartInfo.Arguments); // run rsync (0 means success) return(Utils.RunLocalProcess(RsyncProcess) == 0); }
/// <summary> /// Execute a remote command, capturing the output text /// </summary> /// <param name="Command">Command to be executed</param> /// <param name="Output">Receives the output text</param> /// <returns></returns> protected int ExecuteAndCaptureOutput(string Command, out StringBuilder Output) { StringBuilder FullCommand = new StringBuilder(); foreach (string CommonSshArgument in CommonSshArguments) { FullCommand.AppendFormat("{0} ", CommonSshArgument); } FullCommand.Append(Command.Replace("\"", "\\\"")); using (Process SSHProcess = new Process()) { Output = new StringBuilder(); StringBuilder OutputLocal = Output; DataReceivedEventHandler OutputHandler = (E, Args) => { if (Args.Data != null) { OutputLocal.Append(Args.Data); } }; SSHProcess.StartInfo.FileName = SshExe.FullName; SSHProcess.StartInfo.WorkingDirectory = SshExe.Directory.FullName; SSHProcess.StartInfo.Arguments = FullCommand.ToString(); SSHProcess.OutputDataReceived += OutputHandler; SSHProcess.ErrorDataReceived += OutputHandler; Log.TraceLog("[SSH] {0} {1}", Utils.MakePathSafeToUseWithCommandLine(SSHProcess.StartInfo.FileName), SSHProcess.StartInfo.Arguments); return(Utils.RunLocalProcess(SSHProcess)); } }
/// <summary> /// /// </summary> /// <param name="ProjectFile"></param> /// <param name="Executable"></param> /// <param name="StageDirectory"></param> /// <param name="PlatformType"></param> public static void GenerateAssetCatalog(FileReference ProjectFile, FileReference Executable, DirectoryReference StageDirectory, UnrealTargetPlatform PlatformType) { CppPlatform Platform = PlatformType == UnrealTargetPlatform.IOS ? CppPlatform.IOS : CppPlatform.TVOS; // Determine whether the user has modified icons that require a remote Mac to build. bool bUserImagesExist = false; DirectoryReference ResourcesDir = IOSToolChain.GenerateAssetCatalog(ProjectFile, Platform, ref bUserImagesExist); // Don't attempt to do anything remotely if the user is using the default UE4 images. if (!bUserImagesExist) { return; } // Also don't attempt to use a remote Mac if packaging for TVOS on PC. if (Platform == CppPlatform.TVOS && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { return; } // Compile the asset catalog immediately if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { FileReference OutputFile = FileReference.Combine(StageDirectory, "Assets.car"); RemoteMac Remote = new RemoteMac(ProjectFile); Remote.RunAssetCatalogTool(Platform, ResourcesDir, OutputFile); } else { // Get the output file FileReference OutputFile = IOSToolChain.GetAssetCatalogFile(Platform, Executable); // Delete the Assets.car file to force the asset catalog to build every time, because // removals of files or copies of icons (for instance) with a timestamp earlier than // the last generated Assets.car will result in nothing built. if (FileReference.Exists(OutputFile)) { FileReference.Delete(OutputFile); } // Run the process locally using (Process Process = new Process()) { Process.StartInfo.FileName = "/usr/bin/xcrun"; Process.StartInfo.Arguments = IOSToolChain.GetAssetCatalogArgs(Platform, ResourcesDir.FullName, OutputFile.Directory.FullName);; Process.StartInfo.UseShellExecute = false; Utils.RunLocalProcess(Process); } } }
/// <summary> /// Execute Rsync /// </summary> /// <param name="Arguments">Arguments for the Rsync command</param> /// <returns>Exit code from Rsync</returns> private int Rsync(string Arguments) { using (Process RsyncProcess = new Process()) { RsyncProcess.StartInfo.FileName = RsyncExe.FullName; RsyncProcess.StartInfo.Arguments = Arguments; RsyncProcess.StartInfo.WorkingDirectory = SshExe.Directory.FullName; RsyncProcess.OutputDataReceived += RsyncOutput; RsyncProcess.ErrorDataReceived += RsyncOutput; Log.TraceLog("[Rsync] {0} {1}", Utils.MakePathSafeToUseWithCommandLine(RsyncProcess.StartInfo.FileName), RsyncProcess.StartInfo.Arguments); return(Utils.RunLocalProcess(RsyncProcess)); } }
/// <summary> /// Execute a remote command, capturing the output text /// </summary> /// <param name="WorkingDirectory">The remote working directory</param> /// <param name="Command">Command to be executed</param> /// <returns></returns> protected int Execute(string WorkingDirectory, string Command) { string FullCommand = String.Format("cd {0} && {1}", EscapeShellArgument(WorkingDirectory), Command); using (Process SSHProcess = new Process()) { DataReceivedEventHandler OutputHandler = (E, Args) => { SshOutput(Args); }; SSHProcess.StartInfo.FileName = SshExe.FullName; SSHProcess.StartInfo.WorkingDirectory = SshExe.Directory.FullName; SSHProcess.StartInfo.Arguments = String.Format("{0} {1}", String.Join(" ", CommonSshArguments), FullCommand.Replace("\"", "\\\"")); SSHProcess.OutputDataReceived += OutputHandler; SSHProcess.ErrorDataReceived += OutputHandler; Log.TraceLog("[SSH] {0} {1}", Utils.MakePathSafeToUseWithCommandLine(SSHProcess.StartInfo.FileName), SSHProcess.StartInfo.Arguments); return(Utils.RunLocalProcess(SSHProcess)); } }
static public Int32 QueryRemoteMachine(string MachineName, string Command) { // we must run the commandline RPCUtility, because we could run this before we have opened up the RemoteRPCUtlity Process QueryProcess = new Process(); QueryProcess.StartInfo.WorkingDirectory = Path.GetFullPath("..\\Binaries\\DotNET"); QueryProcess.StartInfo.FileName = QueryProcess.StartInfo.WorkingDirectory + "\\RPCUtility.exe"; QueryProcess.StartInfo.Arguments = string.Format("{0} {1} sysctl -n hw.ncpu", MachineName, UserDevRootMac); QueryProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedForQuery); QueryProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedForQuery); // Try to launch the query's process, and produce a friendly error message if it fails. Utils.RunLocalProcess(QueryProcess); return(QueryResult); }
protected IOSProvisioningData(IOSProjectSettings ProjectSettings, bool bIsTVOS, bool bForDistribtion) { SigningCertificate = ProjectSettings.SigningCertificate; 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) || // no provision specified !File.Exists((BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac ? (Environment.GetEnvironmentVariable("HOME") + "/Library/MobileDevice/Provisioning Profiles/") : (Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/Apple Computer/MobileDevice/Provisioning Profiles/")) + MobileProvision) || // file doesn't exist !bHaveCertificate) // certificate doesn't exist { SigningCertificate = ""; MobileProvision = ""; 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); Log.TraceLog("Provision found for " + ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game") + ", Provision: " + MobileProvision + " Certificate: " + SigningCertificate); } // add to the dictionary SigningCertificate = SigningCertificate.Replace("\"", ""); // read the provision to get the UUID string filename = (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac ? (Environment.GetEnvironmentVariable("HOME") + "/Library/MobileDevice/Provisioning Profiles/") : (Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/Apple Computer/MobileDevice/Provisioning Profiles/")) + MobileProvision; if (File.Exists(filename)) { string AllText = File.ReadAllText(filename); 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); } } } else { Log.TraceLog("No matching provision file was discovered. Please ensure you have a compatible provision installed."); } }
static public Hashtable SSHCommand(string WorkingDirectory, string Command, string RemoteOutputPath) { Console.WriteLine("Doing {0}", Command); // make the commandline for other end string RemoteCommandline = "cd \"" + WorkingDirectory + "\""; if (!string.IsNullOrWhiteSpace(RemoteOutputPath)) { RemoteCommandline += " && mkdir -p \"" + Path.GetDirectoryName(RemoteOutputPath).Replace("\\", "/") + "\""; } // get the executable dir for SSH string ExeDir = Path.GetDirectoryName(ResolvedSSHExe); Process SSHProcess = new Process(); if (ExeDir != "") { SSHProcess.StartInfo.WorkingDirectory = ExeDir; } // long commands go as a file if (Command.Length > 1024) { // upload the commandline text file string CommandLineFile = Path.GetTempFileName(); File.WriteAllText(CommandLineFile, Command); string RemoteCommandlineDir = "/var/tmp/" + Environment.MachineName; string RemoteCommandlinePath = RemoteCommandlineDir + "/" + Path.GetFileName(CommandLineFile); DateTime Now = DateTime.Now; UploadFile(CommandLineFile, RemoteCommandlinePath); Console.WriteLine("Upload took {0}", (DateTime.Now - Now).ToString()); // execute the file, not a commandline RemoteCommandline += string.Format(" && bash < {0} && rm {0}", RemoteCommandlinePath); } else { RemoteCommandline += " && " + Command; } SSHProcess.StartInfo.FileName = ResolvedSSHExe; SSHProcess.StartInfo.Arguments = string.Format( "-o BatchMode=yes {0} {1}@{2} \"{3}\"", // "-o CheckHostIP=no {0} {1}@{2} \"{3}\"", ResolvedSSHAuthentication, RSyncUsername, RemoteServerName, RemoteCommandline.Replace("\"", "\\\"")); Hashtable Return = new Hashtable(); // add this process to the map DictionaryLock.WaitOne(); SSHOutputMap[SSHProcess] = new StringBuilder(""); DictionaryLock.ReleaseMutex(); SSHProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedForSSH); SSHProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedForSSH); DateTime Start = DateTime.Now; Int64 ExitCode = Utils.RunLocalProcess(SSHProcess); Console.WriteLine("Execute took {0}", (DateTime.Now - Start).ToString()); // now we have enough to fill out the HashTable DictionaryLock.WaitOne(); Return["CommandOutput"] = SSHOutputMap[SSHProcess].ToString(); Return["ExitCode"] = (object)ExitCode; SSHOutputMap.Remove(SSHProcess); DictionaryLock.ReleaseMutex(); return(Return); }
public override void PreBuildSync() { // no need to sync on the Mac! if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac) { return; } if (bUseRPCUtil) { string ExtString = ""; // look only for useful extensions foreach (string Ext in RsyncExtensions) { // for later ls ExtString += Ext.StartsWith(".") ? ("*" + Ext) : Ext; ExtString += " "; } List <string> BatchUploadCommands = new List <string>(); // for each directory we visited, add all the files in that directory foreach (string Dir in RsyncDirs) { List <string> LocalFilenames = new List <string>(); if (!Directory.Exists(Dir)) { Directory.CreateDirectory(Dir); } // look only for useful extensions foreach (string Ext in RsyncExtensions) { string[] Files = Directory.GetFiles(Dir, "*" + Ext); foreach (string SyncFile in Files) { // remember all local files LocalFilenames.Add(Path.GetFileName(SyncFile)); string RemoteFilePath = ConvertPath(SyncFile); // an upload command is local name and remote name BatchUploadCommands.Add(SyncFile + ";" + RemoteFilePath); } } } // batch upload RPCUtilHelper.BatchUpload(BatchUploadCommands.ToArray()); } else { List <string> RelativeRsyncDirs = new List <string>(); foreach (string Dir in RsyncDirs) { RelativeRsyncDirs.Add(Utils.CleanDirectorySeparators(Dir.Replace(":", ""), '/') + "/"); } // write out directories to copy string RSyncPathsFile = Path.GetTempFileName(); string IncludeFromFile = Path.GetTempFileName(); File.WriteAllLines(RSyncPathsFile, RelativeRsyncDirs.ToArray()); File.WriteAllLines(IncludeFromFile, RsyncExtensions); // source and destination paths in the format rsync wants string CygRootPath = "/cygdrive"; // ConvertPathToCygwin(Path.GetFullPath("")); string RemotePath = string.Format("{0}{1}", UserDevRootMac, Environment.MachineName); // get the executable dir for SSH, so Rsync can call it easily string ExeDir = Path.GetDirectoryName(ResolvedSSHExe); Process RsyncProcess = new Process(); if (ExeDir != "") { RsyncProcess.StartInfo.WorkingDirectory = ExeDir; } // --exclude='*' ??? why??? RsyncProcess.StartInfo.FileName = ResolvedRSyncExe; RsyncProcess.StartInfo.Arguments = string.Format( "-vzae \"{0}\" --rsync-path=\"mkdir -p {2} && rsync\" --chmod=ug=rwX,o=rxX --delete --files-from=\"{4}\" --include-from=\"{5}\" --include='*/' --exclude='*.o' --exclude='Timestamp' '{1}' {6}@{3}:'{2}'", ResolvedRsyncAuthentication, CygRootPath, RemotePath, RemoteServerName, ConvertPathToCygwin(RSyncPathsFile), ConvertPathToCygwin(IncludeFromFile), RSyncUsername); Console.WriteLine("Command: " + RsyncProcess.StartInfo.Arguments); RsyncProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedForRsync); RsyncProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedForRsync); // run rsync Utils.RunLocalProcess(RsyncProcess); File.Delete(IncludeFromFile); File.Delete(RSyncPathsFile); } // we can now clear out the set of files RsyncDirs.Clear(); RsyncExtensions.Clear(); }
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."); } } }
public override void SetUpProjectEnvironment(UnrealTargetConfiguration Configuration, TargetInfo Target = null) { if (!bInitializedProject) { base.SetUpProjectEnvironment(Configuration, Target); // update the configuration based on the project file // look in ini settings for what platforms to compile for ConfigCacheIni Ini = ConfigCacheIni.CreateConfigCacheIni(Platform, "Engine", DirectoryReference.FromFile(ProjectFile)); string MinVersion = "IOS_8"; if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "MinimumiOSVersion", out MinVersion)) { switch (MinVersion) { case "IOS_61": Log.TraceWarning("IOS 6 is no longer supported in UE4 as 4.11"); RunTimeIOSVersion = "8.0"; break; case "IOS_7": Log.TraceWarning("IOS 7 is no longer supported in UE4 as 4.14"); RunTimeIOSVersion = "8.0"; break; case "IOS_8": RunTimeIOSVersion = "8.0"; break; case "IOS_9": RunTimeIOSVersion = "9.0"; break; case "IOS_10": RunTimeIOSVersion = "10.0"; break; } } bool biPhoneAllowed = true; bool biPadAllowed = true; Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsIPhone", out biPhoneAllowed); Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsIPad", out biPadAllowed); if (biPhoneAllowed && biPadAllowed) { RunTimeIOSDevices = "1,2"; } else if (biPadAllowed) { RunTimeIOSDevices = "2"; } else if (biPhoneAllowed) { RunTimeIOSDevices = "1"; } ProjectArches = new List <string>(); bool bBuild = true; if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bDevForArmV7", out bBuild) && bBuild) { ProjectArches.Add("armv7"); } if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bDevForArm64", out bBuild) && bBuild) { ProjectArches.Add("arm64"); } if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bDevForArmV7S", out bBuild) && bBuild) { ProjectArches.Add("armv7s"); } // force armv7 if something went wrong if (ProjectArches.Count == 0) { ProjectArches.Add("armv7"); } NonShippingArchitectures = ProjectArches[0]; for (int Index = 1; Index < ProjectArches.Count; ++Index) { NonShippingArchitectures += "," + ProjectArches[Index]; } ProjectArches.Clear(); if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bShipForArmV7", out bBuild) && bBuild) { ProjectArches.Add("armv7"); } if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bShipForArm64", out bBuild) && bBuild) { ProjectArches.Add("arm64"); } if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bShipForArmV7S", out bBuild) && bBuild) { ProjectArches.Add("armv7s"); } // force armv7 if something went wrong if (ProjectArches.Count == 0) { ProjectArches.Add("armv7"); ProjectArches.Add("arm64"); } ShippingArchitectures = ProjectArches[0]; for (int Index = 1; Index < ProjectArches.Count; ++Index) { ShippingArchitectures += "," + ProjectArches[Index]; } // determine if we need to generate the dsym Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGeneratedSYMFile", out BuildConfiguration.bGeneratedSYMFile); Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGeneratedSYMBundle", out BuildConfiguration.bGeneratedSYMBundle); // determie if bitcode should be generated for the shipping code Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bShipForBitcode", out bShipForBitcode); // @todo tvos: We probably want to handle TVOS versions here Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "AdditionalLinkerFlags", out AdditionalLinkerFlags); Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "AdditionalShippingLinkerFlags", out AdditionalShippingLinkerFlags); Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "MobileProvision", out MobileProvision); Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "SigningCertificate", out SigningCertificate); // bundle identifier Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier); bInitializedProject = true; } ProvisionData Data = new ProvisionData(); string BundleId = BundleIdentifier.Replace("[PROJECT_NAME]", ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game")).Replace("_", ""); bool bIsTVOS = GetCodesignPlatformName() == "appletvos"; if (!ProvisionCache.ContainsKey(BundleId + " " + bIsTVOS.ToString() + " " + bForDistribtion.ToString())) { Certificate = SigningCertificate; Provision = MobileProvision; 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 " + BundleId + (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 " + BundleId + (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 { Certificate = bForDistribtion ? "iPhone Distribution" : "iPhone Developer"; bHaveCertificate = true; } if (string.IsNullOrEmpty(MobileProvision) || // no provision specified !File.Exists((BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac ? (Environment.GetEnvironmentVariable("HOME") + "/Library/MobileDevice/Provisioning Profiles/") : (Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/Apple Computer/MobileDevice/Provisioning Profiles/")) + MobileProvision) || // file doesn't exist !bHaveCertificate) // certificate doesn't exist { Certificate = ""; Provision = ""; 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 " + BundleId + (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 " + BundleId + (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); Log.TraceLog("Provision found for " + ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game") + ", Provision: " + Provision + " Certificate: " + Certificate); } // add to the dictionary Data.MobileProvision = Provision; Data.Certificate = Certificate.Replace("\"", ""); // read the provision to get the UUID string filename = (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac ? (Environment.GetEnvironmentVariable("HOME") + "/Library/MobileDevice/Provisioning Profiles/") : (Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/Apple Computer/MobileDevice/Provisioning Profiles/")) + Data.MobileProvision; if (File.Exists(filename)) { string AllText = File.ReadAllText(filename); int idx = AllText.IndexOf("<key>UUID</key>"); if (idx > 0) { idx = AllText.IndexOf("<string>", idx); if (idx > 0) { idx += "<string>".Length; Data.UUID = 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; Data.TeamUUID = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx); } } } else { Log.TraceLog("No matching provision file was discovered. Please ensure you have a compatible provision installed."); } ProvisionCache.Add(BundleId + " " + bIsTVOS.ToString() + " " + bForDistribtion.ToString(), Data); } else { Data = ProvisionCache[BundleId + " " + bIsTVOS.ToString() + " " + bForDistribtion.ToString()]; } MobileProvision = Data.MobileProvision; SigningCertificate = Data.Certificate; MobileProvisionUUID = Data.UUID; TeamUUID = Data.TeamUUID; }
public override bool ExecuteActions(List <Action> Actions, bool bLogDetailedActionStats) { if (Actions.Count == 0) { return(true); } // Clean the intermediate directory in case there are any leftovers from previous builds if (DirectoryReference.Exists(IntermediateDir)) { DirectoryReference.Delete(IntermediateDir, true); } DirectoryReference.CreateDirectory(IntermediateDir); if (!DirectoryReference.Exists(IntermediateDir)) { throw new BuildException($"Failed to create directory \"{IntermediateDir}\"."); } // Build the json script file to describe all the actions and their dependencies var ActionIds = Actions.ToDictionary(a => a, a => Guid.NewGuid().ToString()); File.WriteAllText(ScriptFile.FullName, Json.Serialize(new Dictionary <string, object>() { ["jobs"] = Actions.ToDictionary(a => ActionIds[a], a => { var Job = new Dictionary <string, object>() { ["title"] = a.StatusDescription, ["command"] = $"\"{a.CommandPath}\" {a.CommandArguments}", ["working_directory"] = a.WorkingDirectory.FullName, ["dependencies"] = a.PrerequisiteActions.Select(p => ActionIds[p]).ToArray(), ["run_locally"] = !(a.bCanExecuteRemotely && a.bCanExecuteRemotelyWithSNDBS) }; if (a.PrerequisiteItems.Count > 0) { Job["explicit_input_files"] = a.PrerequisiteItems.Select(i => new Dictionary <string, object>() { ["filename"] = i.AbsolutePath }).ToList(); } if (EnableEcho) { var EchoString = string.Join(" ", string.IsNullOrWhiteSpace(a.CommandDescription) ? string.Empty : $"[{a.CommandDescription}]", a.StatusDescription); if (!string.IsNullOrWhiteSpace(EchoString)) { Job["echo"] = EchoString; } } return(Job); }) })); PrepareToolTemplates(); bool bHasRewrites = GenerateSNDBSIncludeRewriteRules(); var LocalProcess = new Process(); LocalProcess.StartInfo = new ProcessStartInfo(SNDBSExecutable, $"-q -p \"Unreal Engine Tasks\" -s \"{ScriptFile}\" -templates \"{IntermediateDir}\"{(bHasRewrites ? $" --include-rewrite-rules \"{IncludeRewriteRulesFile}\"" : "")}"); LocalProcess.OutputDataReceived += (Sender, Args) => Log.TraceInformation("{0}", Args.Data); LocalProcess.ErrorDataReceived += (Sender, Args) => Log.TraceInformation("{0}", Args.Data); return(Utils.RunLocalProcess(LocalProcess) == 0); }