/// <summary> /// Stage a single file to its default location /// </summary> /// <param name="FileType">The type of file being staged</param> /// <param name="InputFile">Path to the file</param> public void StageFile(StagedFileType FileType, FileReference InputFile) { StagedFileReference OutputFile; if (InputFile.IsUnderDirectory(ProjectRoot)) { OutputFile = StagedFileReference.Combine(RelativeProjectRootForStage, InputFile.MakeRelativeTo(ProjectRoot)); } else if (InputFile.HasExtension(".uplugin")) { if (InputFile.IsUnderDirectory(EngineRoot)) { OutputFile = new StagedFileReference(InputFile.MakeRelativeTo(LocalRoot)); } else { // This is a plugin that lives outside of the Engine/Plugins or Game/Plugins directory so needs to be remapped for staging/packaging // We need to remap C:\SomePath\PluginName\PluginName.uplugin to RemappedPlugins\PluginName\PluginName.uplugin OutputFile = new StagedFileReference(String.Format("RemappedPlugins/{0}/{1}", InputFile.GetFileNameWithoutExtension(), InputFile.GetFileName())); } } else if (InputFile.IsUnderDirectory(LocalRoot)) { OutputFile = new StagedFileReference(InputFile.MakeRelativeTo(LocalRoot)); } else { throw new AutomationException("Can't deploy {0} because it doesn't start with {1} or {2}", InputFile, ProjectRoot, LocalRoot); } StageFile(FileType, InputFile, OutputFile); }
/// <summary> /// Gets the default location to stage an input file /// </summary> /// <param name="InputFile">Location of the file in the file system</param> /// <returns>Staged file location</returns> public StagedFileReference GetStagedFileLocation(FileReference InputFile) { StagedFileReference OutputFile; if (InputFile.IsUnderDirectory(ProjectRoot)) { OutputFile = StagedFileReference.Combine(RelativeProjectRootForStage, InputFile.MakeRelativeTo(ProjectRoot)); } else if (InputFile.HasExtension(".uplugin")) { DirectoryReference EnterpriseRoot = DirectoryReference.Combine(EngineRoot, "..", "Enterprise"); // Enterprise plugins aren't under the project additional plugin directories, so they shouldn't be remapped if (InputFile.IsUnderDirectory(EngineRoot) || InputFile.IsUnderDirectory(EnterpriseRoot)) { OutputFile = new StagedFileReference(InputFile.MakeRelativeTo(LocalRoot)); } else { // This is a plugin that lives outside of the Engine/Plugins or Game/Plugins directory so needs to be remapped for staging/packaging // We need to remap C:\SomePath\PluginName\PluginName.uplugin to RemappedPlugins\PluginName\PluginName.uplugin OutputFile = new StagedFileReference(String.Format("RemappedPlugins/{0}/{1}", InputFile.GetFileNameWithoutExtension(), InputFile.GetFileName())); } } else if (InputFile.IsUnderDirectory(LocalRoot)) { OutputFile = new StagedFileReference(InputFile.MakeRelativeTo(LocalRoot)); } else { throw new AutomationException("Can't deploy {0} because it doesn't start with {1} or {2}", InputFile, ProjectRoot, LocalRoot); } return(OutputFile); }
/// <summary> /// Format an include of the given file /// </summary> /// <param name="FromDirectory">The directory containing the file with the #include directive</param> /// <param name="IncludeFile">File to include</param> /// <param name="IncludePaths">Directories to base relative include paths from</param> /// <param name="SystemIncludePaths">Directories to base system include paths from</param> /// <returns>Formatted include path, with surrounding quotes</returns> public static bool TryFormatInclude(DirectoryReference FromDirectory, FileReference IncludeFile, IEnumerable <DirectoryReference> IncludePaths, IEnumerable <DirectoryReference> SystemIncludePaths, out string IncludeText) { // Generated headers are always included without a path if (IncludeFile.FullName.Contains(".generated.") || IncludeFile.FullName.EndsWith("Classes.h")) { IncludeText = String.Format("\"{0}\"", IncludeFile.GetFileName()); return(true); } // Try to write an include relative to one of the system include paths foreach (DirectoryReference SystemIncludePath in SystemIncludePaths) { if (IncludeFile.IsUnderDirectory(SystemIncludePath)) { IncludeText = String.Format("<{0}>", IncludeFile.MakeRelativeTo(SystemIncludePath).Replace('\\', '/')); return(true); } } // Try to write an include relative to one of the standard include paths foreach (DirectoryReference IncludePath in IncludePaths) { if (IncludeFile.IsUnderDirectory(IncludePath)) { IncludeText = String.Format("\"{0}\"", IncludeFile.MakeRelativeTo(IncludePath).Replace('\\', '/')); return(true); } } // Try to write an include relative to the file if (IncludeFile.IsUnderDirectory(FromDirectory)) { IncludeText = String.Format("\"{0}\"", IncludeFile.MakeRelativeTo(FromDirectory).Replace('\\', '/')); return(true); } // HACK: VsPerf.h is in the compiler environment, but the include path is added directly if (IncludeFile.FullName.EndsWith("\\PerfSDK\\VSPerf.h", StringComparison.InvariantCultureIgnoreCase)) { IncludeText = "\"VSPerf.h\""; return(true); } // HACK: public Paper2D header in classes folder including private Paper2D header if (IncludeFile.FullName.IndexOf("\\Paper2D\\Private\\", StringComparison.InvariantCultureIgnoreCase) != -1) { IncludeText = "\"" + IncludeFile.GetFileName() + "\""; return(true); } if (IncludeFile.FullName.IndexOf("\\OnlineSubsystemUtils\\Private\\", StringComparison.InvariantCultureIgnoreCase) != -1) { IncludeText = "\"" + IncludeFile.GetFileName() + "\""; return(true); } // Otherwise we don't know where it came from IncludeText = null; return(false); }
/// <summary> /// Converts a file into a more readable form for diangostic messages /// </summary> /// <param name="File">Path to the file</param> /// <returns>Readable form of the path</returns> static string GetReadablePathForDiagnostics(FileReference File) { if (File.IsUnderDirectory(CommandUtils.RootDirectory)) { return(File.MakeRelativeTo(CommandUtils.RootDirectory)); } else { return(File.FullName); } }
public override void ExecuteBuild() { // Get the output directory string TargetDirParam = ParseParamValue("TargetDir"); if (TargetDirParam == null) { throw new AutomationException("Missing -TargetDir=... argument to CopyUAT"); } // Construct a dummy UE4Build object to get a list of the UAT and UBT build products UE4Build Build = new UE4Build(this); Build.AddUATFilesToBuildProducts(); if (ParseParam("WithLauncher")) { Build.AddUATLauncherFilesToBuildProducts(); } Build.AddUBTFilesToBuildProducts(); // Get a list of all the input files List <FileReference> SourceFiles = new List <FileReference>(); foreach (string BuildProductFile in Build.BuildProductFiles) { FileReference SourceFile = new FileReference(BuildProductFile); SourceFiles.Add(SourceFile); FileReference SourceSymbolFile = SourceFile.ChangeExtension(".pdb"); if (FileReference.Exists(SourceSymbolFile)) { SourceFiles.Add(SourceSymbolFile); } FileReference DocumentationFile = SourceFile.ChangeExtension(".xml"); if (FileReference.Exists(DocumentationFile)) { SourceFiles.Add(DocumentationFile); } } // Copy all the files over DirectoryReference TargetDir = new DirectoryReference(TargetDirParam); foreach (FileReference SourceFile in SourceFiles) { FileReference TargetFile = FileReference.Combine(TargetDir, SourceFile.MakeRelativeTo(CommandUtils.RootDirectory)); DirectoryReference.CreateDirectory(TargetFile.Directory); CommandUtils.CopyFile(SourceFile.FullName, TargetFile.FullName); } Log("Copied {0} files to {1}", SourceFiles.Count, TargetDir); }
/// <summary> /// Checks whether the given assembly is a publically distributed engine assembly. /// </summary> /// <param name="File">Assembly location</param> /// <returns>True if the assembly is distributed publically</returns> static bool IsPublicAssembly(FileReference File) { DirectoryReference EngineDirectory = CommandUtils.EngineDirectory; if (File.IsUnderDirectory(EngineDirectory)) { string[] PathFragments = File.MakeRelativeTo(EngineDirectory).Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); if (PathFragments.All(x => !x.Equals("NotForLicensees", StringComparison.InvariantCultureIgnoreCase) && !x.Equals("NoRedist", StringComparison.InvariantCultureIgnoreCase))) { return(true); } } return(false); }
/// <summary> /// Find the shortest relative path of the given file from a set of base directories. /// </summary> /// <param name="File">Full path to a file</param> /// <param name="RebaseDirs">Possible base directories</param> /// <returns>The shortest relative path, or null if the file is not under any of them</returns> public static string FindShortestRelativePath(FileReference File, IEnumerable <DirectoryReference> RebaseDirs) { string RelativePath = null; foreach (DirectoryReference RebaseDir in RebaseDirs) { if (File.IsUnderDirectory(RebaseDir)) { string NewRelativePath = File.MakeRelativeTo(RebaseDir); if (RelativePath == null || NewRelativePath.Length < RelativePath.Length) { RelativePath = NewRelativePath; } } } return(RelativePath); }
/// <summary> /// Constructor /// </summary> /// <param name="FileInfo">File to be added</param> /// <param name="RootDir">Root directory to store paths relative to</param> public TempStorageFile(FileInfo FileInfo, DirectoryReference RootDir) { // Check the file exists and is in the right location FileReference File = new FileReference(FileInfo); if (!File.IsUnderDirectory(RootDir)) { throw new AutomationException("Attempt to add file to temp storage manifest that is outside the root directory ({0})", File.FullName); } if (!FileInfo.Exists) { throw new AutomationException("Attempt to add file to temp storage manifest that does not exist ({0})", File.FullName); } RelativePath = File.MakeRelativeTo(RootDir).Replace(Path.DirectorySeparatorChar, '/'); LastWriteTimeUtcTicks = FileInfo.LastWriteTimeUtc.Ticks; Length = FileInfo.Length; }
public int ArchiveFiles(string InPath, string Wildcard = "*", bool bRecursive = true, string[] ExcludeWildcard = null, string NewPath = null) { int FilesAdded = 0; if (CommandUtils.DirectoryExists(InPath)) { var All = CommandUtils.FindFiles(Wildcard, bRecursive, InPath); var Exclude = new HashSet <string>(); if (ExcludeWildcard != null) { foreach (var Excl in ExcludeWildcard) { var Remove = CommandUtils.FindFiles(Excl, bRecursive, InPath); foreach (var File in Remove) { Exclude.Add(CommandUtils.CombinePaths(File)); } } } foreach (var AllFile in All) { var FileToCopy = CommandUtils.CombinePaths(AllFile); if (Exclude.Contains(FileToCopy)) { continue; } if (!bIsCombiningMultiplePlatforms) { FileReference InputFile = new FileReference(FileToCopy); bool OtherPlatform = false; foreach (UnrealTargetPlatform Plat in Enum.GetValues(typeof(UnrealTargetPlatform))) { if (Plat != StageTargetPlatform.PlatformType && Plat != UnrealTargetPlatform.Unknown) { var Search = FileToCopy; if (InputFile.IsUnderDirectory(LocalRoot)) { Search = InputFile.MakeRelativeTo(LocalRoot); } else if (InputFile.IsUnderDirectory(ProjectRoot)) { Search = InputFile.MakeRelativeTo(ProjectRoot); } if (Search.IndexOf(CommandUtils.CombinePaths("/" + Plat.ToString() + "/"), 0, StringComparison.InvariantCultureIgnoreCase) >= 0) { OtherPlatform = true; break; } } } if (OtherPlatform) { continue; } } string Dest; if (!FileToCopy.StartsWith(InPath)) { throw new AutomationException("Can't archive {0}; it was supposed to start with {1}", FileToCopy, InPath); } // If the specified a new directory, first we deal with that, then apply the other things // this is used to collapse the sandbox, among other things if (NewPath != null) { Dest = FileToCopy.Substring(InPath.Length); if (Dest.StartsWith("/") || Dest.StartsWith("\\")) { Dest = Dest.Substring(1); } Dest = CommandUtils.CombinePaths(NewPath, Dest); } else { Dest = FileToCopy.Substring(InPath.Length); } if (Dest.StartsWith("/") || Dest.StartsWith("\\")) { Dest = Dest.Substring(1); } if (ArchivedFiles.ContainsKey(FileToCopy)) { if (ArchivedFiles[FileToCopy] != Dest) { throw new AutomationException("Can't archive {0}: it was already in the files to archive with a different destination '{1}'", FileToCopy, Dest); } } else { ArchivedFiles.Add(FileToCopy, Dest); } FilesAdded++; } } return(FilesAdded); }
/// <summary> /// Entry point for the commandlet /// </summary> public override void ExecuteBuild() { string OutputDir = ParseParamValue("OutputDir"); string ContentOnlyPlatformsString = ParseParamValue("ContentOnlyPlatforms"); IEnumerable <UnrealTargetPlatform> ContentOnlyPlatforms = Enumerable.Empty <UnrealTargetPlatform>(); if (!String.IsNullOrWhiteSpace(ContentOnlyPlatformsString)) { ContentOnlyPlatforms = ContentOnlyPlatformsString.Split(';').Where(x => !String.IsNullOrWhiteSpace(x)).Select(x => UnrealTargetPlatform.Parse(x)); } string AnalyticsTypeOverride = ParseParamValue("AnalyticsTypeOverride"); // Write InstalledBuild.txt to indicate Engine is installed string InstalledBuildFile = CommandUtils.CombinePaths(OutputDir, "Engine/Build/InstalledBuild.txt"); CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(InstalledBuildFile)); CommandUtils.WriteAllText(InstalledBuildFile, ""); // Write InstalledBuild.txt to indicate Engine is installed string Project = ParseParamValue("Project"); if (Project != null) { string InstalledProjectBuildFile = CommandUtils.CombinePaths(OutputDir, "Engine/Build/InstalledProjectBuild.txt"); CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(InstalledProjectBuildFile)); CommandUtils.WriteAllText(InstalledProjectBuildFile, new FileReference(Project).MakeRelativeTo(new DirectoryReference(OutputDir))); } string OutputEnginePath = Path.Combine(OutputDir, "Engine"); string OutputBaseEnginePath = Path.Combine(OutputEnginePath, "Config", "BaseEngine.ini"); FileAttributes OutputAttributes = FileAttributes.ReadOnly; List <String> IniLines = new List <String>(); // Should always exist but if not, we don't need extra line if (File.Exists(OutputBaseEnginePath)) { OutputAttributes = File.GetAttributes(OutputBaseEnginePath); IniLines.Add(""); } else { CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(OutputBaseEnginePath)); CommandUtils.WriteAllText(OutputBaseEnginePath, ""); OutputAttributes = File.GetAttributes(OutputBaseEnginePath) | OutputAttributes; } // Create list of platform configurations installed in a Rocket build List <InstalledPlatformInfo.InstalledPlatformConfiguration> InstalledConfigs = new List <InstalledPlatformInfo.InstalledPlatformConfiguration>(); // Add the editor platform, otherwise we'll never be able to run UAT string EditorArchitecture = PlatformExports.GetDefaultArchitecture(HostPlatform.Current.HostEditorPlatform, null); InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(UnrealTargetConfiguration.Development, HostPlatform.Current.HostEditorPlatform, TargetRules.TargetType.Editor, EditorArchitecture, "", EProjectType.Unknown, false)); InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(UnrealTargetConfiguration.DebugGame, HostPlatform.Current.HostEditorPlatform, TargetRules.TargetType.Editor, EditorArchitecture, "", EProjectType.Unknown, false)); foreach (UnrealTargetPlatform CodeTargetPlatform in UnrealTargetPlatform.GetValidPlatforms()) { if (PlatformExports.IsPlatformAvailable(CodeTargetPlatform)) { string Architecture = PlatformExports.GetDefaultArchitecture(CodeTargetPlatform, null); // Try to parse additional Architectures from the command line string Architectures = ParseParamValue(CodeTargetPlatform.ToString() + "Architectures"); string GPUArchitectures = ParseParamValue(CodeTargetPlatform.ToString() + "GPUArchitectures"); // Build a list of pre-compiled architecture combinations for this platform if any List <string> AllArchNames; if (!String.IsNullOrWhiteSpace(Architectures) && !String.IsNullOrWhiteSpace(GPUArchitectures)) { AllArchNames = (from Arch in Architectures.Split('+') from GPUArch in GPUArchitectures.Split('+') select "-" + Arch + "-" + GPUArch).ToList(); } else if (!String.IsNullOrWhiteSpace(Architectures)) { AllArchNames = Architectures.Split('+').ToList(); } // if there aren't any, use the default else { AllArchNames = new List <string>() { Architecture }; } // Check whether this platform should only be used for content based projects EProjectType ProjectType = ContentOnlyPlatforms.Contains(CodeTargetPlatform) ? EProjectType.Content : EProjectType.Any; // Allow Content only platforms to be shown as options in all projects bool bCanBeDisplayed = ProjectType == EProjectType.Content; foreach (UnrealTargetConfiguration CodeTargetConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration))) { Dictionary <String, TargetType> Targets = new Dictionary <string, TargetType>() { { "UE4Game", TargetType.Game }, { "UE4Client", TargetType.Client }, { "UE4Server", TargetType.Server } }; foreach (KeyValuePair <string, TargetType> Target in Targets) { string CurrentTargetName = Target.Key; TargetType CurrentTargetType = Target.Value; // Need to check for development receipt as we use that for the Engine code in DebugGame UnrealTargetConfiguration EngineConfiguration = (CodeTargetConfiguration == UnrealTargetConfiguration.DebugGame) ? UnrealTargetConfiguration.Development : CodeTargetConfiguration; // Android has multiple architecture flavors built without receipts, so use the default arch target instead if (CodeTargetPlatform == UnrealTargetPlatform.Android) { FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(new DirectoryReference(OutputEnginePath), CurrentTargetName, CodeTargetPlatform, EngineConfiguration, Architecture); if (FileReference.Exists(ReceiptFileName)) { // Strip the output folder so that this can be used on any machine string RelativeReceiptFileName = ReceiptFileName.MakeRelativeTo(new DirectoryReference(OutputDir)); // Blindly append all of the architecture names if (AllArchNames.Count > 0) { foreach (string Arch in AllArchNames) { InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, CurrentTargetType, Arch, RelativeReceiptFileName, ProjectType, bCanBeDisplayed)); } } // if for some reason we didn't specify any flavors, just add the default one. else { InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, CurrentTargetType, Architecture, RelativeReceiptFileName, ProjectType, bCanBeDisplayed)); } } } // If we're not Android, check the existence of the target receipts for each architecture specified. else { foreach (string Arch in AllArchNames) { FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(new DirectoryReference(OutputEnginePath), CurrentTargetName, CodeTargetPlatform, EngineConfiguration, Arch); if (FileReference.Exists(ReceiptFileName)) { string RelativeReceiptFileName = ReceiptFileName.MakeRelativeTo(new DirectoryReference(OutputDir)); InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, CurrentTargetType, Arch, RelativeReceiptFileName, ProjectType, bCanBeDisplayed)); } } } } } } } UnrealBuildTool.InstalledPlatformInfo.WriteConfigFileEntries(InstalledConfigs, ref IniLines); if (!String.IsNullOrEmpty(AnalyticsTypeOverride)) { // Write Custom Analytics type setting IniLines.Add(""); IniLines.Add("[Analytics]"); IniLines.Add(String.Format("UE4TypeOverride=\"{0}\"", AnalyticsTypeOverride)); } // Make sure we can write to the the config file File.SetAttributes(OutputBaseEnginePath, OutputAttributes & ~FileAttributes.ReadOnly); File.AppendAllLines(OutputBaseEnginePath, IniLines); File.SetAttributes(OutputBaseEnginePath, OutputAttributes); }
/// <summary> /// Writes a preprocessed build graph to a script file /// </summary> /// <param name="File">The file to load</param> /// <param name="SchemaFile">Schema file for validation</param> public void Write(FileReference File, FileReference SchemaFile) { XmlWriterSettings Settings = new XmlWriterSettings(); Settings.Indent = true; Settings.IndentChars = "\t"; using (XmlWriter Writer = XmlWriter.Create(File.FullName, Settings)) { Writer.WriteStartElement("BuildGraph", "http://www.epicgames.com/BuildGraph"); if (SchemaFile != null) { Writer.WriteAttributeString("schemaLocation", "http://www.w3.org/2001/XMLSchema-instance", "http://www.epicgames.com/BuildGraph " + SchemaFile.MakeRelativeTo(File.Directory)); } foreach (Agent Agent in Agents) { Agent.Write(Writer, null); } foreach (ManualTrigger ControllingTrigger in Agents.SelectMany(x => x.Nodes).Where(x => x.ControllingTrigger != null).Select(x => x.ControllingTrigger).Distinct()) { Writer.WriteStartElement("Trigger"); Writer.WriteAttributeString("Name", ControllingTrigger.QualifiedName); foreach (Agent Agent in Agents) { Agent.Write(Writer, ControllingTrigger); } Writer.WriteEndElement(); } foreach (KeyValuePair<string, Node[]> Aggregate in AggregateNameToNodes) { Writer.WriteStartElement("Aggregate"); Writer.WriteAttributeString("Name", Aggregate.Key); Writer.WriteAttributeString("Requires", String.Join(";", Aggregate.Value.Select(x => x.Name))); Writer.WriteEndElement(); } foreach (Report Report in NameToReport.Values) { Writer.WriteStartElement("Report"); Writer.WriteAttributeString("Name", Report.Name); Writer.WriteAttributeString("Requires", String.Join(";", Report.Nodes.Select(x => x.Name))); Writer.WriteEndElement(); } foreach (Badge Badge in Badges) { Writer.WriteStartElement("Badge"); Writer.WriteAttributeString("Name", Badge.Name); if (Badge.Project != null) { Writer.WriteAttributeString("Project", Badge.Project); } Writer.WriteAttributeString("Requires", String.Join(";", Badge.Nodes.Select(x => x.Name))); Writer.WriteEndElement(); } Writer.WriteEndElement(); } }
/// <summary> /// Find the shortest relative path of the given file from a set of base directories. /// </summary> /// <param name="File">Full path to a file</param> /// <param name="RebaseDirs">Possible base directories</param> /// <returns>The shortest relative path, or null if the file is not under any of them</returns> public static string FindShortestRelativePath(FileReference File, IEnumerable<DirectoryReference> RebaseDirs) { string RelativePath = null; foreach(DirectoryReference RebaseDir in RebaseDirs) { if(File.IsUnderDirectory(RebaseDir)) { string NewRelativePath = File.MakeRelativeTo(RebaseDir); if(RelativePath == null || NewRelativePath.Length < RelativePath.Length) { RelativePath = NewRelativePath; } } } return RelativePath; }
public virtual List <string> GetExecutableNames(DeploymentContext SC, bool bIsRun = false) { var ExecutableNames = new List <String>(); string Ext = AutomationTool.Platform.GetExeExtension(SC.StageTargetPlatform.TargetPlatformType); if (!String.IsNullOrEmpty(SC.CookPlatform)) { if (SC.StageTargets.Count() > 0) { DirectoryReference ProjectRoot = new DirectoryReference(SC.ProjectRoot); foreach (StageTarget Target in SC.StageTargets) { foreach (BuildProduct Product in Target.Receipt.BuildProducts) { if (Product.Type == BuildProductType.Executable) { FileReference BuildProductFile = new FileReference(Product.Path); if (BuildProductFile.IsUnderDirectory(ProjectRoot)) { ExecutableNames.Add(CombinePaths(SC.RuntimeProjectRootDir, BuildProductFile.MakeRelativeTo(ProjectRoot))); } else { ExecutableNames.Add(CombinePaths(SC.RuntimeRootDir, BuildProductFile.MakeRelativeTo(RootDirectory))); } } } } } //@todo, probably the rest of this can go away once everything passes it through else if (SC.DedicatedServer) { if (!SC.IsCodeBasedProject) { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName("UE4Server"); ExecutableNames.Add(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir, ExeName + Ext)); } else { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName(SC.ShortProjectName + "Server"); string ClientApp = CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir, ExeName + Ext); var TestApp = CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir, SC.ShortProjectName + "Server" + Ext); string Game = "Game"; //@todo, this is sketchy, someone might ask what the exe is before it is compiled if (!FileExists_NoExceptions(ClientApp) && !FileExists_NoExceptions(TestApp) && SC.ShortProjectName.EndsWith(Game, StringComparison.InvariantCultureIgnoreCase)) { ExeName = SC.StageTargetPlatform.GetPlatformExecutableName(SC.ShortProjectName.Substring(0, SC.ShortProjectName.Length - Game.Length) + "Server"); ClientApp = CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir, ExeName + Ext); } ExecutableNames.Add(ClientApp); } } else { if (!SC.IsCodeBasedProject) { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName("UE4Game"); ExecutableNames.Add(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir, ExeName + Ext)); } else { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName(SC.ShortProjectName); ExecutableNames.Add(CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir, ExeName + Ext)); } } } else { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName("UE4Editor"); ExecutableNames.Add(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir, ExeName + Ext)); } return(ExecutableNames); }
/// <summary> /// Constructor /// </summary> /// <param name="FileInfo">File to be added</param> /// <param name="RootDir">Root directory to store paths relative to</param> public TempStorageFile(FileInfo FileInfo, DirectoryReference RootDir) { // Check the file exists and is in the right location FileReference File = new FileReference(FileInfo); if(!File.IsUnderDirectory(RootDir)) { throw new AutomationException("Attempt to add file to temp storage manifest that is outside the root directory ({0})", File.FullName); } if(!FileInfo.Exists) { throw new AutomationException("Attempt to add file to temp storage manifest that does not exist ({0})", File.FullName); } RelativePath = File.MakeRelativeTo(RootDir).Replace(Path.DirectorySeparatorChar, '/'); LastWriteTimeUtcTicks = FileInfo.LastWriteTimeUtc.Ticks; Length = FileInfo.Length; }
/// <summary> /// Writes a preprocessed build graph to a script file /// </summary> /// <param name="File">The file to load</param> /// <param name="SchemaFile">Schema file for validation</param> public void Write(FileReference File, FileReference SchemaFile) { XmlWriterSettings Settings = new XmlWriterSettings(); Settings.Indent = true; Settings.IndentChars = "\t"; using (XmlWriter Writer = XmlWriter.Create(File.FullName, Settings)) { Writer.WriteStartElement("BuildGraph", "http://www.epicgames.com/BuildGraph"); if (SchemaFile != null) { Writer.WriteAttributeString("schemaLocation", "http://www.w3.org/2001/XMLSchema-instance", "http://www.epicgames.com/BuildGraph " + SchemaFile.MakeRelativeTo(File.Directory)); } foreach (Agent Agent in Agents) { Agent.Write(Writer, null); } foreach (ManualTrigger ControllingTrigger in Agents.SelectMany(x => x.Nodes).Where(x => x.ControllingTrigger != null).Select(x => x.ControllingTrigger).Distinct()) { Writer.WriteStartElement("Trigger"); Writer.WriteAttributeString("Name", ControllingTrigger.QualifiedName); foreach (Agent Agent in Agents) { Agent.Write(Writer, ControllingTrigger); } Writer.WriteEndElement(); } foreach (Aggregate Aggregate in NameToAggregate.Values) { // If the aggregate has no required elements, skip it. if (Aggregate.RequiredNodes.Count == 0) { continue; } Writer.WriteStartElement("Aggregate"); Writer.WriteAttributeString("Name", Aggregate.Name); Writer.WriteAttributeString("Requires", String.Join(";", Aggregate.RequiredNodes.Select(x => x.Name))); Writer.WriteEndElement(); } foreach (Label Label in Labels) { Writer.WriteStartElement("Label"); if (Label.DashboardCategory != null) { Writer.WriteAttributeString("Category", Label.DashboardCategory); } Writer.WriteAttributeString("Name", Label.DashboardName); Writer.WriteAttributeString("Requires", String.Join(";", Label.RequiredNodes.Select(x => x.Name))); HashSet <Node> IncludedNodes = new HashSet <Node>(Label.IncludedNodes); IncludedNodes.ExceptWith(Label.IncludedNodes.SelectMany(x => x.InputDependencies)); IncludedNodes.ExceptWith(Label.RequiredNodes); if (IncludedNodes.Count > 0) { Writer.WriteAttributeString("Include", String.Join(";", IncludedNodes.Select(x => x.Name))); } HashSet <Node> ExcludedNodes = new HashSet <Node>(Label.IncludedNodes); ExcludedNodes.UnionWith(Label.IncludedNodes.SelectMany(x => x.InputDependencies)); ExcludedNodes.ExceptWith(Label.IncludedNodes); ExcludedNodes.ExceptWith(ExcludedNodes.ToArray().SelectMany(x => x.InputDependencies)); if (ExcludedNodes.Count > 0) { Writer.WriteAttributeString("Exclude", String.Join(";", ExcludedNodes.Select(x => x.Name))); } Writer.WriteEndElement(); } foreach (Report Report in NameToReport.Values) { Writer.WriteStartElement("Report"); Writer.WriteAttributeString("Name", Report.Name); Writer.WriteAttributeString("Requires", String.Join(";", Report.Nodes.Select(x => x.Name))); Writer.WriteEndElement(); } foreach (Badge Badge in Badges) { Writer.WriteStartElement("Badge"); Writer.WriteAttributeString("Name", Badge.Name); if (Badge.Project != null) { Writer.WriteAttributeString("Project", Badge.Project); } if (Badge.Change != 0) { Writer.WriteAttributeString("Change", Badge.Change.ToString()); } Writer.WriteAttributeString("Requires", String.Join(";", Badge.Nodes.Select(x => x.Name))); Writer.WriteEndElement(); } Writer.WriteEndElement(); } }
/// <summary> /// Writes a preprocessed build graph to a script file /// </summary> /// <param name="File">The file to load</param> /// <param name="SchemaFile">Schema file for validation</param> public void Write(FileReference File, FileReference SchemaFile) { XmlWriterSettings Settings = new XmlWriterSettings(); Settings.Indent = true; Settings.IndentChars = "\t"; using (XmlWriter Writer = XmlWriter.Create(File.FullName, Settings)) { Writer.WriteStartElement("BuildGraph", "http://www.epicgames.com/BuildGraph"); if (SchemaFile != null) { Writer.WriteAttributeString("schemaLocation", "http://www.w3.org/2001/XMLSchema-instance", "http://www.epicgames.com/BuildGraph " + SchemaFile.MakeRelativeTo(File.Directory)); } foreach (Agent Agent in Agents) { Agent.Write(Writer, null); } foreach (ManualTrigger ControllingTrigger in Agents.SelectMany(x => x.Nodes).Where(x => x.ControllingTrigger != null).Select(x => x.ControllingTrigger).Distinct()) { Writer.WriteStartElement("Trigger"); Writer.WriteAttributeString("Name", ControllingTrigger.QualifiedName); foreach (Agent Agent in Agents) { Agent.Write(Writer, ControllingTrigger); } Writer.WriteEndElement(); } foreach (KeyValuePair <string, Node[]> Aggregate in AggregateNameToNodes) { Writer.WriteStartElement("Aggregate"); Writer.WriteAttributeString("Name", Aggregate.Key); Writer.WriteAttributeString("Requires", String.Join(";", Aggregate.Value.Select(x => x.Name))); Writer.WriteEndElement(); } foreach (Report Report in NameToReport.Values) { Writer.WriteStartElement("Report"); Writer.WriteAttributeString("Name", Report.Name); Writer.WriteAttributeString("Requires", String.Join(";", Report.Nodes.Select(x => x.Name))); Writer.WriteEndElement(); } foreach (Badge Badge in Badges) { Writer.WriteStartElement("Badge"); Writer.WriteAttributeString("Name", Badge.Name); if (Badge.Project != null) { Writer.WriteAttributeString("Project", Badge.Project); } if (Badge.Change != 0) { Writer.WriteAttributeString("Change", Badge.Change.ToString()); } Writer.WriteAttributeString("Requires", String.Join(";", Badge.Nodes.Select(x => x.Name))); Writer.WriteEndElement(); } Writer.WriteEndElement(); } }
public virtual List <FileReference> GetExecutableNames(DeploymentContext SC) { List <FileReference> ExecutableNames = new List <FileReference>(); foreach (StageTarget Target in SC.StageTargets) { foreach (BuildProduct Product in Target.Receipt.BuildProducts) { if (Product.Type == BuildProductType.Executable) { FileReference BuildProductFile = Product.Path; if (BuildProductFile.IsUnderDirectory(SC.ProjectRoot)) { ExecutableNames.Add(FileReference.Combine(SC.RuntimeProjectRootDir, BuildProductFile.MakeRelativeTo(SC.ProjectRoot))); } else { ExecutableNames.Add(FileReference.Combine(SC.RuntimeRootDir, BuildProductFile.MakeRelativeTo(RootDirectory))); } } } } return(ExecutableNames); }
/// <summary> /// Checks whether the given assembly is a publically distributed engine assembly. /// </summary> /// <param name="File">Assembly location</param> /// <returns>True if the assembly is distributed publically</returns> static bool IsPublicAssembly(FileReference File) { DirectoryReference EngineDirectory = UnrealBuildTool.UnrealBuildTool.EngineDirectory; if(File.IsUnderDirectory(EngineDirectory)) { string[] PathFragments = File.MakeRelativeTo(EngineDirectory).Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); if(PathFragments.All(x => !x.Equals("NotForLicensees", StringComparison.InvariantCultureIgnoreCase) && !x.Equals("NoRedist", StringComparison.InvariantCultureIgnoreCase))) { return true; } } return false; }