You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
========================== MAJOR FEATURES + CHANGES ========================== Change 2986511 on 2016/05/23 by Ben.Marsh UdpMessaging: Force references to symbols in the files containing UDP automated tests. Since plugins are compiled into static libraries before being linked into the executable, the linker will exclude any object files which don't have any referenced symbols. In non-unity builds, or adaptive unity builds with modified test files, this results in the tests not being linked in. Change 2993274 on 2016/05/27 by Ben.Marsh Fix UGS enumerating deleted .target.cs files when trying to detect editor target name. Change 2994265 on 2016/05/31 by Ben.Marsh Add info about setting up CIS integration and zipped editor builds in UGS. Change 2994275 on 2016/05/31 by Ben.Marsh PR #2443: [Unreal Game Sync] Added -project so shortcut or script can hint at the project file to open. (Contributed by paulevans) Change 2994287 on 2016/05/31 by Ben.Marsh UnrealGameSync: Add information about how UGS self-patches and updates. Change 2996928 on 2016/06/01 by Ben.Marsh UnrealGameSync: Fix trying to sync files which are open for branch or move/add. They don't exist on the server yet. Change 2997619 on 2016/06/02 by Ben.Marsh UAT: Fix PRX files not being remapped on PS4. All non-UFS should be allowed to be remapped, and UFS files can be if we're not using a PAK file. Change 2999769 on 2016/06/03 by Ben.Marsh UBT: Fix codepaths which assume that the current user account has a personal folder. The SYSTEM account (which Jenkins defaults to using) does not. Change 3004879 on 2016/06/07 by Ben.Marsh Remove copy of AWSSDK in NotForLicensees folder. Change 3004902 on 2016/06/07 by Ben.Marsh UAT: Switch MCP to use version of AWSSDK that's not in a NotForLicensees folder. Change 3005892 on 2016/06/08 by Ben.Marsh Add the GitHub promotion to the UE4 binary release build. Change 3016241 on 2016/06/16 by Ben.Marsh UGS: Always sync version files at the same changelist as everything else (rather than head revision) Change 3016446 on 2016/06/16 by Ben.Marsh PR #2279: Use MSBuild instead of DevEnv for solution builds (Contributed by FineRedMist) Change 3016472 on 2016/06/16 by Ben.Marsh PR #2442: pointing to the pull requests page of the repo (Contributed by KrishMunot) Change 3017694 on 2016/06/17 by Ben.Marsh EC: Produce an error if trying to sync back to a changelist more than 30 days before the most recent change. Meant to catch errors in entered CL fields from the dashboard. Can be overridden by specifying --allow-old-change in the build arguments. Change 3017695 on 2016/06/17 by Ben.Marsh UBT: Use a well defined order for parsing configuration files, rather than ignoring one file if another has a newer timestamp. Prevents confusing behavior where settings can be present, but are completely ignored. Now prioritizes the BuildConfiguration.xml file in the My Documents/Unreal Engine/UnrealBuildTool, followed by the one in AppData/Roaming/Unreal Engine/UnrealBuildTool. Both are added to the Config section of the solution if present, under different folders. #jira UE-24271 Change 3017698 on 2016/06/17 by Ben.Marsh Rename the <MsBuild> task to <CsCompile>, highlighting the fact that it only actually works on .csproj files (and not .sln files or other project types). #jira UEB-664 Change 3017701 on 2016/06/17 by Ben.Marsh BuildGraph: Relax a lot of the restrictions relating to using output tags from nodes. Output tags may contain an arbitrary set of files, including files which are also in other tags or produced by other nodes, but will not be written to temp storage more than once. The default tagged set of files for a node (eg. #MyNodeName) now includes all build products produced by that node. Temp storage now separates the storing of build products from the tags which reference them. A TempStorageFileList object is written for each output tag, which includes a list of files as well as a list of the storage blocks referenced by it. When a node depends on a tag, the TempStorageFileList is read first and used to determine which storage blocks to read. All tasks now have overloaded functions for returning the tags which they modify and/or reference, and errors are produced if an existing tag is modified, or referenced without being added as an input dependency. Change 3017714 on 2016/06/17 by Ben.Marsh BuildGraph: Allow specifying multiple tag names in the 'Tag' attribute of build tasks (or 'With' attribute of the 'Tag' task). Change 3018007 on 2016/06/17 by Ben.Marsh UBT: Add sections to the target receipt listing files which are required to build using precompiled binaries (as previously generated using -generateexternalfilelist), and runtime dependencies that may be required when using precompiled binaries but aren't actually required for the current target (which previously had to be specified through InstalledEngineFilters.ini). Tested by running UBT with arguments "UE4Game Win64 Development -precompile -xgeexport" and examining target receipt. #jira UE-28761 Change 3018322 on 2016/06/17 by Ben.Marsh PR #2518: Improvements for Clang on Windows (Contributed by Mattiwatti) Change 3018365 on 2016/06/17 by Ben.Marsh Misc: Fixes for warnings compiling ShaderCompileWorker on Clang Change 3018397 on 2016/06/17 by Ben.Marsh UnrealVS: Add an UnrealVS command to run a single-file-compile with UBT Change 3019421 on 2016/06/20 by Ben.Marsh Fix compilation of FreeType on Clang for Windows - there's an fttypes.h header already in the Windows SDK, so use a relative include path instead. Change 3019423 on 2016/06/20 by Ben.Marsh PR #2518: Improvements for Clang on Windows (Contributed by Mattiwatti) Change 3020377 on 2016/06/20 by Ben.Marsh UBT: Fix strings not being escaped before writing to JSON files. Change 3020378 on 2016/06/20 by Ben.Marsh UBT: Exclude precompiled files from the target receipt which are outside the engine and project directories. We don't need SDK libs being added to the precompile list. Change 3020966 on 2016/06/21 by Ben.Marsh EC: Allow scheduling builds at a certain offset past midnight, using the schedule formatted like "Every 20m from 04:00", and add scheduled builds of target platforms for dev streams every 4 hours. Also make the meaning of "Editor Only" and "Editor, Tools & Monolithics" build names consistent between Dev streams and Main, and add a new "Editor, Tools, Monolithics & DDC" build type includes additional DDC build for //UE4/Main. #rb none #lockdown Nick.Penwarden [CL 3020980 by Ben Marsh in Main branch]
374 lines
13 KiB
C#
374 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Xml;
|
|
using UnrealBuildTool;
|
|
|
|
namespace AutomationTool
|
|
{
|
|
/// <summary>
|
|
/// Specifies validation that should be performed on a task parameter.
|
|
/// </summary>
|
|
public enum TaskParameterValidationType
|
|
{
|
|
/// <summary>
|
|
/// Allow any valid values for the field type.
|
|
/// </summary>
|
|
Default,
|
|
|
|
/// <summary>
|
|
/// A standard name; alphanumeric characters, plus underscore and space. Spaces at the start or end, or more than one in a row are prohibited.
|
|
/// </summary>
|
|
Name,
|
|
|
|
/// <summary>
|
|
/// A list of names separated by semicolons
|
|
/// </summary>
|
|
NameList,
|
|
|
|
/// <summary>
|
|
/// A tag name (a regular name with '#' prefix)
|
|
/// </summary>
|
|
Tag,
|
|
|
|
/// <summary>
|
|
/// A list of tag names separated by semicolons
|
|
/// </summary>
|
|
TagList,
|
|
|
|
/// <summary>
|
|
/// A standard name or tag name
|
|
/// </summary>
|
|
NameOrTag,
|
|
|
|
/// <summary>
|
|
/// A list of standard name or tag names separated by semicolons
|
|
/// </summary>
|
|
NameOrTagList,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attribute to mark parameters to a task, which should be read as XML attributes from the script file.
|
|
/// </summary>
|
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
|
public class TaskParameterAttribute : Attribute
|
|
{
|
|
/// <summary>
|
|
/// Whether the parameter can be omitted
|
|
/// </summary>
|
|
public bool Optional
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets additional restrictions on how this field is validated in the schema. Default is to allow any valid field type.
|
|
/// </summary>
|
|
public TaskParameterValidationType ValidationType
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attribute used to associate an XML element name with a parameter block that can be used to construct tasks
|
|
/// </summary>
|
|
[AttributeUsage(AttributeTargets.Class)]
|
|
public class TaskElementAttribute : Attribute
|
|
{
|
|
/// <summary>
|
|
/// Name of the XML element that can be used to denote this class
|
|
/// </summary>
|
|
public string Name;
|
|
|
|
/// <summary>
|
|
/// Type to be constructed from the deserialized element
|
|
/// </summary>
|
|
public Type ParametersType;
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="InName">Name of the XML element used to denote this object</param>
|
|
/// <param name="InParametersType">Type to be constructed from this object</param>
|
|
public TaskElementAttribute(string InName, Type InParametersType)
|
|
{
|
|
Name = InName;
|
|
ParametersType = InParametersType;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Base class for all custom build tasks
|
|
/// </summary>
|
|
public abstract class CustomTask
|
|
{
|
|
/// <summary>
|
|
/// Allow this task to merge with other tasks within the same node if it can. This can be useful to allow tasks to execute in parallel.
|
|
/// </summary>
|
|
/// <param name="OtherTasks">Other tasks that this task can merge with. If a merge takes place, the other tasks should be removed from the list.</param>
|
|
public virtual void Merge(List<CustomTask> OtherTasks)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Execute this node.
|
|
/// </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>Whether the task succeeded or not. Exiting with an exception will be caught and treated as a failure.</returns>
|
|
public abstract bool Execute(JobContext Job, HashSet<FileReference> BuildProducts, Dictionary<string, HashSet<FileReference>> TagNameToFileSet);
|
|
|
|
/// <summary>
|
|
/// Output this task out to an XML writer.
|
|
/// </summary>
|
|
public abstract void Write(XmlWriter Writer);
|
|
|
|
/// <summary>
|
|
/// Writes this task to an XML writer, using the given parameters object.
|
|
/// </summary>
|
|
/// <param name="Writer"></param>
|
|
/// <param name="Task"></param>
|
|
protected void Write(XmlWriter Writer, object Parameters)
|
|
{
|
|
TaskElementAttribute Element = GetType().GetCustomAttribute<TaskElementAttribute>();
|
|
Writer.WriteStartElement(Element.Name);
|
|
|
|
foreach (FieldInfo Field in Parameters.GetType().GetFields())
|
|
{
|
|
if (Field.MemberType == MemberTypes.Field)
|
|
{
|
|
TaskParameterAttribute ParameterAttribute = Field.GetCustomAttribute<TaskParameterAttribute>();
|
|
if (ParameterAttribute != null)
|
|
{
|
|
object Value = Field.GetValue(Parameters);
|
|
if (Value != null && Field.FieldType == typeof(bool) && (bool)Value == false)
|
|
{
|
|
Value = null;
|
|
}
|
|
if (Value != null)
|
|
{
|
|
Writer.WriteAttributeString(Field.Name, Value.ToString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Writer.WriteEndElement();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find all the tags which are used as inputs to this task
|
|
/// </summary>
|
|
/// <returns>The tag names which are read by this task</returns>
|
|
public abstract IEnumerable<string> FindConsumedTagNames();
|
|
|
|
/// <summary>
|
|
/// Find all the tags which are modified by this task
|
|
/// </summary>
|
|
/// <returns>The tag names which are modified by this task</returns>
|
|
public abstract IEnumerable<string> FindProducedTagNames();
|
|
|
|
/// <summary>
|
|
/// Adds tag names from a filespec
|
|
/// </summary>
|
|
/// <param name="Filespec">A filespec, as can be passed to ResolveFilespec</param>
|
|
/// <returns>Tag names from this filespec</returns>
|
|
protected IEnumerable<string> FindTagNamesFromFilespec(string Filespec)
|
|
{
|
|
if(!String.IsNullOrEmpty(Filespec))
|
|
{
|
|
string[] Patterns = SplitDelimitedList(Filespec);
|
|
foreach(string Pattern in Patterns)
|
|
{
|
|
if(Pattern.StartsWith("#"))
|
|
{
|
|
yield return Pattern;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enumerates tag names from a list
|
|
/// </summary>
|
|
/// <param name="Filespec">A filespec, as can be passed to ResolveFilespec</param>
|
|
/// <returns>Tag names from this filespec</returns>
|
|
protected IEnumerable<string> FindTagNamesFromList(string TagList)
|
|
{
|
|
if(!String.IsNullOrEmpty(TagList))
|
|
{
|
|
string[] TagNames = SplitDelimitedList(TagList);
|
|
foreach(string TagName in TagNames)
|
|
{
|
|
yield return TagName;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolves a single name to a file reference, resolving relative paths to the root of the current path.
|
|
/// </summary>
|
|
/// <param name="Name">Name of the file</param>
|
|
/// <returns>Fully qualified file reference</returns>
|
|
public static FileReference ResolveFile(string Name)
|
|
{
|
|
if(Path.IsPathRooted(Name))
|
|
{
|
|
return new FileReference(Name);
|
|
}
|
|
else
|
|
{
|
|
return new FileReference(Path.Combine(CommandUtils.CmdEnv.LocalRoot, Name));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolves a directory reference from the given string. Assumes the root directory is the root of the current branch.
|
|
/// </summary>
|
|
/// <param name="Name">Name of the directory. May be null or empty.</param>
|
|
/// <returns>The resolved directory</returns>
|
|
public static DirectoryReference ResolveDirectory(string Name)
|
|
{
|
|
if(String.IsNullOrEmpty(Name))
|
|
{
|
|
return CommandUtils.RootDirectory;
|
|
}
|
|
else if(Path.IsPathRooted(Name))
|
|
{
|
|
return new DirectoryReference(Name);
|
|
}
|
|
else
|
|
{
|
|
return DirectoryReference.Combine(CommandUtils.RootDirectory, Name);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds or adds a set containing files with the given tag
|
|
/// </summary>
|
|
/// <param name="Name">The tag name to return a set for. An leading '#' character is optional.</param>
|
|
/// <returns>Set of files</returns>
|
|
public static HashSet<FileReference> FindOrAddTagSet(Dictionary<string, HashSet<FileReference>> TagNameToFileSet, string TagName)
|
|
{
|
|
// Make sure the tag name contains a leading hash
|
|
if(!TagName.StartsWith("#"))
|
|
{
|
|
throw new AutomationException("Tag name does not start with a '#' character");
|
|
}
|
|
|
|
// Find the files which match this tag
|
|
HashSet<FileReference> Files;
|
|
if(!TagNameToFileSet.TryGetValue(TagName, out Files))
|
|
{
|
|
Files = new HashSet<FileReference>();
|
|
TagNameToFileSet.Add(TagName, Files);
|
|
}
|
|
|
|
// If we got a null reference, it's because the tag is not listed as an input for this node (see RunGraph.BuildSingleNode). Fill it in, but only with an error.
|
|
if(Files == null)
|
|
{
|
|
CommandUtils.LogError("Attempt to reference tag '{0}', which is not listed as a dependency of this node.", TagName);
|
|
Files = new HashSet<FileReference>();
|
|
TagNameToFileSet.Add(TagName, Files);
|
|
}
|
|
return Files;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolve a list of files, tag names or file specifications separated by semicolons. Supported entries may be:
|
|
/// a) The name of a tag set (eg. #CompiledBinaries)
|
|
/// b) Relative or absolute filenames
|
|
/// c) A simple file pattern (eg. Foo/*.cpp)
|
|
/// d) A full directory wildcard (eg. Engine/...)
|
|
/// Note that wildcards may only match the last fragment in a pattern, so matches like "/*/Foo.txt" and "/.../Bar.txt" are illegal.
|
|
/// </summary>
|
|
/// <param name="DefaultDirectory">The default directory to resolve relative paths to</param>
|
|
/// <param name="DelimitedPatterns">List of files, tag names, or file specifications to include separated by semicolons.</param>
|
|
/// <param name="TagNameToFileSet">Mapping of tag name to fileset, as passed to the Execute() method</param>
|
|
/// <returns>Set of matching files.</returns>
|
|
public static HashSet<FileReference> ResolveFilespec(DirectoryReference DefaultDirectory, string DelimitedPatterns, Dictionary<string, HashSet<FileReference>> TagNameToFileSet)
|
|
{
|
|
List<string> ExcludePatterns = new List<string>();
|
|
return ResolveFilespecWithExcludePatterns(DefaultDirectory, DelimitedPatterns, ExcludePatterns, TagNameToFileSet);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolve a list of files, tag names or file specifications separated by semicolons as above, but preserves any directory references for further processing.
|
|
/// </summary>
|
|
/// <param name="DefaultDirectory">The default directory to resolve relative paths to</param>
|
|
/// <param name="DelimitedPatterns">List of files, tag names, or file specifications to include separated by semicolons.</param>
|
|
/// <param name="ExcludePatterns">Set of patterns to apply to directory searches. This can greatly speed up enumeration by earlying out of recursive directory searches if large directories are excluded (eg. .../Intermediate/...).</param>
|
|
/// <param name="TagNameToFileSet">Mapping of tag name to fileset, as passed to the Execute() method</param>
|
|
/// <returns>Set of matching files.</returns>
|
|
public static HashSet<FileReference> ResolveFilespecWithExcludePatterns(DirectoryReference DefaultDirectory, string DelimitedPatterns, List<string> ExcludePatterns, Dictionary<string, HashSet<FileReference>> TagNameToFileSet)
|
|
{
|
|
// Split the argument into a list of patterns
|
|
string[] Patterns = SplitDelimitedList(DelimitedPatterns);
|
|
|
|
// Parse each of the patterns, and add the results into the given sets
|
|
HashSet<FileReference> Files = new HashSet<FileReference>();
|
|
foreach(string Pattern in Patterns)
|
|
{
|
|
// Check if it's a tag name
|
|
if(Pattern.StartsWith("#"))
|
|
{
|
|
Files.UnionWith(FindOrAddTagSet(TagNameToFileSet, Pattern));
|
|
continue;
|
|
}
|
|
|
|
// If it doesn't contain any wildcards, just add the pattern directly
|
|
int WildcardIdx = FileFilter.FindWildcardIndex(Pattern);
|
|
if(WildcardIdx == -1)
|
|
{
|
|
Files.Add(FileReference.Combine(DefaultDirectory, Pattern));
|
|
continue;
|
|
}
|
|
|
|
// Find the base directory for the search. We construct this in a very deliberate way including the directory separator itself, so matches
|
|
// against the OS root directory will resolve correctly both on Mac (where / is the filesystem root) and Windows (where / refers to the current drive).
|
|
int LastDirectoryIdx = Pattern.LastIndexOfAny(new char[]{ Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, WildcardIdx);
|
|
DirectoryReference BaseDir = DirectoryReference.Combine(DefaultDirectory, Pattern.Substring(0, LastDirectoryIdx + 1));
|
|
|
|
// Construct the absolute include pattern to match against, re-inserting the resolved base directory to construct a canonical path.
|
|
string IncludePattern = BaseDir.FullName.TrimEnd(new char[]{ Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }) + "/" + Pattern.Substring(LastDirectoryIdx + 1);
|
|
|
|
// Construct a filter and apply it to the directory
|
|
if(BaseDir.Exists())
|
|
{
|
|
FileFilter Filter = new FileFilter();
|
|
Filter.AddRule(IncludePattern, FileFilterType.Include);
|
|
Filter.AddRules(ExcludePatterns, FileFilterType.Exclude);
|
|
Files.UnionWith(Filter.ApplyToDirectory(BaseDir, BaseDir.FullName, true));
|
|
}
|
|
}
|
|
|
|
// If we have exclude rules, create and run a filter against all the output files to catch things that weren't added from an include
|
|
if(ExcludePatterns.Count > 0)
|
|
{
|
|
FileFilter Filter = new FileFilter(FileFilterType.Include);
|
|
Filter.AddRules(ExcludePatterns, FileFilterType.Exclude);
|
|
Files.RemoveWhere(x => !Filter.Matches(x.FullName));
|
|
}
|
|
return Files;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Splits a string separated by semicolons into a list, removing empty entries
|
|
/// </summary>
|
|
/// <param name="Text">The input string</param>
|
|
/// <returns>Array of the parsed items</returns>
|
|
public static string[] SplitDelimitedList(string Text)
|
|
{
|
|
return Text.Split(';').Select(x => x.Trim()).Where(x => x.Length > 0).ToArray();
|
|
}
|
|
}
|
|
}
|