/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> /// <returns>True if the task succeeded</returns> public override bool Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { bool bSuccess = false; UEBuildPlatform Platform = UEBuildPlatform.GetBuildPlatform(Parameters.Platform); UEToolChain ToolChain = Platform.CreateContext(null, null).CreateToolChainForDefaultCppPlatform(); // Find the matching files List <FileReference> Files = ResolveFilespec(CommandUtils.RootDirectory, Parameters.Files, TagNameToFileSet).ToList(); // Get the symbol store directory DirectoryReference StoreDir = ResolveDirectory(Parameters.StoreDir); // Take the lock before accessing the symbol server LockFile.TakeLock(StoreDir, TimeSpan.FromMinutes(15), () => { bSuccess = ToolChain.PublishSymbols(StoreDir, Files, Parameters.Product); }); if (!bSuccess) { CommandUtils.LogError("Failure publishing symbol files."); } return(bSuccess); }
/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> /// <returns>True if the task succeeded</returns> public override bool Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { // Get the list of symbol file name patterns from the platform. UEBuildPlatform Platform = UEBuildPlatform.GetBuildPlatform(Parameters.Platform); UEToolChain ToolChain = Platform.CreateContext(null).CreateToolChainForDefaultCppPlatform(); var DirectoryStructure = ToolChain.SymbolServerDirectoryStructure; if (DirectoryStructure == null) { CommandUtils.LogError("Platform does not specify the symbol server structure. Cannot age the symbol server."); return(false); } string Filter = string.IsNullOrWhiteSpace(Parameters.Filter) ? string.Empty : Parameters.Filter.Trim(); // Get the time at which to expire files DateTime ExpireTimeUtc = DateTime.UtcNow - TimeSpan.FromDays(Parameters.Days); CommandUtils.Log("Expiring all files before {0}...", ExpireTimeUtc); // Scan the store directory and delete old symbol files DirectoryReference SymbolServerDirectory = ResolveDirectory(Parameters.StoreDir); LockFile.TakeLock(SymbolServerDirectory, TimeSpan.FromMinutes(15), () => { RecurseDirectory(ExpireTimeUtc, new DirectoryInfo(SymbolServerDirectory.FullName), DirectoryStructure, 0, Filter); }); return(true); }
/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> /// <returns>True if the task succeeded</returns> public override bool Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { // Get the base directory DirectoryReference BaseDir = ResolveDirectory(Parameters.BaseDir); // Get the output directory DirectoryReference OutputDir = ResolveDirectory(Parameters.OutputDir); // Make sure the source and destination directories don't overlap. We can't strip in-place at the moment. if (BaseDir == OutputDir) { CommandUtils.LogError("Output directory for stripped files is the same as source directory ({0})", BaseDir.FullName); return(false); } // Find the matching files FileReference[] SourceFiles = ResolveFilespec(BaseDir, Parameters.Files, TagNameToFileSet).OrderBy(x => x.FullName).ToArray(); // Create the matching target files FileReference[] TargetFiles = SourceFiles.Select(x => FileReference.Combine(OutputDir, x.MakeRelativeTo(BaseDir))).ToArray(); // Run the stripping command UEBuildPlatform Platform = UEBuildPlatform.GetBuildPlatform(Parameters.Platform); UEToolChain ToolChain = Platform.CreateContext(null, null).CreateToolChainForDefaultCppPlatform(); for (int Idx = 0; Idx < SourceFiles.Length; Idx++) { TargetFiles[Idx].Directory.CreateDirectory(); CommandUtils.Log("Stripping symbols: {0} -> {1}", SourceFiles[Idx].FullName, TargetFiles[Idx].FullName); ToolChain.StripSymbols(SourceFiles[Idx].FullName, TargetFiles[Idx].FullName); } // Apply the optional tag to the build products foreach (string TagName in FindTagNamesFromList(Parameters.Tag)) { FindOrAddTagSet(TagNameToFileSet, TagName).UnionWith(TargetFiles); } // Add the target files to the set of build products BuildProducts.UnionWith(TargetFiles); return(true); }
public override bool PrepTargetForDeployment(UEBuildTarget InTarget) { string GameName = InTarget.TargetName; string BuildPath = (GameName == "UE4Game" ? "../../Engine" : InTarget.ProjectDirectory) + "/Binaries/IOS"; string ProjectDirectory = InTarget.ProjectDirectory; bool bIsUE4Game = GameName.Contains("UE4Game"); string DecoratedGameName; if (InTarget.Configuration == UnrealTargetConfiguration.Development) { DecoratedGameName = GameName; } else { DecoratedGameName = String.Format("{0}-{1}-{2}", GameName, InTarget.Platform.ToString(), InTarget.Configuration.ToString()); } if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac && Environment.GetEnvironmentVariable("UBT_NO_POST_DEPLOY") != "true") { return(PrepForUATPackageOrDeploy(GameName, ProjectDirectory, BuildPath + "/" + DecoratedGameName, "../../Engine", false, "", false)); } else { // If it is requested, send the app bundle back to the platform executing these commands. if (BuildConfiguration.bCopyAppBundleBackToDevice) { Log.TraceInformation("Copying binaries back to this device..."); IOSToolChain Toolchain = UEToolChain.GetPlatformToolChain(CPPTargetPlatform.IOS) as IOSToolChain; try { string BinaryDir = Path.GetDirectoryName(InTarget.OutputPath) + "\\"; if (BinaryDir.EndsWith(InTarget.AppName + "\\Binaries\\IOS\\") && InTarget.TargetType != TargetRules.TargetType.Game) { BinaryDir = BinaryDir.Replace(InTarget.TargetType.ToString(), "Game"); } // Get the app bundle's name string AppFullName = InTarget.AppName; if (InTarget.Configuration != UnrealTargetConfiguration.Development) { AppFullName += "-" + InTarget.Platform.ToString(); AppFullName += "-" + InTarget.Configuration.ToString(); } foreach (string BinaryPath in Toolchain.BuiltBinaries) { if (!BinaryPath.Contains("Dummy")) { RPCUtilHelper.CopyFile(Toolchain.ConvertPath(BinaryPath), BinaryPath, false); } } Log.TraceInformation("Copied binaries successfully."); } catch (Exception) { Log.TraceInformation("Copying binaries back to this device failed."); } } GeneratePList(ProjectDirectory, bIsUE4Game, GameName, Path.GetFileNameWithoutExtension(UnrealBuildTool.GetUProjectFile()), "../../Engine", ""); } return(true); }
public override bool PrepTargetForDeployment(UEBuildTarget InTarget) { Log.TraceInformation("Deploying now!"); string IntermediateDirectory = InTarget.AppName + "/Intermediate/Build/Mac/" + InTarget.AppName + "/" + InTarget.Configuration; if (!Directory.Exists("../../" + IntermediateDirectory)) { IntermediateDirectory = "Engine/Intermediate/Build/Mac/" + InTarget.AppName + "/" + InTarget.Configuration; } MacToolChain Toolchain = UEToolChain.GetPlatformToolChain(CPPTargetPlatform.Mac) as MacToolChain; string FixDylibDepsScript = Path.Combine(IntermediateDirectory, "FixDylibDependencies.sh"); string FinalizeAppBundleScript = Path.Combine(IntermediateDirectory, "FinalizeAppBundle.sh"); string RemoteWorkingDir = ""; bool bIsStaticLibrary = InTarget.OutputPath.EndsWith(".a"); if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { if (!bIsStaticLibrary) { // Copy the command scripts to the intermediate on the target Mac. string RemoteFixDylibDepsScript = Toolchain.ConvertPath(Path.GetFullPath(FixDylibDepsScript)); RemoteFixDylibDepsScript = RemoteFixDylibDepsScript.Replace("../../../../", "../../"); RPCUtilHelper.CopyFile("../../" + FixDylibDepsScript, RemoteFixDylibDepsScript, true); if (!InTarget.GlobalLinkEnvironment.Config.bIsBuildingConsoleApplication) { string RemoteFinalizeAppBundleScript = Toolchain.ConvertPath(Path.GetFullPath(FinalizeAppBundleScript)); RemoteFinalizeAppBundleScript = RemoteFinalizeAppBundleScript.Replace("../../../../", "../../"); RPCUtilHelper.CopyFile("../../" + FinalizeAppBundleScript, RemoteFinalizeAppBundleScript, true); } // run it remotely RemoteWorkingDir = Toolchain.ConvertPath(Path.GetDirectoryName(Path.GetFullPath(FixDylibDepsScript))); Log.TraceInformation("Running FixDylibDependencies.sh..."); Hashtable Results = RPCUtilHelper.Command(RemoteWorkingDir, "/bin/sh", "FixDylibDependencies.sh", null); if (Results != null) { string Result = (string)Results["CommandOutput"]; if (Result != null) { Log.TraceInformation(Result); } } if (!InTarget.GlobalLinkEnvironment.Config.bIsBuildingConsoleApplication) { Log.TraceInformation("Running FinalizeAppBundle.sh..."); Results = RPCUtilHelper.Command(RemoteWorkingDir, "/bin/sh", "FinalizeAppBundle.sh", null); if (Results != null) { string Result = (string)Results["CommandOutput"]; if (Result != null) { Log.TraceInformation(Result); } } } } // If it is requested, send the app bundle back to the platform executing these commands. if (BuildConfiguration.bCopyAppBundleBackToDevice) { Log.TraceInformation("Copying binaries back to this device..."); try { string BinaryDir = Path.GetDirectoryName(InTarget.OutputPath) + "\\"; if (BinaryDir.EndsWith(InTarget.AppName + "\\Binaries\\Mac\\") && InTarget.TargetType != TargetRules.TargetType.Game) { BinaryDir = BinaryDir.Replace(InTarget.TargetType.ToString(), "Game"); } string RemoteBinariesDir = Toolchain.ConvertPath(BinaryDir); string LocalBinariesDir = BinaryDir; // Get the app bundle's name string AppFullName = InTarget.AppName; if (InTarget.Configuration != UnrealTargetConfiguration.Development) { AppFullName += "-" + InTarget.Platform.ToString(); AppFullName += "-" + InTarget.Configuration.ToString(); } if (!InTarget.GlobalLinkEnvironment.Config.bIsBuildingConsoleApplication) { AppFullName += ".app"; } List <string> NotBundledBinaries = new List <string>(); foreach (string BinaryPath in Toolchain.BuiltBinaries) { if (InTarget.GlobalLinkEnvironment.Config.bIsBuildingConsoleApplication || bIsStaticLibrary || !BinaryPath.StartsWith(LocalBinariesDir + AppFullName)) { NotBundledBinaries.Add(BinaryPath); } } // Zip the app bundle for transferring. if (!InTarget.GlobalLinkEnvironment.Config.bIsBuildingConsoleApplication && !bIsStaticLibrary) { string ZipCommand = "zip -0 -r -y -T \"" + AppFullName + ".zip\" \"" + AppFullName + "\""; RPCUtilHelper.Command(RemoteBinariesDir, ZipCommand, "", null); // Copy the AppBundle back to the source machine string LocalZipFileLocation = LocalBinariesDir + AppFullName + ".zip "; string RemoteZipFileLocation = RemoteBinariesDir + AppFullName + ".zip"; RPCUtilHelper.CopyFile(RemoteZipFileLocation, LocalZipFileLocation, false); // Extract the copied app bundle (in zip format) to the local binaries directory using (ZipFile AppBundleZip = ZipFile.Read(LocalZipFileLocation)) { foreach (ZipEntry Entry in AppBundleZip) { Entry.Extract(LocalBinariesDir, ExtractExistingFileAction.OverwriteSilently); } } // Delete the zip as we no longer need/want it. File.Delete(LocalZipFileLocation); RPCUtilHelper.Command(RemoteBinariesDir, "rm -f \"" + AppFullName + ".zip\"", "", null); } if (NotBundledBinaries.Count > 0) { foreach (string BinaryPath in NotBundledBinaries) { RPCUtilHelper.CopyFile(Toolchain.ConvertPath(BinaryPath), BinaryPath, false); } } Log.TraceInformation("Copied binaries successfully."); } catch (Exception) { Log.TraceInformation("Copying binaries back to this device failed."); } } } return(true); }
public override bool PrepTargetForDeployment(UEBuildTarget InTarget) { string GameName = InTarget.AppName; string BuildPath = InTarget.ProjectDirectory + "/Binaries/IOS"; string ProjectDirectory = InTarget.ProjectDirectory; if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac && Environment.GetEnvironmentVariable("UBT_NO_POST_DEPLOY") != "true") { string DecoratedGameName; if (InTarget.Configuration == UnrealTargetConfiguration.Development) { DecoratedGameName = GameName; } else { DecoratedGameName = String.Format("{0}-{1}-{2}", GameName, InTarget.Platform.ToString(), InTarget.Configuration.ToString()); } return PrepForUATPackageOrDeploy(GameName, ProjectDirectory, BuildPath + "/" + DecoratedGameName, "../../Engine", false, ""); } else { // If it is requested, send the app bundle back to the platform executing these commands. if (BuildConfiguration.bCopyAppBundleBackToDevice) { Log.TraceInformation("Copying binaries back to this device..."); IOSToolChain Toolchain = UEToolChain.GetPlatformToolChain(CPPTargetPlatform.IOS) as IOSToolChain; try { string BinaryDir = Path.GetDirectoryName(InTarget.OutputPath) + "\\"; if (BinaryDir.EndsWith(InTarget.AppName + "\\Binaries\\IOS\\") && InTarget.TargetType != TargetRules.TargetType.Game) { BinaryDir = BinaryDir.Replace(InTarget.TargetType.ToString(), "Game"); } // Get the app bundle's name string AppFullName = InTarget.AppName; if (InTarget.Configuration != UnrealTargetConfiguration.Development) { AppFullName += "-" + InTarget.Platform.ToString(); AppFullName += "-" + InTarget.Configuration.ToString(); } foreach (string BinaryPath in Toolchain.BuiltBinaries) { if (!BinaryPath.Contains("Dummy")) { RPCUtilHelper.CopyFile(Toolchain.ConvertPath(BinaryPath), BinaryPath, false); } } Log.TraceInformation("Copied binaries successfully."); } catch (Exception) { Log.TraceInformation("Copying binaries back to this device failed."); } } // install the provision /* string ProvisionWithPrefix = "../../Engine/Build/IOS/UE4Game.mobileprovision"; if (File.Exists(BuildPath + "/" + GameName + ".mobileprovision")) { ProvisionWithPrefix = BuildPath + "/" + GameName + ".mobileprovision"; } else { if (File.Exists(BuildPath + "/NotForLicensees/" + GameName + ".mobileprovision")) { ProvisionWithPrefix = BuildPath + "/NotForLicensees/" + GameName + ".mobileprovision"; } else if (!File.Exists(ProvisionWithPrefix)) { ProvisionWithPrefix = "../../Engine/Build/IOS/NotForLicensees/UE4Game.mobileprovision"; } } string LibraryDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/Apple Computer/MobileDevice/Provisioning Profiles/"; if (File.Exists(ProvisionWithPrefix)) { Directory.CreateDirectory(LibraryDir); File.Copy(ProvisionWithPrefix, LibraryDir + GameName + ".mobileprovision", true); FileInfo DestFileInfo = new FileInfo(LibraryDir + GameName + ".mobileprovision"); DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly; } // install the distribution provision ProvisionWithPrefix = "../../Engine/Build/IOS/UE4Game_Distro.mobileprovision"; if (File.Exists(BuildPath + "/" + GameName + "_Distro.mobileprovision")) { ProvisionWithPrefix = BuildPath + "/" + GameName + "_Distro.mobileprovision"; } else { if (File.Exists(BuildPath + "/NotForLicensees/" + GameName + "_Distro.mobileprovision")) { ProvisionWithPrefix = BuildPath + "/NotForLicensees/" + GameName + "_Distro.mobileprovision"; } else if (!File.Exists(ProvisionWithPrefix)) { ProvisionWithPrefix = "../../Engine/Build/IOS/NotForLicensees/UE4Game_Distro.mobileprovision"; } } if (File.Exists(ProvisionWithPrefix)) { File.Copy(ProvisionWithPrefix, LibraryDir + GameName + "_Distro.mobileprovision", true); FileInfo DestFileInfo = new FileInfo(LibraryDir + GameName + "_Distro.mobileprovision"); DestFileInfo.Attributes = DestFileInfo.Attributes & ~FileAttributes.ReadOnly; }*/ } return true; }
public override void ExecuteBuild() { // Parse the target list string[] Targets = ParseParamValues("Target"); if (Targets.Length == 0) { throw new AutomationException("No targets specified (eg. -Target=\"UE4Editor Win64 Development\")"); } // Parse the archive path string ArchivePath = ParseParamValue("Archive"); if (ArchivePath != null && (!ArchivePath.StartsWith("//") || ArchivePath.Sum(x => (x == '/')? 1 : 0) < 4)) { throw new AutomationException("Archive path is not a valid depot filename"); } // Prepare the build agenda UE4Build.BuildAgenda Agenda = new UE4Build.BuildAgenda(); foreach (string Target in Targets) { string[] Tokens = Target.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); UnrealTargetPlatform Platform; UnrealTargetConfiguration Configuration; if (Tokens.Length < 3 || !Enum.TryParse(Tokens[1], true, out Platform) || !Enum.TryParse(Tokens[2], true, out Configuration)) { throw new AutomationException("Invalid target '{0}' - expected <TargetName> <Platform> <Configuration>"); } Agenda.AddTarget(Tokens[0], Platform, Configuration, InAddArgs: String.Join(" ", Tokens.Skip(3))); } // Build everything UE4Build Builder = new UE4Build(this); Builder.Build(Agenda, InUpdateVersionFiles: ArchivePath != null); // Include the build products for UAT and UBT if required if (ParseParam("WithUAT")) { Builder.AddUATFilesToBuildProducts(); } if (ParseParam("WithUBT")) { Builder.AddUBTFilesToBuildProducts(); } // Archive the build products if (ArchivePath != null) { // Create an output folder string OutputFolder = Path.Combine(CommandUtils.CmdEnv.LocalRoot, "ArchiveForUGS"); Directory.CreateDirectory(OutputFolder); // Create a temp folder for storing stripped PDB files string SymbolsFolder = Path.Combine(OutputFolder, "Symbols"); Directory.CreateDirectory(SymbolsFolder); // Get the Windows toolchain UEToolChain WindowsToolChain = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.Win64).CreateContext(null).CreateToolChain(CPPTargetPlatform.Win64); // Figure out all the files for the archive Ionic.Zip.ZipFile Zip = new Ionic.Zip.ZipFile(); Zip.UseZip64WhenSaving = Ionic.Zip.Zip64Option.Always; foreach (string BuildProduct in Builder.BuildProductFiles) { if (!File.Exists(BuildProduct)) { throw new AutomationException("Missing build product: {0}", BuildProduct); } if (BuildProduct.EndsWith(".pdb", StringComparison.InvariantCultureIgnoreCase)) { string StrippedFileName = CommandUtils.MakeRerootedFilePath(BuildProduct, CommandUtils.CmdEnv.LocalRoot, SymbolsFolder); Directory.CreateDirectory(Path.GetDirectoryName(StrippedFileName)); WindowsToolChain.StripSymbols(BuildProduct, StrippedFileName); Zip.AddFile(StrippedFileName, Path.GetDirectoryName(CommandUtils.StripBaseDirectory(StrippedFileName, SymbolsFolder))); } else { Zip.AddFile(BuildProduct, Path.GetDirectoryName(CommandUtils.StripBaseDirectory(BuildProduct, CommandUtils.CmdEnv.LocalRoot))); } } // Create the zip file string ZipFileName = Path.Combine(OutputFolder, "Archive.zip"); Console.WriteLine("Writing {0}...", ZipFileName); Zip.Save(ZipFileName); // Submit it to Perforce if required if (CommandUtils.AllowSubmit) { // Delete any existing clientspec for submitting string ClientName = Environment.MachineName + "_BuildForUGS"; // Create a brand new one P4ClientInfo Client = new P4ClientInfo(); Client.Owner = CommandUtils.P4Env.User; Client.Host = Environment.MachineName; Client.Stream = ArchivePath.Substring(0, ArchivePath.IndexOf('/', ArchivePath.IndexOf('/', 2) + 1)); Client.RootPath = Path.Combine(OutputFolder, "Perforce"); Client.Name = ClientName; Client.Options = P4ClientOption.NoAllWrite | P4ClientOption.NoClobber | P4ClientOption.NoCompress | P4ClientOption.Unlocked | P4ClientOption.NoModTime | P4ClientOption.RmDir; Client.LineEnd = P4LineEnd.Local; P4.CreateClient(Client, AllowSpew: false); // Create a new P4 connection for this workspace P4Connection SubmitP4 = new P4Connection(Client.Owner, Client.Name, P4Env.P4Port); SubmitP4.Revert("-k //..."); // Figure out where the zip file has to go in Perforce P4WhereRecord WhereZipFile = SubmitP4.Where(ArchivePath, false).FirstOrDefault(x => !x.bUnmap && x.Path != null); if (WhereZipFile == null) { throw new AutomationException("Couldn't locate {0} in this workspace"); } // Get the latest version of it int NewCL = SubmitP4.CreateChange(Description: String.Format("[CL {0}] Updated binaries", P4Env.Changelist)); SubmitP4.Sync(String.Format("-k \"{0}\"", ArchivePath), AllowSpew: false); CommandUtils.CopyFile(ZipFileName, WhereZipFile.Path); SubmitP4.Add(NewCL, String.Format("\"{0}\"", ArchivePath)); SubmitP4.Edit(NewCL, String.Format("\"{0}\"", ArchivePath)); // Submit it int SubmittedCL; SubmitP4.Submit(NewCL, out SubmittedCL); if (SubmittedCL <= 0) { throw new AutomationException("Submit failed."); } Console.WriteLine("Submitted in changelist {0}", SubmittedCL); } } }