You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
GUBP High Level
* Temp Storage is zipped into a single archive per node now. This results in ~75% reduction in temp storage usage and network traffic, not to mention the per-file overhead.
* Temp Storage is in P:\\Builds\\{Game}\\TmpStore instead of P:\\Builds\\{Game}\\GUBP (to facilitate easier cleaning of this new structure).
* Temp Storage nodes are in subdirectories of {Branch}\\{CL}\\{NodeName} now instead of a flat directory structure that was hard to manually sift through.
GUBP Mid Level
* Removed -Store= and -StoreSuffix= test parameters.
* Added -NoZipTempStorage parameter to turn off temp storage zipping if necessary.
* Created GUBP.JobInfo class that collects info about the job as a whole to be passed around by GUBP. Mostly used by any code that need to interact with TempStorage.
* Created TempStorageNodeInfo that describes the necessary parameters to find the temp storage location for a node.
* Fully XML commented TempStorage.cs, and commented internals all major functions.
* Added a bunch of telemetry data for storing, retrieving, and cleaning shared temp storage.
UAT Mid Level
* Fixed a bug in Ionic.Zip that make ExtractAll() not work on Mono, checked in new DLLs.
* Added UAT parameter -UseLocalBuildStorage that allows you to test build storage stuff completely locally. Writes to Engine\\Saved\\LocalBuilds\\...
GUBP Low Level
* Refactored some GUBP startup code so temp vars would be limited in scope. Makes it easier to track the impact of refactoring these things.
* CullNodesForPreflight is only called for preflight builds.
* Refactored TempStorage.FindTempStorageManifests to use new TmpStore structure and harden the brittle string/path parsing it was doing. See the new TempStorage FindMatchingSharedTempStorageNodeCLs().
* Refactored TempStorage Saving and Loading to use XDocument instead of older XmlDocument. Removed a bunch of redundant checks.
* Use StripBaseDirectory and MakeRerootedFilePath to remove the brittle directory manipulation code. Directories no longer require a '/' at the end.
* Removed a few redundant caching layers in cleaning temp storage that try to ensure we don't clean a folder twice. None of them were necessary.
* Removed unused single-threaded copy code from temp storage.
* Updated Temp Storage unit test, and fully commented the logic behind it.
UAT Low Level
* UAT top level exception handler is now a single log line now to help parsers find the error.
* Removed several uses of FormatException as it doesn't display the entire exception chain, and is not as good as the default exception formatter.
* Removed ExceptionToString as it used FormatException, which was not a good precedent.
* Fixed several cases of exception propagation that was not properly chaining the inner exception.
* Refactored ThreadedCopyFiles to use Parallel.For because it was just as fast (if not faster) and much simpler to maintain.
* Removed the suffix from Robust_FileExists_NoExceptions because it's sole purpose in life WAS to throw exceptions!
* Added a bunch of XML doc comments to CommandUtils.
* Modernized some container manipulation and iteration to use IEnumerable and extension methods more appropriately.
* Added several @todos for other minor cleanup stuff that should happen eventually.
* Fixed some uses of String.Compare to use invariant culture.
#codereview:ben.marsh
[CL 2644846 by Wes Hunt in Main branch]
175 lines
7.1 KiB
C#
175 lines
7.1 KiB
C#
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using AutomationTool;
|
|
using UnrealBuildTool;
|
|
|
|
[Help("Builds a plugin, and packages it for distribution")]
|
|
[Help("Plugin", "Specify the path to the descriptor file for the plugin that should be packaged")]
|
|
[Help("NoHostPlatform", "Prevent compiling for the editor platform on the host")]
|
|
[Help("TargetPlatforms", "Specify a list of target platforms to build, separated by '+' characters (eg. -TargetPlatforms=Win32+Win64). Default is all the Rocket target platforms.")]
|
|
[Help("Package", "The path which the build artifacts should be packaged to, ready for distribution.")]
|
|
class BuildPlugin : BuildCommand
|
|
{
|
|
public override void ExecuteBuild()
|
|
{
|
|
// Get the plugin filename
|
|
string PluginFileName = ParseParamValue("Plugin");
|
|
if(PluginFileName == null)
|
|
{
|
|
throw new AutomationException("Plugin file name was not specified via the -plugin argument");
|
|
}
|
|
|
|
// Read the plugin
|
|
PluginDescriptor Plugin = PluginDescriptor.FromFile(PluginFileName);
|
|
|
|
// Clean the intermediate build directory
|
|
string IntermediateBuildDirectory = Path.Combine(Path.GetDirectoryName(PluginFileName), "Intermediate", "Build");
|
|
if(CommandUtils.DirectoryExists(IntermediateBuildDirectory))
|
|
{
|
|
CommandUtils.DeleteDirectory(IntermediateBuildDirectory);
|
|
}
|
|
|
|
// Get any additional arguments from the commandline
|
|
string AdditionalArgs = "";
|
|
if(ParseParam("Rocket"))
|
|
{
|
|
AdditionalArgs += " -Rocket";
|
|
}
|
|
|
|
// Build the host platforms
|
|
List<string> ReceiptFileNames = new List<string>();
|
|
UE4Build.BuildAgenda Agenda = new UE4Build.BuildAgenda();
|
|
UnrealTargetPlatform HostPlatform = BuildHostPlatform.Current.Platform;
|
|
if(!ParseParam("NoHostPlatform"))
|
|
{
|
|
AddPluginToAgenda(Agenda, PluginFileName, Plugin, "UE4Editor", TargetRules.TargetType.Editor, HostPlatform, UnrealTargetConfiguration.Development, ReceiptFileNames, AdditionalArgs);
|
|
}
|
|
|
|
// Add the game targets
|
|
List<UnrealTargetPlatform> TargetPlatforms = Rocket.RocketBuild.GetTargetPlatforms(this, HostPlatform);
|
|
foreach(UnrealTargetPlatform TargetPlatform in TargetPlatforms)
|
|
{
|
|
if(Rocket.RocketBuild.IsCodeTargetPlatform(HostPlatform, TargetPlatform))
|
|
{
|
|
AddPluginToAgenda(Agenda, PluginFileName, Plugin, "UE4Game", TargetRules.TargetType.Game, TargetPlatform, UnrealTargetConfiguration.Development, ReceiptFileNames, AdditionalArgs);
|
|
AddPluginToAgenda(Agenda, PluginFileName, Plugin, "UE4Game", TargetRules.TargetType.Game, TargetPlatform, UnrealTargetConfiguration.Shipping, ReceiptFileNames, AdditionalArgs);
|
|
}
|
|
}
|
|
|
|
// Build it
|
|
UE4Build Build = new UE4Build(this);
|
|
Build.Build(Agenda, InDeleteBuildProducts: true, InUpdateVersionFiles: false);
|
|
|
|
// Package the plugin to the output folder
|
|
string PackageDirectory = ParseParamValue("Package");
|
|
if(PackageDirectory != null)
|
|
{
|
|
List<BuildProduct> BuildProducts = GetBuildProductsFromReceipts(ReceiptFileNames);
|
|
PackagePlugin(PluginFileName, BuildProducts, PackageDirectory);
|
|
}
|
|
}
|
|
|
|
static void AddPluginToAgenda(UE4Build.BuildAgenda Agenda, string PluginFileName, PluginDescriptor Plugin, string TargetName, TargetRules.TargetType TargetType, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, List<string> ReceiptFileNames, string InAdditionalArgs)
|
|
{
|
|
// Find a list of modules that need to be built for this plugin
|
|
List<string> ModuleNames = new List<string>();
|
|
foreach(ModuleDescriptor Module in Plugin.Modules)
|
|
{
|
|
bool bBuildDeveloperTools = (TargetType == TargetRules.TargetType.Editor || TargetType == TargetRules.TargetType.Program);
|
|
bool bBuildEditor = (TargetType == TargetRules.TargetType.Editor);
|
|
if(Module.IsCompiledInConfiguration(Platform, TargetType, bBuildDeveloperTools, bBuildEditor))
|
|
{
|
|
ModuleNames.Add(Module.Name);
|
|
}
|
|
}
|
|
|
|
// Add these modules to the build agenda
|
|
if(ModuleNames.Count > 0)
|
|
{
|
|
string Arguments = String.Format("-plugin {0}", CommandUtils.MakePathSafeToUseWithCommandLine(PluginFileName));
|
|
foreach(string ModuleName in ModuleNames)
|
|
{
|
|
Arguments += String.Format(" -module {0}", ModuleName);
|
|
}
|
|
|
|
string ReceiptFileName = TargetReceipt.GetDefaultPath(Path.GetDirectoryName(PluginFileName), TargetName, Platform, Configuration, "");
|
|
Arguments += String.Format(" -receipt {0}", CommandUtils.MakePathSafeToUseWithCommandLine(ReceiptFileName));
|
|
ReceiptFileNames.Add(ReceiptFileName);
|
|
|
|
if(!String.IsNullOrEmpty(InAdditionalArgs))
|
|
{
|
|
Arguments += InAdditionalArgs;
|
|
}
|
|
|
|
Agenda.AddTarget(TargetName, Platform, Configuration, InAddArgs: Arguments);
|
|
}
|
|
}
|
|
|
|
static List<BuildProduct> GetBuildProductsFromReceipts(List<string> ReceiptFileNames)
|
|
{
|
|
List<BuildProduct> BuildProducts = new List<BuildProduct>();
|
|
foreach(string ReceiptFileName in ReceiptFileNames)
|
|
{
|
|
TargetReceipt Receipt = TargetReceipt.Read(ReceiptFileName);
|
|
BuildProducts.AddRange(Receipt.BuildProducts);
|
|
}
|
|
return BuildProducts;
|
|
}
|
|
|
|
static void PackagePlugin(string PluginFileName, List<BuildProduct> BuildProducts, string PackageDirectory)
|
|
{
|
|
// Clear the output directory
|
|
CommandUtils.DeleteDirectoryContents(PackageDirectory);
|
|
|
|
// Copy all the files to the output directory
|
|
List<string> MatchingFileNames = FilterPluginFiles(PluginFileName, BuildProducts);
|
|
foreach(string MatchingFileName in MatchingFileNames)
|
|
{
|
|
string SourceFileName = Path.Combine(Path.GetDirectoryName(PluginFileName), MatchingFileName);
|
|
string TargetFileName = Path.Combine(PackageDirectory, MatchingFileName);
|
|
CommandUtils.CopyFile(SourceFileName, TargetFileName);
|
|
CommandUtils.SetFileAttributes(TargetFileName, ReadOnly: false);
|
|
}
|
|
|
|
// Get the output plugin filename
|
|
string TargetPluginFileName = CommandUtils.MakeRerootedFilePath(Path.GetFullPath(PluginFileName), Path.GetDirectoryName(Path.GetFullPath(PluginFileName)), PackageDirectory);
|
|
PluginDescriptor NewDescriptor = PluginDescriptor.FromFile(TargetPluginFileName);
|
|
NewDescriptor.bEnabledByDefault = true;
|
|
NewDescriptor.bInstalled = true;
|
|
NewDescriptor.Save(TargetPluginFileName);
|
|
}
|
|
|
|
static List<string> FilterPluginFiles(string PluginFileName, List<BuildProduct> BuildProducts)
|
|
{
|
|
string PluginDirectory = Path.GetDirectoryName(PluginFileName);
|
|
|
|
// Set up the default filter
|
|
FileFilter Filter = new FileFilter();
|
|
Filter.AddRuleForFile(PluginFileName, PluginDirectory, FileFilterType.Include);
|
|
Filter.AddRuleForFiles(BuildProducts.Select(x => x.Path), PluginDirectory, FileFilterType.Include);
|
|
Filter.Include("/Resources/...");
|
|
Filter.Include("/Content/...");
|
|
Filter.Include("/Intermediate/Build/.../Inc/...");
|
|
Filter.Include("/Source/...");
|
|
|
|
// Add custom rules for each platform
|
|
string FilterFileName = Path.Combine(Path.GetDirectoryName(PluginFileName), "Config", "FilterPlugin.ini");
|
|
if(File.Exists(FilterFileName))
|
|
{
|
|
Filter.ReadRulesFromFile(FilterFileName, "FilterPlugin");
|
|
}
|
|
|
|
// Apply the standard exclusion rules
|
|
Filter.ExcludeConfidentialFolders();
|
|
Filter.ExcludeConfidentialPlatforms();
|
|
|
|
// Apply the filter to the plugin directory
|
|
return Filter.ApplyToDirectory(PluginDirectory, true);
|
|
}
|
|
}
|