2016-01-07 08:17:16 -05:00
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
// This software is provided "as-is," without any express or implied warranty.
// In no event shall the author, nor Epic Games, Inc. be held liable for any damages arising from the use of this software.
// This software will not be supported.
// Use at your own risk.
using System ;
using System.Threading ;
using System.Diagnostics ;
using UnrealBuildTool ;
using System.Reflection ;
2015-07-22 14:00:30 -04:00
using Tools.DotNETCommon ;
2015-08-06 15:55:44 -04:00
using System.IO ;
2014-03-14 14:13:41 -04:00
namespace AutomationTool
{
2014-08-29 12:25:29 -04:00
public class Program
2014-03-14 14:13:41 -04:00
{
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 2972140)
==========================
MAJOR FEATURES + CHANGES
==========================
Change 2959679 on 2016/04/28 by Ben.Marsh
UGS: Show the original author for changes with a #ROBOMERGE-AUTHOR tag.
Change 2959695 on 2016/04/28 by Ben.Marsh
UGS: Only filter out changes from by buildmachine that contain the string "CIS Counter".
Change 2960798 on 2016/04/29 by Ben.Marsh
Remove C++ version of ParallelExecutor. Now implemented in C# as part of UAT.
Change 2960928 on 2016/04/29 by Ben.Marsh
UGS: Change filter for buildmachine changes to only include rebuilt lightmaps.
Change 2963214 on 2016/05/02 by Ben.Marsh
BuildGraph: Allow specifying optional dependencies for a node, indicating that the build products from an upstream node are desired, but should not block the node from running.
Change 2964454 on 2016/05/03 by Ben.Marsh
Change PostBuildInfoTool to PostBadgeStatus, and add position-independent argument parsing.
Change 2964533 on 2016/05/03 by Ben.Marsh
BuildGraph: Add the ability to generate summary badges from BuildGraph scripts, which can be pushed into a separate database for consumption by UGS.
Change 2964852 on 2016/05/03 by Ben.Marsh
BuildGraph: Add a task which can submit a set of files to Perforce, optionally creating and using a different workspace to do so.
Change 2966856 on 2016/05/04 by Ben.Marsh
EC: Allow specifying a filter for the changes considered when looking for the most recent change. Allows filtering out content changes for UGS builds, code-only builds, etc...
Change 2966867 on 2016/05/04 by Ben.Marsh
EC: Restore code to always set time in CIS state; we never want large builds to trigger off their defined interval.
Change 2967504 on 2016/05/05 by Ben.Marsh
UAT: Make sure the intermediate directory exists before writing out the list of changes in StreamCopyDescription.
Change 2967778 on 2016/05/05 by Ben.Marsh
UAT: Detect the P4 environment by querying Perforce for the setting of P4PORT, rather than assuming it's set in an environment variable. Windows stores this setting in the registry rather than the environment, but it's also valid to be set via P4CONFIG.
Change 2967815 on 2016/05/05 by Ben.Marsh
EC: Copy the initial resource pool setting from the stream settings into an EC property
Change 2967873 on 2016/05/05 by Ben.Marsh
EC: Allow stream settings to be stored directly in /GUBP_V5/Streams/ rather than having to be in a child property sheet.
Change 2969294 on 2016/05/06 by Ben.Marsh
EC: Extend ConformResources command to allow updating the pools that resources are assigned to, and to limit the number of machines which are syncing at once. Also added new EC procedure to allow specifying these arguments.
Change 2969371 on 2016/05/06 by Ben.Marsh
EC: Allow overriding the stream and workspace identifier synced by the builders. Overriding the stream allows syncing a narrower view of files (eg. Dev-Main vs Main), and overriding the workspace identifier allows sharing a workspace between two streams.
Change 2970623 on 2016/05/09 by Ben.Marsh
UAT: Prevent Ctrl-C handler delegate from being garbage collected and failing to be triggered.
Change 2970627 on 2016/05/09 by Ben.Marsh
UAT: Don't limit the list of valid target platforms specified on the command line to just those that we have initialized. Ignoring the platform if the SDK is not installed is never what the user wants.
Change 2972140 on 2016/05/10 by Ben.Marsh
Change 'Engine, Tools and Monolithics' to include QAGame and Template editors, but exclude everything downstream of a trigger.
#lockdown Nick.Penwarden
[CL 2972146 by Ben Marsh in Main branch]
2016-05-10 08:49:41 -04:00
/// <summary>
/// Keep a persistent reference to the delegate for handling Ctrl-C events. Since it's passed to non-managed code, we have to prevent it from being garbage collected.
/// </summary>
static ProcessManager . CtrlHandlerDelegate CtrlHandlerDelegateInstance = CtrlHandler ;
2014-07-01 10:58:33 -04:00
[STAThread]
2014-08-29 12:25:29 -04:00
public static int Main ( )
2014-03-14 14:13:41 -04:00
{
2015-06-30 11:40:05 -04:00
var CommandLine = SharedUtils . ParseCommandLine ( ) ;
LogUtils . InitLogging ( CommandLine ) ;
2015-08-20 08:38:09 -04:00
ExitCode ReturnCode = ExitCode . Success ;
2015-06-30 11:40:05 -04:00
2015-08-20 08:38:09 -04:00
try
{
// ensure we can resolve any external assemblies as necessary.
AssemblyUtils . InstallAssemblyResolver ( Path . GetDirectoryName ( Assembly . GetEntryAssembly ( ) . GetOriginalLocation ( ) ) ) ;
HostPlatform . Initialize ( ) ;
2015-06-30 11:40:05 -04:00
2016-01-11 10:12:46 -05:00
Log . TraceVerbose ( "{2}: Running on {0} as a {1}-bit process." , HostPlatform . Current . GetType ( ) . Name , Environment . Is64BitProcess ? 64 : 32 , DateTime . UtcNow . ToString ( "o" ) ) ;
2014-03-14 14:13:41 -04:00
2015-08-20 08:38:09 -04:00
XmlConfigLoader . Init ( ) ;
2014-04-23 18:00:27 -04:00
2015-08-20 08:38:09 -04:00
// Log if we're running from the launcher
var ExecutingAssemblyLocation = Assembly . GetExecutingAssembly ( ) . Location ;
if ( string . Compare ( ExecutingAssemblyLocation , Assembly . GetEntryAssembly ( ) . GetOriginalLocation ( ) , StringComparison . OrdinalIgnoreCase ) ! = 0 )
{
Log . TraceVerbose ( "Executed from AutomationToolLauncher ({0})" , ExecutingAssemblyLocation ) ;
}
Log . TraceVerbose ( "CWD={0}" , Environment . CurrentDirectory ) ;
2014-03-14 14:13:41 -04:00
2015-08-20 08:38:09 -04:00
// Hook up exit callbacks
var Domain = AppDomain . CurrentDomain ;
Domain . ProcessExit + = Domain_ProcessExit ;
Domain . DomainUnload + = Domain_ProcessExit ;
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 2972140)
==========================
MAJOR FEATURES + CHANGES
==========================
Change 2959679 on 2016/04/28 by Ben.Marsh
UGS: Show the original author for changes with a #ROBOMERGE-AUTHOR tag.
Change 2959695 on 2016/04/28 by Ben.Marsh
UGS: Only filter out changes from by buildmachine that contain the string "CIS Counter".
Change 2960798 on 2016/04/29 by Ben.Marsh
Remove C++ version of ParallelExecutor. Now implemented in C# as part of UAT.
Change 2960928 on 2016/04/29 by Ben.Marsh
UGS: Change filter for buildmachine changes to only include rebuilt lightmaps.
Change 2963214 on 2016/05/02 by Ben.Marsh
BuildGraph: Allow specifying optional dependencies for a node, indicating that the build products from an upstream node are desired, but should not block the node from running.
Change 2964454 on 2016/05/03 by Ben.Marsh
Change PostBuildInfoTool to PostBadgeStatus, and add position-independent argument parsing.
Change 2964533 on 2016/05/03 by Ben.Marsh
BuildGraph: Add the ability to generate summary badges from BuildGraph scripts, which can be pushed into a separate database for consumption by UGS.
Change 2964852 on 2016/05/03 by Ben.Marsh
BuildGraph: Add a task which can submit a set of files to Perforce, optionally creating and using a different workspace to do so.
Change 2966856 on 2016/05/04 by Ben.Marsh
EC: Allow specifying a filter for the changes considered when looking for the most recent change. Allows filtering out content changes for UGS builds, code-only builds, etc...
Change 2966867 on 2016/05/04 by Ben.Marsh
EC: Restore code to always set time in CIS state; we never want large builds to trigger off their defined interval.
Change 2967504 on 2016/05/05 by Ben.Marsh
UAT: Make sure the intermediate directory exists before writing out the list of changes in StreamCopyDescription.
Change 2967778 on 2016/05/05 by Ben.Marsh
UAT: Detect the P4 environment by querying Perforce for the setting of P4PORT, rather than assuming it's set in an environment variable. Windows stores this setting in the registry rather than the environment, but it's also valid to be set via P4CONFIG.
Change 2967815 on 2016/05/05 by Ben.Marsh
EC: Copy the initial resource pool setting from the stream settings into an EC property
Change 2967873 on 2016/05/05 by Ben.Marsh
EC: Allow stream settings to be stored directly in /GUBP_V5/Streams/ rather than having to be in a child property sheet.
Change 2969294 on 2016/05/06 by Ben.Marsh
EC: Extend ConformResources command to allow updating the pools that resources are assigned to, and to limit the number of machines which are syncing at once. Also added new EC procedure to allow specifying these arguments.
Change 2969371 on 2016/05/06 by Ben.Marsh
EC: Allow overriding the stream and workspace identifier synced by the builders. Overriding the stream allows syncing a narrower view of files (eg. Dev-Main vs Main), and overriding the workspace identifier allows sharing a workspace between two streams.
Change 2970623 on 2016/05/09 by Ben.Marsh
UAT: Prevent Ctrl-C handler delegate from being garbage collected and failing to be triggered.
Change 2970627 on 2016/05/09 by Ben.Marsh
UAT: Don't limit the list of valid target platforms specified on the command line to just those that we have initialized. Ignoring the platform if the SDK is not installed is never what the user wants.
Change 2972140 on 2016/05/10 by Ben.Marsh
Change 'Engine, Tools and Monolithics' to include QAGame and Template editors, but exclude everything downstream of a trigger.
#lockdown Nick.Penwarden
[CL 2972146 by Ben Marsh in Main branch]
2016-05-10 08:49:41 -04:00
HostPlatform . Current . SetConsoleCtrlHandler ( CtrlHandlerDelegateInstance ) ;
2014-03-14 14:13:41 -04:00
2015-08-20 08:38:09 -04:00
var Version = AssemblyUtils . ExecutableVersion ;
Log . TraceVerbose ( "{0} ver. {1}" , Version . ProductName , Version . ProductVersion ) ;
2014-03-14 14:13:41 -04:00
2015-08-20 08:38:09 -04:00
// Don't allow simultaneous execution of AT (in the same branch)
2015-08-20 09:46:59 -04:00
ReturnCode = InternalUtils . RunSingleInstance ( MainProc , CommandLine ) ;
2014-03-14 14:13:41 -04:00
2015-08-20 08:38:09 -04:00
}
catch ( AutomationException Ex )
{
Log . TraceError ( "AutomationTool terminated with exception: {0}" , Ex ) ;
ReturnCode = Ex . ErrorCode ;
}
catch ( Exception Ex )
{
// Catch all exceptions and propagate the ErrorCode if we are given one.
Log . TraceError ( "AutomationTool terminated with exception: {0}" , Ex ) ;
ReturnCode = ExitCode . Error_Unknown ;
}
UBT Utils.cs (New logging system)
* Allows us to use built-in Trace providers (console, file, etc) directly and still use our custom formatting.
* Fat comments explaining why Trace.WriteXXX functions should not be used directly in our system.
* Fixes thread safety by using Trace.WriteXXX under the hood after formatting, which uses a global lock (except on Mono, where a bug appears to be preventing this. Simulating the call on that platform).
* No need for TraceEvent overloads, which saves us the extra parameter cruft.
* Removed non-varargs overloads of Log functions (technically a bit slower, but these are already small messages).
* No longer needed VerbosityFilter and ConsoleListener classes.
* Avoid calling GetSource() if we aren't outputting the source.
* Avoid formatting the string if it won't pass the verbosity level.
* Consolidated all of UAT and UBT options into this class, so they could fully share the implementation.
UBT BuildConfiguration.cs
* Added LogFilename (and --log=<file> arg) that enables logging to a file.
* Added static ctor guard that asserts if someone tries to read a config before we have loaded config files and parsed config-override commandlines. It's a poor man's hack, but better than nothing!
UBT UEBuildConfiguration.cs
* Same static ctor guard as above.
UBT UnrealBuildTools.cs (initialization refactoring)
* In general I tried to de-mystify some of the rationale behind our startup code via fat comments.
* Broke main into 3 stages:
1. "early code" that should not try to read a config value.
* Very little code here. Mostly setting the current directory.
* Does an early init of logging to ensure logging is around, but config values won't be ready.
2. "Init Configuration code" that loads config files and parses command lines that may override them.
* I isolated two locations in startup that parsed long sets of switches and moved ones that trivially affected BuildConfiguration and UEBuildConfiguration in here. Those two locations seemed to have mostly copies of the same switches, indicating serious param parsing issues at some point in time.
* This allows switches to override config files more easily than the patchwork of re-parsing that was currently used (particularly for -verbose).
* I did a cursory examination of later code that indicated this double (actually, triple) parsing was no longer necessary with the refactors above. Any insight into why things may have ended up this way would be helpful.
3. "Post Init code" that is actually the meat of UBT.
* I left this code largely untouched.
* Removed 2 of 3 different command line logging statements.
* Removed two redundant parses of config overrides (ParseBuildConfigurationFlags).
* Guarded all of main in a try/catch block to ensure no exceptions can leak from UBT without returning a valid error code. It ALMOST already did this, but only covered the part surrounded by the Mutex.
* There was a perplexing bit that redundantly called XmlConfigLoader.Reset<> (line 683) that I struggled to understand. It turns out UEBuildConfiguration was sensitive to the current directory being set before files were loaded, and the old code called XmlConfigLoader.Init() super early, which required it to be called again after the current directory was set (see UEBuldConfiguration.UEThirdPartySourceDirectory for the cause). After my changes, I verified as best I could that these calls are no longer needed and removed them.
XmlConfigLoader.cs
* Add support for Properties in XmlConfigLoader.
AutomationTool Program.cs
* Guard logging shutdown code in try/finally so it can't be missed.
AutomationTool Log.cs
* Uses new logging system from UBT
* Removed unnecessary classes (VerbosityFilter, AutomationConsoleTraceListener, and AutomationFileTraceListener)
* Console trace logic is handled by UBT code now, moved UTF8Output handling to InitLogging.
* A custom TraceListener for file logging was unnecessary.
* Logic to handle creating the log file and retry loops was move into InitLogging, and the result passed to a regular TextFileTraceListener.
* Logic to handle copying the log on shutdown was moved to a ShutdownLogging function.
#codereview:robert.manuszewski,michael.trepka,kellan.carr
[CL 2526245 by Wes Hunt in Main branch]
2015-04-26 18:19:28 -04:00
finally
{
2015-06-30 11:40:05 -04:00
// In all cases, do necessary shut down stuff, but don't let any additional exceptions leak out while trying to shut down.
// Make sure there's no directories on the stack.
NoThrow ( ( ) = > CommandUtils . ClearDirStack ( ) , "Clear Dir Stack" ) ;
// Try to kill process before app domain exits to leave the other KillAll call to extreme edge cases
NoThrow ( ( ) = > { if ( ShouldKillProcesses & & ! Utils . IsRunningOnMono ) ProcessManager . KillAll ( ) ; } , "Kill All Processes" ) ;
2015-08-20 08:38:09 -04:00
Log . TraceInformation ( "AutomationTool exiting with ExitCode={0} ({1})" , ( int ) ReturnCode , ReturnCode ) ;
2015-06-30 11:40:05 -04:00
// Can't use NoThrow here because the code logs exceptions. We're shutting down logging!
UBT Utils.cs (New logging system)
* Allows us to use built-in Trace providers (console, file, etc) directly and still use our custom formatting.
* Fat comments explaining why Trace.WriteXXX functions should not be used directly in our system.
* Fixes thread safety by using Trace.WriteXXX under the hood after formatting, which uses a global lock (except on Mono, where a bug appears to be preventing this. Simulating the call on that platform).
* No need for TraceEvent overloads, which saves us the extra parameter cruft.
* Removed non-varargs overloads of Log functions (technically a bit slower, but these are already small messages).
* No longer needed VerbosityFilter and ConsoleListener classes.
* Avoid calling GetSource() if we aren't outputting the source.
* Avoid formatting the string if it won't pass the verbosity level.
* Consolidated all of UAT and UBT options into this class, so they could fully share the implementation.
UBT BuildConfiguration.cs
* Added LogFilename (and --log=<file> arg) that enables logging to a file.
* Added static ctor guard that asserts if someone tries to read a config before we have loaded config files and parsed config-override commandlines. It's a poor man's hack, but better than nothing!
UBT UEBuildConfiguration.cs
* Same static ctor guard as above.
UBT UnrealBuildTools.cs (initialization refactoring)
* In general I tried to de-mystify some of the rationale behind our startup code via fat comments.
* Broke main into 3 stages:
1. "early code" that should not try to read a config value.
* Very little code here. Mostly setting the current directory.
* Does an early init of logging to ensure logging is around, but config values won't be ready.
2. "Init Configuration code" that loads config files and parses command lines that may override them.
* I isolated two locations in startup that parsed long sets of switches and moved ones that trivially affected BuildConfiguration and UEBuildConfiguration in here. Those two locations seemed to have mostly copies of the same switches, indicating serious param parsing issues at some point in time.
* This allows switches to override config files more easily than the patchwork of re-parsing that was currently used (particularly for -verbose).
* I did a cursory examination of later code that indicated this double (actually, triple) parsing was no longer necessary with the refactors above. Any insight into why things may have ended up this way would be helpful.
3. "Post Init code" that is actually the meat of UBT.
* I left this code largely untouched.
* Removed 2 of 3 different command line logging statements.
* Removed two redundant parses of config overrides (ParseBuildConfigurationFlags).
* Guarded all of main in a try/catch block to ensure no exceptions can leak from UBT without returning a valid error code. It ALMOST already did this, but only covered the part surrounded by the Mutex.
* There was a perplexing bit that redundantly called XmlConfigLoader.Reset<> (line 683) that I struggled to understand. It turns out UEBuildConfiguration was sensitive to the current directory being set before files were loaded, and the old code called XmlConfigLoader.Init() super early, which required it to be called again after the current directory was set (see UEBuldConfiguration.UEThirdPartySourceDirectory for the cause). After my changes, I verified as best I could that these calls are no longer needed and removed them.
XmlConfigLoader.cs
* Add support for Properties in XmlConfigLoader.
AutomationTool Program.cs
* Guard logging shutdown code in try/finally so it can't be missed.
AutomationTool Log.cs
* Uses new logging system from UBT
* Removed unnecessary classes (VerbosityFilter, AutomationConsoleTraceListener, and AutomationFileTraceListener)
* Console trace logic is handled by UBT code now, moved UTF8Output handling to InitLogging.
* A custom TraceListener for file logging was unnecessary.
* Logic to handle creating the log file and retry loops was move into InitLogging, and the result passed to a regular TextFileTraceListener.
* Logic to handle copying the log on shutdown was moved to a ShutdownLogging function.
#codereview:robert.manuszewski,michael.trepka,kellan.carr
[CL 2526245 by Wes Hunt in Main branch]
2015-04-26 18:19:28 -04:00
LogUtils . ShutdownLogging ( ) ;
}
2014-05-14 14:52:20 -04:00
2015-06-30 11:40:05 -04:00
// STOP: No code beyond the return statement should go beyond this point!
// Nothing should happen after the finally block above is finished.
return ( int ) ReturnCode ;
}
2014-03-14 14:13:41 -04:00
2015-06-30 11:40:05 -04:00
/// <summary>
/// Wraps an action in an exception block.
/// Ensures individual actions can be performed and exceptions won't prevent further actions from being executed.
/// Useful for shutdown code where shutdown may be in several stages and it's important that all stages get a chance to run.
/// </summary>
/// <param name="Action"></param>
private static void NoThrow ( System . Action Action , string ActionDesc )
{
try
{
Action ( ) ;
}
catch ( Exception Ex )
{
2015-07-23 14:51:46 -04:00
Log . TraceError ( "Exception performing nothrow action \"{0}\": {1}" , ActionDesc , LogUtils . FormatException ( Ex ) ) ;
2015-06-30 11:40:05 -04:00
}
}
static bool CtrlHandler ( CtrlTypes EventType )
2014-03-14 14:13:41 -04:00
{
Domain_ProcessExit ( null , null ) ;
if ( EventType = = CtrlTypes . CTRL_C_EVENT )
{
// Force exit
Environment . Exit ( 3 ) ;
2014-05-14 14:52:20 -04:00
}
2014-03-14 14:13:41 -04:00
return true ;
}
static void Domain_ProcessExit ( object sender , EventArgs e )
{
2014-05-14 14:52:20 -04:00
// Kill all spawned processes (Console instead of Log because logging is closed at this time anyway)
2015-02-27 15:47:09 -05:00
if ( ShouldKillProcesses & & ! Utils . IsRunningOnMono )
2014-04-23 18:25:41 -04:00
{
2014-03-14 14:13:41 -04:00
ProcessManager . KillAll ( ) ;
}
Trace . Close ( ) ;
}
2015-08-20 09:46:59 -04:00
static ExitCode MainProc ( object Param )
2014-03-14 14:13:41 -04:00
{
2015-08-20 09:46:59 -04:00
ExitCode Result = Automation . Process ( ( string [ ] ) Param ) ;
2014-03-14 14:13:41 -04:00
ShouldKillProcesses = Automation . ShouldKillProcesses ;
2015-08-20 09:46:59 -04:00
return Result ;
2014-03-14 14:13:41 -04:00
}
static bool ShouldKillProcesses = true ;
}
}