Files
UnrealEngineUWP/Engine/Source/Programs/AutomationTool/Scripts/BuildPluginCommand.Automation.cs
Ben Marsh 92ec2b8239 Copying //UE4/Dev-Build to Dev-Main (//UE4/Dev-Main)
==========================
MAJOR FEATURES + CHANGES
==========================

Change 2718441 on 2015/10/06 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Allow nodes to be added with an "explicit" frequency, meaning that they'll only be part of manually triggered builds (not CIS).

Change 2718698 on 2015/10/06 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Add a type of node that can execute an arbitrary sequence of tasks, and allow constructing graphs of such nodes from an XML file.

Change 2723013 on 2015/10/09 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Small utility to quickly capture a workspace, or delete files to restore the workspace to a previously captured state (and output a p4 sync list to restore it)

Change 2744521 on 2015/10/28 by Matthew.Griffin@Matthew.Griffin_G5772_BuildStream

	Adding config entries to determine which platforms/configurations are available

	Currently only written out as part of the Rocket Build process but could be done elsewhere for other types of installed build.

	A near identical singleton class is used in both C++ and C# to load the config section and check whether configuration/platform combinations are valid.

Change 2773723 on 2015/11/19 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Copying UnrealGameSync into Engine/Source/Programs.

Change 2773914 on 2015/11/19 by Ben.Marsh@Ben.Marsh_T3245_Stream

	PR #1687: [GitDependencies] New feature: ignore file support (.gitdepsignore) (Contributed by nbjk667)

Change 2775317 on 2015/11/20 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Add a -listtps option to UBT, which will find all the TPS files in any directory that's compiled into a target.

Change 2780832 on 2015/11/25 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Allow compiling a single file in UBT. Pass -singlefile=<Path> on command line to UBT to use.

Change 2781071 on 2015/11/25 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Precompile all valid engine modules for Rocket by default. Modules may set the PrecompileForTargets field to control which configurations they should be compiled for. Modules which currently fail to compile have this set to
PrecompileTargetsType.None.

	#codereview Matthew.Griffin

Change 2784469 on 2015/12/01 by Matthew.Griffin@Matthew.Griffin_G5772_BuildStream

	Added -FastPDB commandline parameter for UBT, so that we can make use of the /DEBUG:FASTLINK option in VS2015

Change 2784722 on 2015/12/01 by Matthew.Griffin@Matthew.Griffin_G5772_BuildStream

	Made -FastPDB option part of BuildConfiguration instead of checking commandline at each place it's used. Also added option to override if someone doesn't want it automatically added to their project files.

Change 2787501 on 2015/12/02 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Restore change to gather VC environment directly from registry.

#lockdown Nick.Penwarden

[CL 2790002 by Ben Marsh in Main branch]
2015-12-04 09:32:58 -05:00

176 lines
7.2 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(new FileReference(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 = "";
// 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;
if(!TargetReceipt.TryRead(ReceiptFileName, out Receipt))
{
throw new AutomationException("Missing or invalid target receipt ({0})", 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(new FileReference(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("/Binaries/ThirdParty/...");
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);
}
}